diff --git a/game/entities/player/abstract_player_state.gd b/game/entities/player/abstract_player_state.gd new file mode 100644 index 0000000..9cb50bb --- /dev/null +++ b/game/entities/player/abstract_player_state.gd @@ -0,0 +1,5 @@ +class_name AbstractPlayerState +extends AbstractState + + +@export var player : Player diff --git a/game/entities/player/abstract_player_state.gd.uid b/game/entities/player/abstract_player_state.gd.uid new file mode 100644 index 0000000..3a6c9bf --- /dev/null +++ b/game/entities/player/abstract_player_state.gd.uid @@ -0,0 +1 @@ +uid://dj8pkf8aq2x73 diff --git a/game/entities/player/abstract_player_state.tscn b/game/entities/player/abstract_player_state.tscn new file mode 100644 index 0000000..b4cf972 --- /dev/null +++ b/game/entities/player/abstract_player_state.tscn @@ -0,0 +1,7 @@ +[gd_scene format=3 uid="uid://dqkewlpol05ap"] + +[ext_resource type="PackedScene" uid="uid://cxdirjlkyccs4" path="res://game/state_machine/abstract_state.tscn" id="1_7h8jh"] +[ext_resource type="Script" uid="uid://dj8pkf8aq2x73" path="res://game/entities/player/abstract_player_state.gd" id="2_inbmw"] + +[node name="AbstractPlayerState" unique_id=836520368 instance=ExtResource("1_7h8jh")] +script = ExtResource("2_inbmw") diff --git a/game/entities/player/player.gd b/game/entities/player/player.gd index daa8450..1111bde 100644 --- a/game/entities/player/player.gd +++ b/game/entities/player/player.gd @@ -1,2 +1,77 @@ class_name Player extends CharacterBody2D + + +@export_group("Movement", "movement") +@export_range(0.0, 1000.0) var movement_max_speed_normal := 350 +@export_range(0.0, 1000.0) var movement_max_speed_after_attack := 250 +@export_range(0.0, 1000.0) var movement_acceleration := 1000.0 + +@export_group("Jump", "jump") +@export_range(0.0, 1000.0) var jump_max_fall_speed := 1000 +@export_range(0.0, 1000.0) var jump_velocity := 500.0 + +@export_group("Gravity factors", "gravity_factor") +@export_range(0.0, 2.0) var gravity_factor_jump := 1.0 +@export_range(0.0, 2.0) var gravity_factor_fall := 1.5 +@export_range(0.0, 2.0) var gravity_factor_slide := 0.1 +@export_range(0.0, 1.0) var gravity_factor_passive_jump := 0.5 + + +@onready var state_machine : StateMachine = $StateMachine + +@onready var jump_buffer_timer : Timer = $JumpBufferTimer +@onready var coyote_time_timer : Timer = $CoyoteTimeTimer +@onready var attack_cooldown_timer : Timer = $AttackCooldownTimer +@onready var attack_slowdown_timer : Timer = $AttackSlowdownTimer +@onready var slide_delay_timer : Timer = $SlideDelayTimer + + +func _ready() -> void: + state_machine.init() + + +func _physics_process(delta: float) -> void: + if is_on_floor(): + coyote_time_timer.start() + if is_on_ceiling_only() and velocity.y < 0.0: + velocity.y = 0.0 + + if not is_on_floor(): + var gravity_factor := gravity_factor_jump if velocity.y < 0.0 else gravity_factor_fall + + if velocity.y < 0.0 and not Input.is_action_pressed("jump"): + velocity.y *= gravity_factor_passive_jump + + velocity += get_gravity() * gravity_factor * delta + velocity.y = clampf(velocity.y, -jump_max_fall_speed, jump_max_fall_speed) + + + if Input.is_action_just_pressed("jump"): + jump_buffer_timer.start() + + if not coyote_time_timer.is_stopped() and not jump_buffer_timer.is_stopped(): + velocity.y = -jump_velocity + jump_buffer_timer.stop() + coyote_time_timer.stop() + + var direction := Input.get_axis("move_left", "move_right") + if direction: + var max_speed : float + if attack_slowdown_timer.is_stopped(): + max_speed = movement_max_speed_normal + else: + max_speed = movement_max_speed_after_attack + + velocity.x = move_toward(velocity.x, direction * max_speed, movement_acceleration * delta) + else: + velocity.x = move_toward(velocity.x, 0, movement_acceleration * delta) + + move_and_slide() + state_machine.physics_process(delta) + + +func _input(event: InputEvent) -> void: + if event.is_action_pressed("attack") and attack_cooldown_timer.is_stopped(): + attack_cooldown_timer.start() + print("Attack") diff --git a/game/entities/player/player.tscn b/game/entities/player/player.tscn index aa965a6..6bedc46 100644 --- a/game/entities/player/player.tscn +++ b/game/entities/player/player.tscn @@ -1,6 +1,8 @@ [gd_scene format=3 uid="uid://ts4dy8xmtot8"] [ext_resource type="Script" uid="uid://bm48h30pkhdkv" path="res://game/entities/player/player.gd" id="1_1a4jd"] +[ext_resource type="PackedScene" uid="uid://blxgfix54dxq3" path="res://game/state_machine/state_machine.tscn" id="2_x4rrl"] +[ext_resource type="PackedScene" uid="uid://btu3hxif2xpvu" path="res://game/entities/player/states/idle_state.tscn" id="3_cjfdk"] [sub_resource type="CapsuleShape2D" id="CapsuleShape2D_bhunq"] @@ -9,3 +11,33 @@ script = ExtResource("1_1a4jd") [node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=379935685] shape = SubResource("CapsuleShape2D_bhunq") + +[node name="Camera2D" type="Camera2D" parent="." unique_id=1654451713] + +[node name="StateMachine" parent="." unique_id=560273456 node_paths=PackedStringArray("initial_state") instance=ExtResource("2_x4rrl")] +initial_state = NodePath("IdleState") + +[node name="IdleState" parent="StateMachine" unique_id=836520368 node_paths=PackedStringArray("player") instance=ExtResource("3_cjfdk")] +player = NodePath("../..") + +[node name="JumpBufferTimer" type="Timer" parent="." unique_id=1845152635] +process_callback = 0 +wait_time = 0.05 +one_shot = true + +[node name="CoyoteTimeTimer" type="Timer" parent="." unique_id=867376979] +process_callback = 0 +wait_time = 0.05 +one_shot = true + +[node name="AttackCooldownTimer" type="Timer" parent="." unique_id=1208896947] +process_callback = 0 +wait_time = 0.75 + +[node name="AttackSlowdownTimer" type="Timer" parent="." unique_id=1617625946] +process_callback = 0 +one_shot = true + +[node name="SlideDelayTimer" type="Timer" parent="." unique_id=1746851787] +process_callback = 0 +wait_time = 0.75 diff --git a/game/entities/player/states/idle_state.gd b/game/entities/player/states/idle_state.gd new file mode 100644 index 0000000..29cfd72 --- /dev/null +++ b/game/entities/player/states/idle_state.gd @@ -0,0 +1 @@ +extends AbstractPlayerState diff --git a/game/entities/player/states/idle_state.gd.uid b/game/entities/player/states/idle_state.gd.uid new file mode 100644 index 0000000..0c81743 --- /dev/null +++ b/game/entities/player/states/idle_state.gd.uid @@ -0,0 +1 @@ +uid://dqefq55apabc8 diff --git a/game/entities/player/states/idle_state.tscn b/game/entities/player/states/idle_state.tscn new file mode 100644 index 0000000..7c6c417 --- /dev/null +++ b/game/entities/player/states/idle_state.tscn @@ -0,0 +1,7 @@ +[gd_scene format=3 uid="uid://btu3hxif2xpvu"] + +[ext_resource type="PackedScene" uid="uid://dqkewlpol05ap" path="res://game/entities/player/abstract_player_state.tscn" id="1_wl4i0"] +[ext_resource type="Script" uid="uid://dqefq55apabc8" path="res://game/entities/player/states/idle_state.gd" id="2_85bpc"] + +[node name="IdleState" unique_id=836520368 instance=ExtResource("1_wl4i0")] +script = ExtResource("2_85bpc") diff --git a/game/levels/test_level.tscn b/game/levels/test_level.tscn new file mode 100644 index 0000000..868b8c1 --- /dev/null +++ b/game/levels/test_level.tscn @@ -0,0 +1,21 @@ +[gd_scene format=3 uid="uid://cuig5x5fd47hs"] + +[ext_resource type="PackedScene" uid="uid://hdnty666fw1h" path="res://game/levels/abstract_level.tscn" id="1_46m3m"] + +[sub_resource type="WorldBoundaryShape2D" id="WorldBoundaryShape2D_bhunq"] + +[node name="TestLevel" unique_id=1001045799 instance=ExtResource("1_46m3m")] + +[node name="Player" parent="." index="0" unique_id=763780926] +position = Vector2(0, -30) + +[node name="StaticBody2D" type="StaticBody2D" parent="." index="1" unique_id=1113871341] + +[node name="CollisionShape2D" type="CollisionShape2D" parent="StaticBody2D" index="0" unique_id=2097094532] +shape = SubResource("WorldBoundaryShape2D_bhunq") + +[node name="Menus" parent="." index="2" unique_id=1464185162] +offset_left = -320.0 +offset_top = -210.0 +offset_right = 320.0 +offset_bottom = 150.0 diff --git a/game/menu/main_menu.gd b/game/menu/main_menu.gd index c3c8d39..96810d8 100644 --- a/game/menu/main_menu.gd +++ b/game/menu/main_menu.gd @@ -31,7 +31,7 @@ func _on_gui_focus_changed(_node: Control) -> void: func _on_start_button_pressed() -> void: SoundManager.play_ui_stream(SoundManager.ui_stream_accept) - #TODO transition to level selection + get_tree().change_scene_to_file("res://game/levels/test_level.tscn") func _on_options_button_pressed() -> void: diff --git a/project.godot b/project.godot index b2a6905..3acf71b 100644 --- a/project.godot +++ b/project.godot @@ -13,6 +13,7 @@ config_version=5 config/name="NeonCollapse" run/main_scene="uid://cl0h2acqcq5wq" config/features=PackedStringArray("4.7", "GL Compatibility") +run/max_fps=240 config/icon="res://icon.svg" [audio] @@ -115,6 +116,7 @@ pause={ [physics] +common/physics_ticks_per_second=120 3d/physics_engine="Jolt Physics" [rendering]