From 151a757e3e62da558cca5ba301048cccd34719fc Mon Sep 17 00:00:00 2001 From: Thayol Date: Sun, 23 Feb 2025 18:25:57 +0900 Subject: [PATCH] move to apply_input_velocity on the subject --- project.godot | 10 ++++++ scenes/chaser.tscn | 66 ++++++++++++++++++++++++++++-------- scenes/runner.tscn | 22 ++++++++---- scripts/in_game.gd | 5 ++- scripts/multiplayer/input.gd | 9 +++++ scripts/runner.gd | 29 +++++++++++----- scripts/states/dead.gd | 12 +++++++ scripts/states/fall.gd | 7 ++-- scripts/states/idle.gd | 8 ++--- scripts/states/lunge.gd | 11 ++++++ scripts/states/run.gd | 13 ++----- scripts/states/state.gd | 1 + scripts/states/walk.gd | 11 +----- 13 files changed, 142 insertions(+), 62 deletions(-) create mode 100644 scripts/states/dead.gd create mode 100644 scripts/states/lunge.gd diff --git a/project.godot b/project.godot index 4ed6e33..d6aa1ce 100644 --- a/project.godot +++ b/project.godot @@ -72,6 +72,16 @@ walk={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) ] } +primary_interact={ +"deadzone": 0.5, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(138, 4),"global_position":Vector2(147, 50),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null) +] +} +secondary_interact={ +"deadzone": 0.5, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":2,"position":Vector2(159, 23),"global_position":Vector2(168, 69),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null) +] +} [rendering] diff --git a/scenes/chaser.tscn b/scenes/chaser.tscn index dd12763..980165e 100644 --- a/scenes/chaser.tscn +++ b/scenes/chaser.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=17 format=3 uid="uid://dvqj0souma3mh"] +[gd_scene load_steps=21 format=3 uid="uid://dvqj0souma3mh"] [ext_resource type="Script" path="res://scripts/runner.gd" id="1_hjhpa"] [ext_resource type="Script" path="res://scripts/multiplayer/input.gd" id="2_ktv5u"] @@ -7,7 +7,8 @@ [ext_resource type="Script" path="res://scripts/states/idle.gd" id="5_vepvv"] [ext_resource type="Script" path="res://scripts/states/run.gd" id="6_fllo7"] [ext_resource type="Script" path="res://scripts/states/fall.gd" id="7_0e04j"] -[ext_resource type="Script" path="res://scripts/states/walk.gd" id="8_s1mx5"] +[ext_resource type="Script" path="res://scripts/states/dead.gd" id="9_8je4a"] +[ext_resource type="Script" path="res://scripts/states/lunge.gd" id="9_nqccg"] [sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_ukf45"] properties/0/path = NodePath(".:player_id") @@ -15,18 +16,24 @@ properties/0/spawn = true properties/0/replication_mode = 2 properties/1/path = NodePath(".:server_position") properties/1/spawn = true -properties/1/replication_mode = 2 +properties/1/replication_mode = 1 properties/2/path = NodePath(".:server_rotation") properties/2/spawn = true -properties/2/replication_mode = 2 +properties/2/replication_mode = 1 [sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_1agtp"] properties/0/path = NodePath("Input:direction") properties/0/spawn = true -properties/0/replication_mode = 2 -properties/1/path = NodePath("Input:walking") +properties/0/replication_mode = 1 +properties/1/path = NodePath("Input:walk") properties/1/spawn = true -properties/1/replication_mode = 2 +properties/1/replication_mode = 1 +properties/2/path = NodePath("Input:primary_interact") +properties/2/spawn = true +properties/2/replication_mode = 1 +properties/3/path = NodePath("Input:secondary_interact") +properties/3/spawn = true +properties/3/replication_mode = 1 [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_j6tb3"] radius = 0.3 @@ -42,6 +49,15 @@ height = 1.8 [sub_resource type="SphereMesh" id="SphereMesh_1gltg"] +[sub_resource type="BoxShape3D" id="BoxShape3D_rsamr"] +size = Vector3(1, 1.75, 1.5) + +[sub_resource type="BoxMesh" id="BoxMesh_phaav"] +size = Vector3(1, 1.75, 1.5) + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ssauw"] +albedo_color = Color(1, 0, 0, 1) + [sub_resource type="SphereShape3D" id="SphereShape3D_wsx1k"] [node name="Chaser" type="CharacterBody3D" node_paths=PackedStringArray("state_machine")] @@ -64,27 +80,43 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) shape = SubResource("CapsuleShape3D_j6tb3") -[node name="Skin" type="Node3D" parent="."] +[node name="RotationBase" type="Node3D" parent="."] unique_name_in_owner = true -[node name="MainBody" type="MeshInstance3D" parent="Skin"] +[node name="Skin" type="Node3D" parent="RotationBase"] +unique_name_in_owner = true + +[node name="MainBody" type="MeshInstance3D" parent="RotationBase/Skin"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) mesh = SubResource("CapsuleMesh_di3a0") -skeleton = NodePath("../..") +skeleton = NodePath("../../..") surface_material_override/0 = ExtResource("3_tvy4p") -[node name="Beak" type="MeshInstance3D" parent="Skin/MainBody"] +[node name="Beak" type="MeshInstance3D" parent="RotationBase/Skin/MainBody"] transform = Transform3D(0.35, 0, 0, 0, -0.105655, 0.0906308, 0, -0.226577, -0.0422618, 0, 0.45, -0.3) mesh = SubResource("PrismMesh_fcj1v") -[node name="RightEye" type="MeshInstance3D" parent="Skin/MainBody"] +[node name="RightEye" type="MeshInstance3D" parent="RotationBase/Skin/MainBody"] transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0.1, 0.6, -0.25) mesh = SubResource("SphereMesh_tudvv") -[node name="LeftEye" type="MeshInstance3D" parent="Skin/MainBody"] +[node name="LeftEye" type="MeshInstance3D" parent="RotationBase/Skin/MainBody"] transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, -0.1, 0.6, -0.25) mesh = SubResource("SphereMesh_1gltg") +[node name="Attack" type="Area3D" parent="RotationBase"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, -0.75) +monitoring = false +monitorable = false + +[node name="CollisionShape3D" type="CollisionShape3D" parent="RotationBase/Attack"] +shape = SubResource("BoxShape3D_rsamr") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="RotationBase/Attack"] +transparency = 0.8 +mesh = SubResource("BoxMesh_phaav") +surface_material_override/0 = SubResource("StandardMaterial3D_ssauw") + [node name="FloatingCamera" type="Node" parent="."] [node name="CameraPlatform" type="Node3D" parent="FloatingCamera"] @@ -113,8 +145,12 @@ script = ExtResource("6_fllo7") unique_name_in_owner = true script = ExtResource("7_0e04j") -[node name="Walk" type="Node" parent="StateMachine"] +[node name="Dead" type="Node" parent="StateMachine"] unique_name_in_owner = true -script = ExtResource("8_s1mx5") +script = ExtResource("9_8je4a") + +[node name="Lunge" type="Node" parent="StateMachine"] +unique_name_in_owner = true +script = ExtResource("9_nqccg") [connection signal="delta_synchronized" from="Sync" to="." method="_on_sync_delta_synchronized"] diff --git a/scenes/runner.tscn b/scenes/runner.tscn index e1cff05..8d071ba 100644 --- a/scenes/runner.tscn +++ b/scenes/runner.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=17 format=3 uid="uid://8esyynmieyog"] +[gd_scene load_steps=18 format=3 uid="uid://8esyynmieyog"] [ext_resource type="Script" path="res://scripts/runner.gd" id="1_d63rt"] [ext_resource type="Script" path="res://scripts/multiplayer/input.gd" id="2_xmliy"] @@ -8,6 +8,7 @@ [ext_resource type="Script" path="res://scripts/states/run.gd" id="6_1teax"] [ext_resource type="Script" path="res://scripts/states/fall.gd" id="7_jfat4"] [ext_resource type="Script" path="res://scripts/states/walk.gd" id="8_phh70"] +[ext_resource type="Script" path="res://scripts/states/dead.gd" id="9_bw4yb"] [sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_ukf45"] properties/0/path = NodePath(".:player_id") @@ -70,24 +71,27 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) shape = SubResource("CapsuleShape3D_j6tb3") -[node name="Skin" type="Node3D" parent="."] +[node name="RotationBase" type="Node3D" parent="."] unique_name_in_owner = true -[node name="MainBody" type="MeshInstance3D" parent="Skin"] +[node name="Skin" type="Node3D" parent="RotationBase"] +unique_name_in_owner = true + +[node name="MainBody" type="MeshInstance3D" parent="RotationBase/Skin"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) mesh = SubResource("CapsuleMesh_di3a0") -skeleton = NodePath("../..") +skeleton = NodePath("../../..") surface_material_override/0 = ExtResource("3_6c0ro") -[node name="Beak" type="MeshInstance3D" parent="Skin/MainBody"] +[node name="Beak" type="MeshInstance3D" parent="RotationBase/Skin/MainBody"] transform = Transform3D(0.35, 0, 0, 0, -0.105655, 0.0906308, 0, -0.226577, -0.0422618, 0, 0.45, -0.3) mesh = SubResource("PrismMesh_fcj1v") -[node name="RightEye" type="MeshInstance3D" parent="Skin/MainBody"] +[node name="RightEye" type="MeshInstance3D" parent="RotationBase/Skin/MainBody"] transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0.1, 0.6, -0.25) mesh = SubResource("SphereMesh_tudvv") -[node name="LeftEye" type="MeshInstance3D" parent="Skin/MainBody"] +[node name="LeftEye" type="MeshInstance3D" parent="RotationBase/Skin/MainBody"] transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, -0.1, 0.6, -0.25) mesh = SubResource("SphereMesh_1gltg") @@ -123,4 +127,8 @@ script = ExtResource("7_jfat4") unique_name_in_owner = true script = ExtResource("8_phh70") +[node name="Dead" type="Node" parent="StateMachine"] +unique_name_in_owner = true +script = ExtResource("9_bw4yb") + [connection signal="delta_synchronized" from="Sync" to="." method="_on_sync_delta_synchronized"] diff --git a/scripts/in_game.gd b/scripts/in_game.gd index 94e8580..54d191c 100644 --- a/scripts/in_game.gd +++ b/scripts/in_game.gd @@ -15,7 +15,10 @@ func spawn_player(player_id: int, runner: bool) -> void: player.player_id = player_id player.name = str(player_id) - _runners_node.add_child(player) if runner else _chasers_node.add_child(player) + if runner: + _runners_node.add_child(player) + else: + _chasers_node.add_child(player) func despawn_player(player_id: int) -> void: if not multiplayer.is_server(): return diff --git a/scripts/multiplayer/input.gd b/scripts/multiplayer/input.gd index 207d89e..7bb7207 100644 --- a/scripts/multiplayer/input.gd +++ b/scripts/multiplayer/input.gd @@ -13,7 +13,16 @@ func _ready() -> void: set_physics_process(false) func _physics_process(_delta: float) -> void: + if get_multiplayer_authority() != multiplayer.get_unique_id(): return + var directional_input := Input.get_vector("move_right", "move_left", "move_forward", "move_back") var camera_adjusted: Vector3 = (directional_input.x * _camera_pivot.global_basis.z) + (directional_input.y * _camera_pivot.global_basis.x) direction = Vector2(camera_adjusted.x, camera_adjusted.z).rotated(PI / 2.0).normalized() walk = Input.is_action_pressed("walk") + +func _input(_event: InputEvent) -> void: + if get_multiplayer_authority() != multiplayer.get_unique_id(): return + if Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED: return + + primary_interact = Input.is_action_pressed("primary_interact") + secondary_interact = Input.is_action_pressed("secondary_interact") diff --git a/scripts/runner.gd b/scripts/runner.gd index 6ad1032..a96101e 100644 --- a/scripts/runner.gd +++ b/scripts/runner.gd @@ -33,7 +33,7 @@ extends CharacterBody3D @onready var _camera_pivot: Node3D = %CameraPivot @onready var _camera_platform: Node3D = %CameraPlatform @onready var _camera: Node3D = %Camera -@onready var skin: Node3D = %Skin +@onready var rotation_base: Node3D = %RotationBase var camera_input_direction := Vector2.ZERO var last_direction := Vector3.FORWARD @@ -46,9 +46,9 @@ func _ready() -> void: if multiplayer.is_server(): return if multiplayer.get_unique_id() == player_id: - %Camera.make_current() + _camera.make_current() else: - %Camera.clear_current(false) + _camera.clear_current(false) func _input(event: InputEvent) -> void: if multiplayer.get_unique_id() != player_id: return @@ -86,21 +86,34 @@ func _physics_process(delta: float) -> void: if not multiplayer.is_server(): if multiplayer.get_unique_id() == player_id and client_prediction: predicted_position = position - predicted_rotation = skin.global_rotation + predicted_rotation = rotation_base.global_rotation if multiplayer.get_unique_id() != player_id or not client_prediction: if client_smoothing: position = lerp(position, server_position, client_smoothing_speed * delta) - skin.global_rotation.y = lerp_angle(skin.global_rotation.y, server_rotation.y, client_smoothing_rotation_speed * delta) + rotation_base.global_rotation.x = server_rotation.x + rotation_base.global_rotation.y = lerp_angle(rotation_base.global_rotation.y, server_rotation.y, client_smoothing_rotation_speed * delta) + rotation_base.global_rotation.z = server_rotation.z else: position = server_position - skin.global_rotation.y = server_rotation.y - + rotation_base.global_rotation = server_rotation +# if multiplayer.is_server(): server_position = position - server_rotation = skin.global_rotation + server_rotation = rotation_base.global_rotation func _on_sync_delta_synchronized() -> void: if client_prediction and server_position.distance_to(predicted_position) > client_prediction_tolerance: print("%v VS %v" % [server_position, predicted_position]) position = server_position + + +func apply_input_velocity(delta: float, input_direction: Vector2, speed: float, acceleration: float) -> void: + var target_velocity = Vector3(input_direction.x * speed, velocity.y, input_direction.y * speed) + velocity = velocity.move_toward(target_velocity, acceleration * delta) + Main.gravity_velocity + move_and_slide() + + if input_direction.length() >= 0.1: + last_direction = Vector3(input_direction.x, 0, input_direction.y) + var target_angle := Vector3.FORWARD.signed_angle_to(last_direction, Vector3.UP) + rotation_base.global_rotation.y = lerp_angle(rotation_base.rotation.y, target_angle, rotation_speed * delta) diff --git a/scripts/states/dead.gd b/scripts/states/dead.gd new file mode 100644 index 0000000..fa8f890 --- /dev/null +++ b/scripts/states/dead.gd @@ -0,0 +1,12 @@ +extends State + +func enter() -> void: + subject.rotation_base.global_rotation.z = PI / 2 + +func exit() -> void: + subject.rotation_base.global_rotation.z = 0 + +func process_physics(_delta: float) -> State: + if not multiplayer.is_server(): return + + return diff --git a/scripts/states/fall.gd b/scripts/states/fall.gd index 7cf9505..dfff4fd 100644 --- a/scripts/states/fall.gd +++ b/scripts/states/fall.gd @@ -3,12 +3,9 @@ extends State func process_physics(delta: float) -> State: if not Main.is_server_or_predicting(subject.player_id, subject.client_prediction): return - var target_velocity = Vector3(0, subject.velocity.y, 0) - subject.velocity = subject.velocity.move_toward(target_velocity, subject.air_deceleration * delta) - subject.velocity += Main.gravity_velocity - subject.move_and_slide() + subject.apply_input_velocity(delta, Vector2.ZERO, 0.0, subject.air_deceleration) if not subject.is_on_floor(): return if %Input.direction.length() < 0.05: return %Idle - if %Input.walk: return %Walk + if has_node("%Walk") and %Input.walk: return %Walk return %Run diff --git a/scripts/states/idle.gd b/scripts/states/idle.gd index 870b645..a8da571 100644 --- a/scripts/states/idle.gd +++ b/scripts/states/idle.gd @@ -3,14 +3,12 @@ extends State func process_physics(delta: float) -> State: if not Main.is_server_or_predicting(subject.player_id, subject.client_prediction): return - var target_velocity = Vector3(0, subject.velocity.y, 0) - subject.velocity = subject.velocity.move_toward(target_velocity, subject.acceleration * delta) - subject.velocity += Main.gravity_velocity - subject.move_and_slide() + subject.apply_input_velocity(delta, Vector2.ZERO, 0.0, subject.acceleration) if not subject.is_on_floor(): return %Fall + if has_node("%Lunge") and %Input.primary_interact: return %Lunge # TODO: Lunge attacks currently do nothing so Chasers can't move when they click in var input_direction = %Input.direction if input_direction.length() < 0.05: return - + if has_node("%Walk") and %Input.walk: return %Walk return %Run diff --git a/scripts/states/lunge.gd b/scripts/states/lunge.gd new file mode 100644 index 0000000..96f5562 --- /dev/null +++ b/scripts/states/lunge.gd @@ -0,0 +1,11 @@ +extends State + +func process_physics(delta: float) -> State: + if not Main.is_server_or_predicting(subject.player_id, subject.client_prediction): return + + var input_direction = %Input.direction if subject.is_on_floor() else Vector2.ZERO + + subject.apply_input_velocity(delta, input_direction, subject.run_speed, subject.acceleration if subject.is_on_floor() else subject.air_deceleration) + + if has_node("%Walk") and %Input.walk: return %Walk + return diff --git a/scripts/states/run.gd b/scripts/states/run.gd index ce42721..7dc119c 100644 --- a/scripts/states/run.gd +++ b/scripts/states/run.gd @@ -6,17 +6,8 @@ func process_physics(delta: float) -> State: var input_direction = %Input.direction if input_direction.length() < 0.05: return %Idle - var move_direction = Vector3(input_direction.x, 0, input_direction.y) - var target_velocity = Vector3(move_direction.x * subject.run_speed, subject.velocity.y, move_direction.z * subject.run_speed) - subject.velocity = subject.velocity.move_toward(target_velocity, subject.acceleration * delta) - subject.velocity += Main.gravity_velocity - subject.move_and_slide() + subject.apply_input_velocity(delta, input_direction, subject.run_speed, subject.acceleration) - if move_direction.length() >= 0.1: - subject.last_direction = move_direction - var target_angle := Vector3.FORWARD.signed_angle_to(subject.last_direction, Vector3.UP) - subject.skin.global_rotation.y = lerp_angle(subject.skin.rotation.y, target_angle, subject.rotation_speed * delta) - - if %Input.walk: return %Walk + if has_node("%Walk") and %Input.walk: return %Walk if not subject.is_on_floor(): return %Fall return diff --git a/scripts/states/state.gd b/scripts/states/state.gd index 2bbb3c6..b17f8a0 100644 --- a/scripts/states/state.gd +++ b/scripts/states/state.gd @@ -4,6 +4,7 @@ extends Node var subject func enter() -> void: + print("Entering state: %s" % name) pass func exit() -> void: diff --git a/scripts/states/walk.gd b/scripts/states/walk.gd index 3277d26..7f1272a 100644 --- a/scripts/states/walk.gd +++ b/scripts/states/walk.gd @@ -6,16 +6,7 @@ func process_physics(delta: float) -> State: var input_direction = %Input.direction if input_direction.length() < 0.05: return %Idle - var move_direction = Vector3(input_direction.x, 0, input_direction.y) - var target_velocity = Vector3(move_direction.x * subject.walk_speed, subject.velocity.y, move_direction.z * subject.walk_speed) - subject.velocity = subject.velocity.move_toward(target_velocity, subject.acceleration * delta) - subject.velocity += Main.gravity_velocity - subject.move_and_slide() - - if move_direction.length() >= 0.1: - subject.last_direction = move_direction - var target_angle := Vector3.FORWARD.signed_angle_to(subject.last_direction, Vector3.UP) - subject.skin.global_rotation.y = lerp_angle(subject.skin.rotation.y, target_angle, subject.rotation_speed * delta) + subject.apply_input_velocity(delta, input_direction, subject.walk_speed, subject.acceleration) if not %Input.walk: return %Run if not subject.is_on_floor(): return %Fall