init
This commit is contained in:
commit
bc132f8e85
4
.editorconfig
Normal file
4
.editorconfig
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
# Normalize EOL for all files that Git considers text files.
|
||||
* text=auto eol=lf
|
||||
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Godot 4+ specific ignores
|
||||
.godot/
|
||||
/android/
|
||||
65
game.tscn
Normal file
65
game.tscn
Normal file
|
|
@ -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")
|
||||
1
icon.svg
Normal file
1
icon.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>
|
||||
|
After Width: | Height: | Size: 995 B |
44
icon.svg.import
Normal file
44
icon.svg.import
Normal file
|
|
@ -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
|
||||
23
project.godot
Normal file
23
project.godot
Normal file
|
|
@ -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")
|
||||
74
scripts/camera_targeter.gd
Normal file
74
scripts/camera_targeter.gd
Normal file
|
|
@ -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)
|
||||
1
scripts/camera_targeter.gd.uid
Normal file
1
scripts/camera_targeter.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://d1hs43512acpp
|
||||
73
scripts/physics_movement.gd
Normal file
73
scripts/physics_movement.gd
Normal file
|
|
@ -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
|
||||
1
scripts/physics_movement.gd.uid
Normal file
1
scripts/physics_movement.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://cwg212lk7rfi2
|
||||
Loading…
Reference in New Issue
Block a user