From bc132f8e85aa07ab7fd149f7a1f4a96bb4d617cb Mon Sep 17 00:00:00 2001 From: Hare Date: Sun, 8 Feb 2026 17:04:26 +0900 Subject: [PATCH] init --- .editorconfig | 4 ++ .gitattributes | 2 + .gitignore | 3 ++ game.tscn | 65 +++++++++++++++++++++++++++++ icon.svg | 1 + icon.svg.import | 44 ++++++++++++++++++++ project.godot | 23 ++++++++++ scripts/camera_targeter.gd | 74 +++++++++++++++++++++++++++++++++ scripts/camera_targeter.gd.uid | 1 + scripts/physics_movement.gd | 73 ++++++++++++++++++++++++++++++++ scripts/physics_movement.gd.uid | 1 + 11 files changed, 291 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 game.tscn create mode 100644 icon.svg create mode 100644 icon.svg.import create mode 100644 project.godot create mode 100644 scripts/camera_targeter.gd create mode 100644 scripts/camera_targeter.gd.uid create mode 100644 scripts/physics_movement.gd create mode 100644 scripts/physics_movement.gd.uid diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f28239b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*] +charset = utf-8 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0af181c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# Godot 4+ specific ignores +.godot/ +/android/ diff --git a/game.tscn b/game.tscn new file mode 100644 index 0000000..93bf33b --- /dev/null +++ b/game.tscn @@ -0,0 +1,65 @@ +[gd_scene format=3 uid="uid://be0hdhgh4p8b2"] + +[ext_resource type="Script" uid="uid://d1hs43512acpp" path="res://scripts/camera_targeter.gd" id="1_80nbo"] +[ext_resource type="Script" uid="uid://cwg212lk7rfi2" path="res://scripts/physics_movement.gd" id="2_e2o6t"] +[ext_resource type="Texture2D" uid="uid://cjcpbpcen2su3" path="res://icon.svg" id="3_feb5d"] + +[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_e2o6t"] +rough = true + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_mwb40"] +albedo_color = Color(0.26666668, 0.16078432, 0.08627451, 1) + +[sub_resource type="BoxMesh" id="BoxMesh_mwb40"] +material = SubResource("StandardMaterial3D_mwb40") +size = Vector3(20, 1, 20) + +[sub_resource type="BoxShape3D" id="BoxShape3D_80nbo"] +size = Vector3(20, 1, 20) + +[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_feb5d"] +rough = true +bounce = 0.1 + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_fc0e3"] +albedo_texture = ExtResource("3_feb5d") + +[sub_resource type="SphereMesh" id="SphereMesh_7jktm"] +material = SubResource("StandardMaterial3D_fc0e3") + +[sub_resource type="SphereShape3D" id="SphereShape3D_feb5d"] + +[node name="Node3D" type="Node3D" unique_id=1911957] + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="." unique_id=207332981] +transform = Transform3D(1, 0, 0, 0, 0.37640214, 0.9264564, 0, -0.9264564, 0.37640214, 0, 10.185568, 1.1867445) + +[node name="Camera3D" type="Camera3D" parent="." unique_id=1327314903 node_paths=PackedStringArray("target")] +transform = Transform3D(1, 0, 0, 0, 0.8711967, 0.49093416, 0, -0.49093416, 0.8711967, 0, 6.4932036, 7.1359625) +script = ExtResource("1_80nbo") +target = NodePath("../RigidBody3D") + +[node name="StaticBody3D" type="StaticBody3D" parent="." unique_id=751264409] +physics_material_override = SubResource("PhysicsMaterial_e2o6t") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="StaticBody3D" unique_id=86151585] +mesh = SubResource("BoxMesh_mwb40") +skeleton = NodePath("../..") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D" unique_id=433263418] +shape = SubResource("BoxShape3D_80nbo") + +[node name="RigidBody3D" type="RigidBody3D" parent="." unique_id=779206838 node_paths=PackedStringArray("camera")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5.177694, 0) +mass = 0.5 +physics_material_override = SubResource("PhysicsMaterial_feb5d") +angular_damp = 1.0 +script = ExtResource("2_e2o6t") +camera = NodePath("../Camera3D") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="RigidBody3D" unique_id=2053654807] +mesh = SubResource("SphereMesh_7jktm") +skeleton = NodePath("../..") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="RigidBody3D" unique_id=1975781434] +shape = SubResource("SphereShape3D_feb5d") diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..c6bbb7d --- /dev/null +++ b/icon.svg @@ -0,0 +1 @@ + diff --git a/icon.svg.import b/icon.svg.import new file mode 100644 index 0000000..2cea20b --- /dev/null +++ b/icon.svg.import @@ -0,0 +1,44 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cjcpbpcen2su3" +path.s3tc="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=0 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..b13d4a6 --- /dev/null +++ b/project.godot @@ -0,0 +1,23 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[animation] + +compatibility/default_parent_skeleton_in_mesh_instance_3d=true + +[application] + +config/name="tento-plus-1" +config/features=PackedStringArray("4.6", "Forward Plus") +config/icon="res://icon.svg" + +[editor_plugins] + +enabled=PackedStringArray("res://addons/flexcam/plugin.cfg") diff --git a/scripts/camera_targeter.gd b/scripts/camera_targeter.gd new file mode 100644 index 0000000..f827924 --- /dev/null +++ b/scripts/camera_targeter.gd @@ -0,0 +1,74 @@ +extends Camera3D + +## ターゲットとなるNode3Dオブジェクト +@export var target: Node3D + +## カメラの回転感度 +@export var mouse_sensitivity: float = 0.003 + +## ターゲットからの距離 +@export var distance: float = 5.0 + +## 最小・最大距離 +@export var min_distance: float = 2.0 +@export var max_distance: float = 20.0 + +## ズーム速度 +@export var zoom_speed: float = 0.5 + +## 縦方向の回転制限(ラジアン) +@export var min_pitch: float = -PI / 2 + 0.1 +@export var max_pitch: float = PI / 2 - 0.1 + +## マウスボタン(右クリックでカメラ操作) +@export var rotate_button: MouseButton = MOUSE_BUTTON_RIGHT + +# 内部変数 +var _yaw: float = 0.0 # 水平回転 +var _pitch: float = 0.0 # 垂直回転 +var _is_rotating: bool = false + + +func _ready() -> void: + # 初期角度を設定 + if target: + var direction = global_position - target.global_position + _yaw = atan2(direction.x, direction.z) + _pitch = asin(direction.y / direction.length()) + + +func _unhandled_input(event: InputEvent) -> void: + # マウスボタンの押下/離す + if event is InputEventMouseButton: + if event.button_index == rotate_button: + _is_rotating = event.pressed + + # マウスホイールでズーム + elif event.button_index == MOUSE_BUTTON_WHEEL_UP: + distance = clamp(distance - zoom_speed, min_distance, max_distance) + elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN: + distance = clamp(distance + zoom_speed, min_distance, max_distance) + + # マウス移動で回転 + elif event is InputEventMouseMotion and _is_rotating: + _yaw -= event.relative.x * mouse_sensitivity + _pitch += event.relative.y * mouse_sensitivity + _pitch = clamp(_pitch, min_pitch, max_pitch) + + +func _process(_delta: float) -> void: + if not target: + return + + # 球面座標系でカメラ位置を計算 + var offset = Vector3( + cos(_pitch) * sin(_yaw), + sin(_pitch), + cos(_pitch) * cos(_yaw) + ) * distance + + # カメラ位置を設定 + global_position = target.global_position + offset + + # ターゲットを見る + look_at(target.global_position, Vector3.UP) diff --git a/scripts/camera_targeter.gd.uid b/scripts/camera_targeter.gd.uid new file mode 100644 index 0000000..0aa60ce --- /dev/null +++ b/scripts/camera_targeter.gd.uid @@ -0,0 +1 @@ +uid://d1hs43512acpp diff --git a/scripts/physics_movement.gd b/scripts/physics_movement.gd new file mode 100644 index 0000000..70059ea --- /dev/null +++ b/scripts/physics_movement.gd @@ -0,0 +1,73 @@ +extends RigidBody3D + +## 移動の基準となるカメラ +@export var camera: Camera3D + +## 移動加速度 +@export var move_force: float = 10.0 + +## ジャンプ力 +@export var jump_force: float = 8.0 + +## 空中での移動制御(0.0-1.0、1.0で地上と同じ) +@export var air_control: float = 0.3 + +## 地面判定用のレイキャスト距離 +@export var ground_check_distance: float = 0.6 + +# 内部変数 +var _is_on_ground: bool = false +var _ground_check_ray: RayCast3D + + +func _ready() -> void: + # 地面判定用のレイキャストを作成 + _ground_check_ray = RayCast3D.new() + _ground_check_ray.target_position = Vector3(0, -ground_check_distance, 0) + _ground_check_ray.enabled = true + add_child(_ground_check_ray) + + +func _physics_process(delta: float) -> void: + # レイキャストをグローバル座標系で下向きに固定 + _ground_check_ray.global_rotation = Vector3.ZERO + + # 地面判定 + _is_on_ground = _ground_check_ray.is_colliding() + + # 入力取得 + var input_dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") + + # カメラ基準の移動方向を計算 + var move_direction = _get_camera_relative_direction(input_dir) + + # 移動力を適用 + if move_direction.length() > 0: + var control_factor = air_control if not _is_on_ground else 1.0 + var force = move_direction * move_force * control_factor + apply_central_force(force) + + # ジャンプ + if Input.is_action_just_pressed("ui_accept") and _is_on_ground: + linear_velocity.y = jump_force + + +func _get_camera_relative_direction(input_dir: Vector2) -> Vector3: + + if not camera: + # カメラが設定されていない場合はワールド座標基準 + return Vector3(input_dir.x, 0, input_dir.y).normalized() + + # カメラの前方向と右方向を取得(Y軸は無視して水平面に射影) + var cam_forward = -camera.global_transform.basis.z + cam_forward.y = 0 + cam_forward = cam_forward.normalized() + + var cam_right = camera.global_transform.basis.x + cam_right.y = 0 + cam_right = cam_right.normalized() + + # 入力方向をカメラ基準に変換 + var direction = (cam_right * input_dir.x + cam_forward * -input_dir.y).normalized() + + return direction diff --git a/scripts/physics_movement.gd.uid b/scripts/physics_movement.gd.uid new file mode 100644 index 0000000..6f7f8dc --- /dev/null +++ b/scripts/physics_movement.gd.uid @@ -0,0 +1 @@ +uid://cwg212lk7rfi2