diff --git a/Prefabs/PlayerCamera.tscn b/Prefabs/PlayerCamera.tscn index 91d344f..265b78f 100644 --- a/Prefabs/PlayerCamera.tscn +++ b/Prefabs/PlayerCamera.tscn @@ -2,7 +2,9 @@ [ext_resource type="Script" uid="uid://bici4k5vkuoos" path="res://Scripts/player_camera.gd" id="1_ocbkm"] -[node name="Camera3D" type="Camera3D"] -transform = Transform3D(1, 0, 0, 0, 0.25038, 0.968148, 0, -0.968148, 0.25038, 0, 0, 0) -fov = 80.0 +[node name="CameraFollow" type="Node3D"] script = ExtResource("1_ocbkm") + +[node name="Camera3D" type="Camera3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 0.34202, 0.939693, 0, -0.939693, 0.34202, 0, 10, 3) +fov = 80.0 diff --git a/Prefabs/player.tscn b/Prefabs/player.tscn index 62527c0..1d45e89 100644 --- a/Prefabs/player.tscn +++ b/Prefabs/player.tscn @@ -1,7 +1,11 @@ -[gd_scene load_steps=8 format=4 uid="uid://bacgd5lmvaxea"] +[gd_scene load_steps=15 format=4 uid="uid://bacgd5lmvaxea"] [ext_resource type="Script" uid="uid://bcgt64gerg8pv" path="res://Scripts/player.gd" id="1_5wxv7"] [ext_resource type="Material" uid="uid://b4rpp31c0dx2m" path="res://Assets/Materials/BasicMat.tres" id="1_y6xdh"] +[ext_resource type="Script" uid="uid://bk6205bvyl0to" path="res://Scripts/player_state_machine.gd" id="2_y5hcb"] +[ext_resource type="Script" uid="uid://c2xwiexy5b3b3" path="res://Scripts/player_attack.gd" id="3_knrd4"] +[ext_resource type="Script" uid="uid://wnisqyoyai2h" path="res://Scripts/player_on_floor.gd" id="4_hck1p"] +[ext_resource type="Script" uid="uid://dhnl0penaqfkx" path="res://Scripts/player_dodge_roll.gd" id="5_hck1p"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_i3sml"] resource_name = "Material" @@ -54,11 +58,66 @@ size = Vector3(1.59, 0.4, 0.375) radius = 0.501894 height = 1.30188 +[sub_resource type="Animation" id="Animation_hck1p"] +resource_name = "dodge" +step = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Body:rotation") +tracks/0/interp = 2 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.3), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector3(0, 0, 0), Vector3(0, 0, 6.28319)] +} + +[sub_resource type="Animation" id="Animation_juxdh"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Body:rotation") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0, 0, 0)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_4qbli"] +_data = { +&"RESET": SubResource("Animation_juxdh"), +&"dodge": SubResource("Animation_hck1p") +} + [node name="Player" type="CharacterBody3D"] script = ExtResource("1_5wxv7") +[node name="OmniLight3D" type="OmniLight3D" parent="."] +transform = Transform3D(1, -1.74846e-07, 0, 1.74846e-07, 1, 0, 0, 0, 1, -2.406e-07, 1.87607, 0.0537765) +light_energy = 0.1 + +[node name="State Machine" type="Node" parent="." node_paths=PackedStringArray("character", "initial_state")] +script = ExtResource("2_y5hcb") +character = NodePath("..") +initial_state = NodePath("On Floor") + +[node name="Attack" type="Node" parent="State Machine"] +script = ExtResource("3_knrd4") + +[node name="On Floor" type="Node" parent="State Machine"] +script = ExtResource("4_hck1p") + +[node name="Dodge Roll" type="Node" parent="State Machine"] +script = ExtResource("5_hck1p") + [node name="Body" type="MeshInstance3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0.0537765) material_override = ExtResource("1_y6xdh") mesh = SubResource("ArrayMesh_5wxv7") skeleton = NodePath("") @@ -67,10 +126,6 @@ metadata/extras = { "rr_curve_obj": {} } -[node name="OmniLight3D" type="OmniLight3D" parent="Body"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.37607, 0) -light_energy = 0.1 - [node name="MeshInstance3D" type="MeshInstance3D" parent="Body"] transform = Transform3D(-0.487982, 0, -0.872854, 0, 1, 0, 0.872854, 0, -0.487982, 0.351417, 0.11253, -0.601462) mesh = SubResource("BoxMesh_5wxv7") @@ -79,3 +134,8 @@ skeleton = NodePath("../..") [node name="CollisionShape3D" type="CollisionShape3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) shape = SubResource("CapsuleShape3D_y5hcb") + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +libraries = { +&"": SubResource("AnimationLibrary_4qbli") +} diff --git a/Scenes/TestScene1.tscn b/Scenes/TestScene1.tscn index 70a2a29..9d7df66 100644 --- a/Scenes/TestScene1.tscn +++ b/Scenes/TestScene1.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=25 format=4 uid="uid://dbqyyunvx6fdj"] +[gd_scene load_steps=24 format=4 uid="uid://dbqyyunvx6fdj"] [ext_resource type="Material" uid="uid://b4rpp31c0dx2m" path="res://Assets/Materials/BasicMat.tres" id="1_8lor2"] [ext_resource type="PackedScene" uid="uid://hmyrn2pbbhpm" path="res://Prefabs/PlayerCamera.tscn" id="2_qq11w"] @@ -27,9 +27,6 @@ fog_light_color = Color(0.117, 0.14115, 0.18, 1) fog_light_energy = 1.65 fog_density = 1.0 -[sub_resource type="BoxShape3D" id="BoxShape3D_qq11w"] -size = Vector3(100, 1, 100) - [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_cre2v"] [sub_resource type="ArrayMesh" id="ArrayMesh_eow34"] @@ -201,19 +198,11 @@ _surfaces = [{ blend_shape_mode = 0 shadow_mesh = SubResource("ArrayMesh_ib0jm") -[node name="Node3D" type="Node3D"] +[node name="TestLevel" type="Node3D"] [node name="WorldEnvironment" type="WorldEnvironment" parent="."] environment = SubResource("Environment_vab8d") -[node name="StaticBody3D" type="StaticBody3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.196, 7.041, 1.942) -collision_layer = 128 -collision_mask = 128 - -[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"] -shape = SubResource("BoxShape3D_qq11w") - [node name="Test1" type="Node3D" parent="."] [node name="Cube_001" type="MeshInstance3D" parent="Test1"] @@ -272,7 +261,7 @@ metadata/extras = { } [node name="Camera3D" parent="." node_paths=PackedStringArray("player") instance=ExtResource("2_qq11w")] -transform = Transform3D(1, 0, 0, 0, 0.25038, 0.968148, 0, -0.968148, 0.25038, 0.196, 7.041, 1.942) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) player = NodePath("../Player") [node name="OmniLight3D" type="OmniLight3D" parent="."] @@ -291,7 +280,45 @@ light_color = Color(0.833261, 0.5957, 0.32611, 1) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.26995, 0.974748, 4.40131) light_color = Color(0.833261, 0.5957, 0.32611, 1) +[node name="OmniLight3D5" type="OmniLight3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.66639, 0.974749, -33.6377) +light_color = Color(0.833261, 0.5957, 0.32611, 1) + +[node name="OmniLight3D6" type="OmniLight3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.90079, 0.974749, -34.0342) +light_color = Color(0.833261, 0.5957, 0.32611, 1) + +[node name="OmniLight3D7" type="OmniLight3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.90218, 0.974748, -25.5942) +light_color = Color(0.833261, 0.5957, 0.32611, 1) + +[node name="OmniLight3D8" type="OmniLight3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.26995, 0.974748, -25.5011) +light_color = Color(0.833261, 0.5957, 0.32611, 1) + [node name="PostProcessing" parent="." instance=ExtResource("2_vab8d")] [node name="Player" parent="." instance=ExtResource("3_hfnh2")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0717504, 0.311536, 0.0210209) + +[node name="Blockout" type="Node3D" parent="."] + +[node name="CSGBox3D" type="CSGBox3D" parent="Blockout"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.296387, -13.9739) +use_collision = true +size = Vector3(0.328125, 0.407227, 18.4945) + +[node name="CSGBox3D4" type="CSGBox3D" parent="Blockout"] +transform = Transform3D(0.888377, 0, 0.459115, 0, 1, 0, -0.459115, 0, 0.888377, -3.97738, -0.296386, -15.7424) +use_collision = true +size = Vector3(0.859375, 0.407227, 18.4945) + +[node name="CSGBox3D3" type="CSGBox3D" parent="Blockout"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.296387, -13.9739) +use_collision = true +size = Vector3(0.328125, 0.407227, 18.4945) + +[node name="CSGBox3D2" type="CSGBox3D" parent="Blockout"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.296387, -30.2649) +use_collision = true +size = Vector3(20.9199, 0.407227, 14.3326) diff --git a/Scripts/State.gd b/Scripts/State.gd new file mode 100644 index 0000000..a697be4 --- /dev/null +++ b/Scripts/State.gd @@ -0,0 +1,16 @@ +extends Node +class_name State + +signal Transitioned + +func Enter(): + pass + +func Exit(): + pass + +func Update(_delta : float): + pass + +func Physics_Update(_delta : float): + pass diff --git a/Scripts/State.gd.uid b/Scripts/State.gd.uid new file mode 100644 index 0000000..8cf8975 --- /dev/null +++ b/Scripts/State.gd.uid @@ -0,0 +1 @@ +uid://55lxwlg155dq diff --git a/Scripts/player.gd b/Scripts/player.gd index eea9775..ad05335 100644 --- a/Scripts/player.gd +++ b/Scripts/player.gd @@ -1,34 +1,23 @@ extends CharacterBody3D class_name Player -var input_dir +var dodge_direction @onready var body: MeshInstance3D = $Body +@onready var anim_player: AnimationPlayer = $AnimationPlayer +const MAX_STAMINA : float = 100 +var stamina = MAX_STAMINA +const STAMINA_REGEN_RATE = 10.0 -const MOVE_SPEED = 10.0 -const MOVE_TRANSITION_SPEED = 7.0 +## Gameplay Settings +const DODGE_STAMINA_COST = 30.0 func _physics_process(delta: float) -> void: - if is_on_floor(): - standard_movement(delta) - - body_look_at_mouse() - apply_gravity(delta) + stamina_regen(delta) move_and_slide() -func body_look_at_mouse(): - var mouse_raycast = MousePos.get_mouse_world_position() - if mouse_raycast != null: - body.look_at(Vector3(mouse_raycast.x,body.global_position.y,mouse_raycast.y),Vector3.UP) - -func apply_gravity(delta): - if !is_on_floor(): - velocity.y -= 9.8 * delta - -func standard_movement(delta): - input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_backward") - - if input_dir != null: - velocity.x = lerp(velocity.x, input_dir.x * MOVE_SPEED,delta * MOVE_TRANSITION_SPEED) - velocity.z = lerp(velocity.z, input_dir.y * MOVE_SPEED,delta * MOVE_TRANSITION_SPEED) +func stamina_regen(delta): + if stamina < MAX_STAMINA: + print("STAMINA : ", stamina) + stamina = clamp(stamina + delta * STAMINA_REGEN_RATE,0,MAX_STAMINA) diff --git a/Scripts/player_attack.gd b/Scripts/player_attack.gd new file mode 100644 index 0000000..6d5d084 --- /dev/null +++ b/Scripts/player_attack.gd @@ -0,0 +1,2 @@ +extends State +class_name PlayerAttack diff --git a/Scripts/player_attack.gd.uid b/Scripts/player_attack.gd.uid new file mode 100644 index 0000000..a38c837 --- /dev/null +++ b/Scripts/player_attack.gd.uid @@ -0,0 +1 @@ +uid://c2xwiexy5b3b3 diff --git a/Scripts/player_camera.gd b/Scripts/player_camera.gd index aec2b53..f254f05 100644 --- a/Scripts/player_camera.gd +++ b/Scripts/player_camera.gd @@ -1,5 +1,4 @@ -extends Camera3D -class_name PlayerCamera +extends Node3D @export var player : Player diff --git a/Scripts/player_dodge_roll.gd b/Scripts/player_dodge_roll.gd new file mode 100644 index 0000000..2b60d8f --- /dev/null +++ b/Scripts/player_dodge_roll.gd @@ -0,0 +1,21 @@ +extends PlayerState +class_name PlayerDodgeRoll + + + +const DODGE_SPEED : float = 20.0 +const DODGE_TIME : float = .1 +var dodge_timer = DODGE_TIME + +func Enter(): + character.anim_player.play("dodge") + +func Physics_Update(delta): + if dodge_timer > 0: + dodge_timer -= delta + else: + dodge_timer = DODGE_TIME + Transitioned.emit(self,"on floor") + + character.velocity.x = character.dodge_direction.x * DODGE_SPEED + character.velocity.z = character.dodge_direction.y * DODGE_SPEED diff --git a/Scripts/player_dodge_roll.gd.uid b/Scripts/player_dodge_roll.gd.uid new file mode 100644 index 0000000..2f79fc9 --- /dev/null +++ b/Scripts/player_dodge_roll.gd.uid @@ -0,0 +1 @@ +uid://dhnl0penaqfkx diff --git a/Scripts/player_on_floor.gd b/Scripts/player_on_floor.gd new file mode 100644 index 0000000..3451afd --- /dev/null +++ b/Scripts/player_on_floor.gd @@ -0,0 +1,19 @@ +extends PlayerState +class_name PlayerOnFloor + +func Physics_Update(delta): + dodge_roll() + standard_movement(delta) + body_look_at_mouse() + apply_gravity(delta) + respawn_on_fall(delta) + +func dodge_roll(): + if character.is_on_floor(): + if character.stamina > character.DODGE_STAMINA_COST: + if Input.is_action_just_pressed("dodge"): + var dodge_direction = Input.get_vector("move_left", "move_right", "move_forward", "move_backward") + if dodge_direction: + character.stamina -= character.DODGE_STAMINA_COST + character.dodge_direction = dodge_direction + Transitioned.emit(self,"dodge roll") diff --git a/Scripts/player_on_floor.gd.uid b/Scripts/player_on_floor.gd.uid new file mode 100644 index 0000000..41c0580 --- /dev/null +++ b/Scripts/player_on_floor.gd.uid @@ -0,0 +1 @@ +uid://wnisqyoyai2h diff --git a/Scripts/player_state_machine.gd b/Scripts/player_state_machine.gd new file mode 100644 index 0000000..06ad459 --- /dev/null +++ b/Scripts/player_state_machine.gd @@ -0,0 +1,42 @@ +extends Node +class_name PlayerStateMachine + +@export var character : Player +@export var initial_state : State + +var current_state : State +var states : Dictionary = {} + +func _ready() -> void: + for child in get_children(): + if child is State: + states[child.name.to_lower()] = child + child.Transitioned.connect(on_child_transition) + + if initial_state: + initial_state.Enter() + current_state = initial_state + +func _process(delta: float) -> void: + if current_state: + current_state.Update(delta) + +func _physics_process(delta: float) -> void: + if current_state: + current_state.Physics_Update(delta) + +func on_child_transition(state,new_state_name): + if state != current_state: + return + + var new_state = states.get(new_state_name.to_lower()) + if !new_state: + return + + if current_state: + current_state.Exit() + + new_state.Enter() + + current_state = new_state + print("PLAYER STATE CHANGED TO : ",current_state) diff --git a/Scripts/player_state_machine.gd.uid b/Scripts/player_state_machine.gd.uid new file mode 100644 index 0000000..d22e0e1 --- /dev/null +++ b/Scripts/player_state_machine.gd.uid @@ -0,0 +1 @@ +uid://bk6205bvyl0to diff --git a/Scripts/player_states.gd b/Scripts/player_states.gd new file mode 100644 index 0000000..4ac22e1 --- /dev/null +++ b/Scripts/player_states.gd @@ -0,0 +1,56 @@ +extends State +class_name PlayerState + +@export var move_speed = 10.0 +@export var move_transition_speed = 7.0 +@export var health_lost_on_fall = 2.0 + +# respawn after falling +const FALL_TIME_TO_RESPAWN : float = 4.0 +const TIME_TO_CACHE_POSITION : float = 2.0 +var ground_pos_cached = [] +var fall_timer = FALL_TIME_TO_RESPAWN +var ground_pos_timer = 0 + +@onready var character = get_parent().character + +func Update(delta): + pass + +func respawn_on_fall(delta): + if character.is_on_floor(): + if ground_pos_timer > 0: + ground_pos_timer -= delta + else: + ground_pos_timer = TIME_TO_CACHE_POSITION + ground_pos_cached.append(character.global_position) + if ground_pos_cached.size() > 2: + ground_pos_cached.pop_front() + else: + if fall_timer > 0: + fall_timer -= delta + else: + fall_timer = FALL_TIME_TO_RESPAWN + character.global_position = ground_pos_cached[0] + +func apply_gravity(delta): + if !character.is_on_floor(): + character.velocity.y -= 9.8 * delta + +func body_look_at_mouse(): + var mouse_raycast = MousePos.get_mouse_world_position() + if mouse_raycast != null: + character.body.look_at(Vector3(mouse_raycast.x,character.body.global_position.y,mouse_raycast.y),Vector3.UP) + +func standard_movement(delta): + if character.is_on_floor(): + var input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_backward") + + if input_dir != null: + character.velocity.x = lerp(character.velocity.x, input_dir.x * move_speed, delta * move_transition_speed) + character.velocity.z = lerp(character.velocity.z, input_dir.y * move_speed,delta * move_transition_speed) + else: + if character.velocity: + const MOMENTUM = 2.0 + character.velocity.x = lerp(character.velocity.x, 0.0,delta * MOMENTUM) + character.velocity.z = lerp(character.velocity.z, 0.0,delta * MOMENTUM) diff --git a/Scripts/player_states.gd.uid b/Scripts/player_states.gd.uid new file mode 100644 index 0000000..890b9a7 --- /dev/null +++ b/Scripts/player_states.gd.uid @@ -0,0 +1 @@ +uid://mmr40sx0iij5 diff --git a/project.godot b/project.godot index e01fbf3..fd0265b 100644 --- a/project.godot +++ b/project.godot @@ -45,6 +45,11 @@ move_backward={ "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":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) ] } +dodge={ +"deadzone": 0.2, +"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":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null) +] +} [layer_names]