From 88c7a0a055ac3c8e34f0c557532158f1c8ddba8a Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Sat, 30 Aug 2025 23:06:12 +0200 Subject: [PATCH] Movement refactor --- Mr. Brick Adventures.sln.DotSettings.user | 1 + objects/entities/brick_player.tscn | 83 ++++++--- objects/level/base_level.tscn | 13 +- .../movement_abilities/gravity_ability.tscn | 7 + .../movement_abilities/ground_ability.tscn | 9 + .../one_way_platform_ability.tscn | 7 + .../movement_abilities/spaceship_ability.tscn | 7 + .../variable_jump_ability.tscn | 8 + .../movement_abilities/wall_jump_ability.tscn | 7 + scenes/level_village_1.tscn | 13 +- scenes/level_village_2.tscn | 13 +- scenes/level_village_3.tscn | 6 +- scenes/level_village_4.tscn | 29 ++- scripts/components/BrickThrowComponent.cs | 4 +- scripts/components/JumpPadComponent.cs | 7 +- scripts/components/Movement/GravityAbility.cs | 28 +++ .../components/Movement/GravityAbility.cs.uid | 1 + .../Movement/GroundMovementAbility.cs | 26 +++ .../Movement/GroundMovementAbility.cs.uid | 1 + scripts/components/Movement/JumpAbility.cs | 41 +++++ .../components/Movement/JumpAbility.cs.uid | 1 + .../components/Movement/MovementAbility.cs | 38 ++++ .../Movement/MovementAbility.cs.uid | 1 + .../Movement/OneWayPlatformAbility.cs | 15 ++ .../Movement/OneWayPlatformAbility.cs.uid | 1 + .../components/Movement/PlayerInputHandler.cs | 28 +++ .../Movement/PlayerInputHandler.cs.uid | 1 + .../Movement/SpaceshipMovementAbility.cs | 29 +++ .../Movement/SpaceshipMovementAbility.cs.uid | 1 + .../Movement/VariableJumpAbility.cs | 68 +++++++ .../Movement/VariableJumpAbility.cs.uid | 1 + .../components/Movement/WallJumpAbility.cs | 37 ++++ .../Movement/WallJumpAbility.cs.uid | 1 + scripts/components/PlayerController.cs | 166 ++++++++++-------- scripts/components/PlayerSfxComponent.cs | 29 +++ scripts/components/PlayerSfxComponent.cs.uid | 1 + scripts/components/SpaceshipEnterComponent.cs | 3 +- scripts/components/SpaceshipExitComponent.cs | 3 +- scripts/components/SpriteTilterComponent.cs | 40 +++++ .../components/SpriteTilterComponent.cs.uid | 1 + scripts/components/StompDamageComponent.cs | 2 +- 41 files changed, 656 insertions(+), 122 deletions(-) create mode 100644 objects/movement_abilities/gravity_ability.tscn create mode 100644 objects/movement_abilities/ground_ability.tscn create mode 100644 objects/movement_abilities/one_way_platform_ability.tscn create mode 100644 objects/movement_abilities/spaceship_ability.tscn create mode 100644 objects/movement_abilities/variable_jump_ability.tscn create mode 100644 objects/movement_abilities/wall_jump_ability.tscn create mode 100644 scripts/components/Movement/GravityAbility.cs create mode 100644 scripts/components/Movement/GravityAbility.cs.uid create mode 100644 scripts/components/Movement/GroundMovementAbility.cs create mode 100644 scripts/components/Movement/GroundMovementAbility.cs.uid create mode 100644 scripts/components/Movement/JumpAbility.cs create mode 100644 scripts/components/Movement/JumpAbility.cs.uid create mode 100644 scripts/components/Movement/MovementAbility.cs create mode 100644 scripts/components/Movement/MovementAbility.cs.uid create mode 100644 scripts/components/Movement/OneWayPlatformAbility.cs create mode 100644 scripts/components/Movement/OneWayPlatformAbility.cs.uid create mode 100644 scripts/components/Movement/PlayerInputHandler.cs create mode 100644 scripts/components/Movement/PlayerInputHandler.cs.uid create mode 100644 scripts/components/Movement/SpaceshipMovementAbility.cs create mode 100644 scripts/components/Movement/SpaceshipMovementAbility.cs.uid create mode 100644 scripts/components/Movement/VariableJumpAbility.cs create mode 100644 scripts/components/Movement/VariableJumpAbility.cs.uid create mode 100644 scripts/components/Movement/WallJumpAbility.cs create mode 100644 scripts/components/Movement/WallJumpAbility.cs.uid create mode 100644 scripts/components/PlayerSfxComponent.cs create mode 100644 scripts/components/PlayerSfxComponent.cs.uid create mode 100644 scripts/components/SpriteTilterComponent.cs create mode 100644 scripts/components/SpriteTilterComponent.cs.uid diff --git a/Mr. Brick Adventures.sln.DotSettings.user b/Mr. Brick Adventures.sln.DotSettings.user index 122ad95..f213f4d 100644 --- a/Mr. Brick Adventures.sln.DotSettings.user +++ b/Mr. Brick Adventures.sln.DotSettings.user @@ -4,6 +4,7 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded diff --git a/objects/entities/brick_player.tscn b/objects/entities/brick_player.tscn index 7330bcf..445cd8e 100644 --- a/objects/entities/brick_player.tscn +++ b/objects/entities/brick_player.tscn @@ -1,12 +1,20 @@ -[gd_scene load_steps=48 format=3 uid="uid://bqi5s710xb1ju"] +[gd_scene load_steps=59 format=3 uid="uid://bqi5s710xb1ju"] [ext_resource type="Script" uid="uid://csel4s0e4g5uf" path="res://scripts/components/PlayerController.cs" id="1_yysbb"] [ext_resource type="Shader" uid="uid://bs4xvm4qkurpr" path="res://shaders/hit_flash.tres" id="2_lgb3u"] -[ext_resource type="Script" uid="uid://btlm1f3l70il" path="res://scripts/components/PlatformMovementComponent.cs" id="2_o1ihh"] +[ext_resource type="PackedScene" uid="uid://bcv8kx6bc7u5e" path="res://objects/movement_abilities/ground_ability.tscn" id="2_oefns"] [ext_resource type="Texture2D" uid="uid://jl1gwqchhpdc" path="res://sprites/left_eye.png" id="3_2srrh"] -[ext_resource type="Script" uid="uid://cty54itmnudfm" path="res://scripts/components/ShipMovementComponent.cs" id="3_ur2y5"] +[ext_resource type="PackedScene" uid="uid://d0r5edxnx5jqx" path="res://objects/movement_abilities/variable_jump_ability.tscn" id="3_bnap0"] +[ext_resource type="Script" uid="uid://bf4yclropol43" path="res://scripts/components/Movement/GroundMovementAbility.cs" id="4_7til7"] [ext_resource type="Texture2D" uid="uid://iiawtnwmeny3" path="res://sprites/right_eye.png" id="4_ccn81"] +[ext_resource type="PackedScene" uid="uid://cala7bpo1v4no" path="res://objects/movement_abilities/gravity_ability.tscn" id="4_qec3q"] +[ext_resource type="PackedScene" uid="uid://bty3jq8u0pxkf" path="res://objects/movement_abilities/one_way_platform_ability.tscn" id="5_dhjci"] [ext_resource type="Texture2D" uid="uid://0l454rfplmqg" path="res://sprites/MrBrick_base-sheet.png" id="5_yysbb"] +[ext_resource type="PackedScene" uid="uid://bu3vuxlrvoo1t" path="res://objects/movement_abilities/spaceship_ability.tscn" id="6_721q0"] +[ext_resource type="Script" uid="uid://chgw53qwt7rt8" path="res://scripts/components/Movement/GravityAbility.cs" id="6_xuhvf"] +[ext_resource type="Script" uid="uid://ccksp2e76s7sr" path="res://scripts/components/Movement/VariableJumpAbility.cs" id="7_bl1gx"] +[ext_resource type="PackedScene" uid="uid://chjbi5mgtwhsh" path="res://objects/movement_abilities/wall_jump_ability.tscn" id="7_bnap0"] +[ext_resource type="Script" uid="uid://ck6kmnbwhsttt" path="res://scripts/components/Movement/OneWayPlatformAbility.cs" id="7_uno3u"] [ext_resource type="Texture2D" uid="uid://dhkwyv6ayb5qb" path="res://sprites/flying_ship.png" id="8_6lsog"] [ext_resource type="Script" uid="uid://dy78ak8eykw6e" path="res://scripts/components/FlipComponent.cs" id="9_yysbb"] [ext_resource type="Script" uid="uid://mnjg3p0aw1ow" path="res://scripts/components/CanPickUpComponent.cs" id="10_yysbb"] @@ -38,6 +46,9 @@ [ext_resource type="PackedScene" uid="uid://dtem8jgcyoqar" path="res://objects/entities/green_laser.tscn" id="36_oxudy"] [ext_resource type="Script" uid="uid://diw6opv6yutgi" path="res://scripts/components/KillPlayerOutOfScreenComponent.cs" id="37_qec3q"] [ext_resource type="Script" uid="uid://3qy7rm28q66a" path="res://scripts/components/ProgressiveDamageComponent.cs" id="38_dhjci"] +[ext_resource type="Script" uid="uid://dssa2taiwktis" path="res://scripts/components/Movement/PlayerInputHandler.cs" id="42_e5pae"] +[ext_resource type="Script" uid="uid://ceoxet1nqws8w" path="res://scripts/components/SpriteTilterComponent.cs" id="43_xuhvf"] +[ext_resource type="Script" uid="uid://b1h8r5irryxcx" path="res://scripts/components/PlayerSfxComponent.cs" id="49_qec3q"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_xoue7"] shader = ExtResource("2_lgb3u") @@ -83,30 +94,39 @@ scale_curve = SubResource("CurveTexture_xoue7") color = Color(0.764706, 0.443137, 0, 1) color_ramp = SubResource("GradientTexture1D_lgb3u") -[node name="Brick Player" type="CharacterBody2D" node_paths=PackedStringArray("ShipSprite") groups=["player"]] +[node name="Brick Player" type="CharacterBody2D" node_paths=PackedStringArray("MovementAbilitiesContainer") groups=["player"]] collision_layer = 4 collision_mask = 43 script = ExtResource("1_yysbb") -MovementTypes = Dictionary[String, NodePath]({ -"platform": NodePath("Movements/PlatformMovement"), -"ship": NodePath("Movements/ShipMovement") -}) -ShipSprite = NodePath("Graphics/Ship") +MovementAbilitiesContainer = NodePath("Movements") +GroundMovementScene = ExtResource("2_oefns") +JumpMovementScene = ExtResource("3_bnap0") +GravityScene = ExtResource("4_qec3q") +OneWayPlatformScene = ExtResource("5_dhjci") +SpaceshipMovementScene = ExtResource("6_721q0") +WallJumpScene = ExtResource("7_bnap0") +metadata/_custom_type_script = "uid://csel4s0e4g5uf" [node name="Movements" type="Node" parent="."] -[node name="PlatformMovement" type="Node2D" parent="Movements" node_paths=PackedStringArray("JumpSfx", "RotationTarget", "Body")] -script = ExtResource("2_o1ihh") -JumpSfx = NodePath("../../sfx_jump") -RotationTarget = NodePath("../../Graphics/Root/Base") -Body = NodePath("../..") +[node name="GroundMovementAbility" type="Node" parent="Movements"] +script = ExtResource("4_7til7") +MaxSpeed = 376.0 +Friction = 2500.0 +metadata/_custom_type_script = "uid://bf4yclropol43" -[node name="ShipMovement" type="Node2D" parent="Movements" node_paths=PackedStringArray("Body")] -script = ExtResource("3_ur2y5") -MaxSpeed = 360.0 -Acceleration = 1200.0 -Friction = 800.0 -Body = NodePath("../..") +[node name="GravityAbility" type="Node" parent="Movements"] +script = ExtResource("6_xuhvf") +metadata/_custom_type_script = "uid://chgw53qwt7rt8" + +[node name="VariableJumpAbility" type="Node" parent="Movements"] +script = ExtResource("7_bl1gx") +JumpCutMultiplier = 0.507 +metadata/_custom_type_script = "uid://ccksp2e76s7sr" + +[node name="OneWayPlatformAbility" type="Node" parent="Movements"] +script = ExtResource("7_uno3u") +metadata/_custom_type_script = "uid://ck6kmnbwhsttt" [node name="Graphics" type="Node2D" parent="."] @@ -168,9 +188,8 @@ script = ExtResource("13_7til7") DeathSfx = NodePath("../sfx_hurt") HealthComponent = NodePath("../HealthComponent") -[node name="KnockbackComponent" type="Node" parent="." node_paths=PackedStringArray("Body", "HealthComponent")] +[node name="KnockbackComponent" type="Node" parent="." node_paths=PackedStringArray("HealthComponent")] script = ExtResource("14_e5pae") -Body = NodePath("..") KnockbackForce = 1250.0 HealthComponent = NodePath("../HealthComponent") @@ -196,11 +215,10 @@ Sprite = NodePath("../Graphics/Root/Right Eye") FlashDuration = 1.0 HealthComponent = NodePath("../HealthComponent") -[node name="StompDamageComponent" type="Node" parent="." node_paths=PackedStringArray("Area", "Root")] +[node name="StompDamageComponent" type="Node" parent="." node_paths=PackedStringArray("Area")] script = ExtResource("17_bl1gx") Damage = 4.0 Area = NodePath("../StompDamageArea") -Root = NodePath("..") [node name="SkillManager" type="Node" parent="."] script = ExtResource("18_6lsog") @@ -275,9 +293,22 @@ script = ExtResource("37_qec3q") ScreenNotifier = NodePath("../VisibleOnScreenNotifier2D") HealthComponent = NodePath("../HealthComponent") -[node name="ProgressiveDamageComponent" type="Node" parent="." node_paths=PackedStringArray("HealthComponent", "Sprite", "PlatformMovement")] +[node name="ProgressiveDamageComponent" type="Node" parent="." node_paths=PackedStringArray("HealthComponent", "Sprite")] process_mode = 4 script = ExtResource("38_dhjci") HealthComponent = NodePath("../HealthComponent") Sprite = NodePath("../Graphics/Root/Base") -PlatformMovement = NodePath("../Movements/PlatformMovement") + +[node name="PlayerInputHandler" type="Node" parent="."] +script = ExtResource("42_e5pae") +metadata/_custom_type_script = "uid://dssa2taiwktis" + +[node name="SpriteTilterComponent" type="Node" parent="." node_paths=PackedStringArray("RotationTarget")] +script = ExtResource("43_xuhvf") +RotationTarget = NodePath("../Graphics/Root/Base") +metadata/_custom_type_script = "uid://ceoxet1nqws8w" + +[node name="PlayerSfxComponent" type="Node" parent="." node_paths=PackedStringArray("JumpSfx")] +script = ExtResource("49_qec3q") +JumpSfx = NodePath("../sfx_jump") +metadata/_custom_type_script = "uid://b1h8r5irryxcx" diff --git a/objects/level/base_level.tscn b/objects/level/base_level.tscn index 8de9580..1761ec5 100644 --- a/objects/level/base_level.tscn +++ b/objects/level/base_level.tscn @@ -45,8 +45,8 @@ color_ramp = SubResource("GradientTexture1D_f1fvy") [sub_resource type="Resource" id="Resource_0nwt7"] script = ExtResource("7_kl81p") -duration = 1.0 -transition = 0 +duration = 0.25 +transition = 3 ease = 2 [node name="World" type="Node2D"] @@ -67,6 +67,7 @@ SkillUnlockerComponent = NodePath("../../Brick Player/SkillUnlockerComponent") [node name="Camera2D" parent="." instance=ExtResource("5_517ha")] physics_interpolation_mode = 1 +position = Vector2(32, -16) process_callback = 0 limit_left = -10000000 limit_top = -10000000 @@ -76,11 +77,17 @@ limit_bottom = 10000000 [node name="PhantomCamera" type="Node2D" parent="." node_paths=PackedStringArray("follow_target")] unique_name_in_owner = true top_level = true +position = Vector2(32, -16) script = ExtResource("6_6imqp") -follow_mode = 2 +follow_mode = 5 follow_target = NodePath("../Brick Player") snap_to_pixel = true tween_resource = SubResource("Resource_0nwt7") +follow_offset = Vector2(32, -16) +follow_damping = true +follow_damping_value = Vector2(0.15, 0.1) +dead_zone_width = 0.18 +dead_zone_height = 0.15 draw_limits = true metadata/_custom_type_script = "uid://d23haq52m7ulv" diff --git a/objects/movement_abilities/gravity_ability.tscn b/objects/movement_abilities/gravity_ability.tscn new file mode 100644 index 0000000..6a44968 --- /dev/null +++ b/objects/movement_abilities/gravity_ability.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=3 uid="uid://cala7bpo1v4no"] + +[ext_resource type="Script" uid="uid://chgw53qwt7rt8" path="res://scripts/components/Movement/GravityAbility.cs" id="1_tn5sj"] + +[node name="GravityAbility" type="Node"] +script = ExtResource("1_tn5sj") +metadata/_custom_type_script = "uid://chgw53qwt7rt8" diff --git a/objects/movement_abilities/ground_ability.tscn b/objects/movement_abilities/ground_ability.tscn new file mode 100644 index 0000000..18da366 --- /dev/null +++ b/objects/movement_abilities/ground_ability.tscn @@ -0,0 +1,9 @@ +[gd_scene load_steps=2 format=3 uid="uid://bcv8kx6bc7u5e"] + +[ext_resource type="Script" uid="uid://bf4yclropol43" path="res://scripts/components/Movement/GroundMovementAbility.cs" id="1_7efrb"] + +[node name="GroundAbility" type="Node"] +script = ExtResource("1_7efrb") +MaxSpeed = 376.0 +Friction = 2500.0 +metadata/_custom_type_script = "uid://bf4yclropol43" diff --git a/objects/movement_abilities/one_way_platform_ability.tscn b/objects/movement_abilities/one_way_platform_ability.tscn new file mode 100644 index 0000000..22ea481 --- /dev/null +++ b/objects/movement_abilities/one_way_platform_ability.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=3 uid="uid://bty3jq8u0pxkf"] + +[ext_resource type="Script" uid="uid://ck6kmnbwhsttt" path="res://scripts/components/Movement/OneWayPlatformAbility.cs" id="1_i0f5i"] + +[node name="OneWayPlatformAbility" type="Node"] +script = ExtResource("1_i0f5i") +metadata/_custom_type_script = "uid://ck6kmnbwhsttt" diff --git a/objects/movement_abilities/spaceship_ability.tscn b/objects/movement_abilities/spaceship_ability.tscn new file mode 100644 index 0000000..67e9e6f --- /dev/null +++ b/objects/movement_abilities/spaceship_ability.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=3 uid="uid://bu3vuxlrvoo1t"] + +[ext_resource type="Script" uid="uid://drgwa5q5k2tbm" path="res://scripts/components/Movement/SpaceshipMovementAbility.cs" id="1_u3vpp"] + +[node name="SpaceshipAbility" type="Node"] +script = ExtResource("1_u3vpp") +metadata/_custom_type_script = "uid://drgwa5q5k2tbm" diff --git a/objects/movement_abilities/variable_jump_ability.tscn b/objects/movement_abilities/variable_jump_ability.tscn new file mode 100644 index 0000000..4e22e4a --- /dev/null +++ b/objects/movement_abilities/variable_jump_ability.tscn @@ -0,0 +1,8 @@ +[gd_scene load_steps=2 format=3 uid="uid://d0r5edxnx5jqx"] + +[ext_resource type="Script" uid="uid://ccksp2e76s7sr" path="res://scripts/components/Movement/VariableJumpAbility.cs" id="1_y30i5"] + +[node name="VariableJumpAbility" type="Node"] +script = ExtResource("1_y30i5") +JumpCutMultiplier = 0.507 +metadata/_custom_type_script = "uid://ccksp2e76s7sr" diff --git a/objects/movement_abilities/wall_jump_ability.tscn b/objects/movement_abilities/wall_jump_ability.tscn new file mode 100644 index 0000000..96ac560 --- /dev/null +++ b/objects/movement_abilities/wall_jump_ability.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=3 uid="uid://chjbi5mgtwhsh"] + +[ext_resource type="Script" uid="uid://6foetukqmyoe" path="res://scripts/components/Movement/WallJumpAbility.cs" id="1_jjesg"] + +[node name="WallJumpAbility" type="Node"] +script = ExtResource("1_jjesg") +metadata/_custom_type_script = "uid://6foetukqmyoe" diff --git a/scenes/level_village_1.tscn b/scenes/level_village_1.tscn index d6f9f29..a721fd0 100644 --- a/scenes/level_village_1.tscn +++ b/scenes/level_village_1.tscn @@ -48,8 +48,8 @@ color_ramp = SubResource("GradientTexture1D_f1fvy") [sub_resource type="Resource" id="Resource_0nwt7"] script = ExtResource("7_80vn0") -duration = 1.0 -transition = 0 +duration = 0.25 +transition = 3 ease = 2 [node name="World" type="Node2D"] @@ -86,6 +86,7 @@ AudioSettingsControl = NodePath("../Audio settings") [node name="Camera2D" parent="." instance=ExtResource("5_sskgn")] physics_interpolation_mode = 1 +position = Vector2(32, -16) process_callback = 0 limit_left = -512 limit_top = -720 @@ -94,10 +95,16 @@ limit_bottom = 320 [node name="PhantomCamera2D" type="Node2D" parent="." node_paths=PackedStringArray("follow_target")] top_level = true +position = Vector2(32, -16) script = ExtResource("6_18aqg") -follow_mode = 2 +follow_mode = 5 follow_target = NodePath("../Brick Player") tween_resource = SubResource("Resource_0nwt7") +follow_offset = Vector2(32, -16) +follow_damping = true +follow_damping_value = Vector2(0.15, 0.1) +dead_zone_width = 0.18 +dead_zone_height = 0.15 draw_limits = true limit_target = NodePath("../Terrain Layer") metadata/_custom_type_script = "uid://d23haq52m7ulv" diff --git a/scenes/level_village_2.tscn b/scenes/level_village_2.tscn index 88384c3..ea87e51 100644 --- a/scenes/level_village_2.tscn +++ b/scenes/level_village_2.tscn @@ -50,8 +50,8 @@ color_ramp = SubResource("GradientTexture1D_f1fvy") [sub_resource type="Resource" id="Resource_0nwt7"] script = ExtResource("7_y1tp2") -duration = 1.0 -transition = 0 +duration = 0.25 +transition = 3 ease = 2 [node name="World" type="Node2D"] @@ -77,6 +77,7 @@ ComponentsToDisable = [NodePath("../../Brick Player")] [node name="Camera2D" parent="." instance=ExtResource("5_8nvkd")] physics_interpolation_mode = 1 +position = Vector2(32, -16) process_callback = 0 limit_left = -1952 limit_top = -1744 @@ -85,11 +86,17 @@ limit_bottom = 560 [node name="PhantomCamera2D" type="Node2D" parent="." node_paths=PackedStringArray("follow_target")] top_level = true +position = Vector2(32, -16) script = ExtResource("6_ono4h") -follow_mode = 2 +follow_mode = 5 follow_target = NodePath("../Brick Player") snap_to_pixel = true tween_resource = SubResource("Resource_0nwt7") +follow_offset = Vector2(32, -16) +follow_damping = true +follow_damping_value = Vector2(0.15, 0.1) +dead_zone_width = 0.18 +dead_zone_height = 0.15 draw_limits = true limit_target = NodePath("../Terrain Layer") metadata/_custom_type_script = "uid://d23haq52m7ulv" diff --git a/scenes/level_village_3.tscn b/scenes/level_village_3.tscn index 5b1d61c..8ce9e2c 100644 --- a/scenes/level_village_3.tscn +++ b/scenes/level_village_3.tscn @@ -232,7 +232,7 @@ color_ramp = SubResource("GradientTexture1D_f1fvy") [sub_resource type="Resource" id="Resource_lsjk3"] script = ExtResource("14_k7w2w") duration = 0.25 -transition = 0 +transition = 3 ease = 2 [node name="World" type="Node2D"] @@ -306,13 +306,15 @@ process_callback = 0 top_level = true position = Vector2(935, -134) script = ExtResource("13_01fjw") -follow_mode = 2 +follow_mode = 5 follow_target = NodePath("../Brick Player") snap_to_pixel = true tween_resource = SubResource("Resource_lsjk3") follow_offset = Vector2(32, -16) follow_damping = true follow_damping_value = Vector2(0.15, 0.1) +dead_zone_width = 0.18 +dead_zone_height = 0.15 draw_limits = true limit_target = NodePath("../Terrain Layer") metadata/_edit_lock_ = true diff --git a/scenes/level_village_4.tscn b/scenes/level_village_4.tscn index faa2604..b33ba22 100644 --- a/scenes/level_village_4.tscn +++ b/scenes/level_village_4.tscn @@ -31,7 +31,7 @@ diffuse_texture = SubResource("GradientTexture1D_e6jir") [sub_resource type="Resource" id="Resource_0nwt7"] script = ExtResource("7_57ky0") -duration = 1.0 +duration = 0.25 transition = 0 ease = 2 @@ -133,6 +133,7 @@ position = Vector2(1914, 8) [node name="Camera2D" parent="." instance=ExtResource("5_yqj3b")] physics_interpolation_mode = 1 +position = Vector2(32, -16) process_callback = 0 limit_left = -10000000 limit_top = -10000000 @@ -142,11 +143,16 @@ limit_bottom = 10000000 [node name="PhantomCamera" type="Node2D" parent="." node_paths=PackedStringArray("follow_target")] unique_name_in_owner = true top_level = true +position = Vector2(32, -16) script = ExtResource("6_i5rlu") -follow_mode = 2 +follow_mode = 5 follow_target = NodePath("../Brick Player") tween_resource = SubResource("Resource_0nwt7") +follow_offset = Vector2(32, -16) follow_damping = true +follow_damping_value = Vector2(0.15, 0.1) +dead_zone_width = 0.18 +dead_zone_height = 0.15 draw_limits = true metadata/_custom_type_script = "uid://d23haq52m7ulv" @@ -171,10 +177,24 @@ position = Vector2(7146.51, 21.1388) [node name="Brick Player" parent="." instance=ExtResource("1_k3uyd")] +[node name="GroundMovementAbility" parent="Brick Player/Movements" index="0"] +process_mode = 4 + +[node name="GravityAbility" parent="Brick Player/Movements" index="1"] +process_mode = 4 + +[node name="VariableJumpAbility" parent="Brick Player/Movements" index="2"] +process_mode = 4 + +[node name="OneWayPlatformAbility" parent="Brick Player/Movements" index="3"] +process_mode = 4 + [node name="HitParticles" parent="Brick Player" index="26"] process_material = SubResource("ParticleProcessMaterial_lgb3u") [node name="Enemies" type="Node2D" parent="."] +process_mode = 4 +visible = false [node name="Flying Enemy" parent="Enemies" instance=ExtResource("18_162yw")] position = Vector2(1122, -33) @@ -266,11 +286,10 @@ position = Vector2(16.5, -10) [connection signal="Death" from="Brick Player/HealthComponent" to="UI Layer/DeathScreen" method="OnPlayerDeath"] [connection signal="Death" from="Brick Player/HealthComponent" to="UI Layer/GameOverScreen" method="OnPlayerDeath"] [connection signal="SpaceshipEntered" from="Spaceship Enter" to="Chaser/ChaseLevelComponent" method="OnShipEntered"] -[connection signal="SpaceshipEntered" from="Spaceship Enter" to="Brick Player" method="OnSpaceshipEntered"] -[connection signal="SpaceshipEntered" from="Spaceship Enter" to="Brick Player/Movements/PlatformMovement" method="OnShipEntered"] +[connection signal="SpaceshipEntered" from="Spaceship Enter" to="Brick Player" method="SetSpaceshipMovement"] [connection signal="SpaceshipEntered" from="Spaceship Enter" to="Brick Player/ShipShooter" method="OnShipEntered"] [connection signal="SpaceshipExit" from="Spaceship exit" to="Chaser/ChaseLevelComponent" method="OnShipExited"] -[connection signal="SpaceshipExit" from="Spaceship exit" to="Brick Player" method="OnSpaceshipExited"] +[connection signal="SpaceshipExit" from="Spaceship exit" to="Brick Player" method="SetPlatformMovement"] [connection signal="SpaceshipExit" from="Spaceship exit" to="Brick Player/ShipShooter" method="OnShipExited"] [editable path="Chaser"] diff --git a/scripts/components/BrickThrowComponent.cs b/scripts/components/BrickThrowComponent.cs index df5189b..25fc6cb 100644 --- a/scripts/components/BrickThrowComponent.cs +++ b/scripts/components/BrickThrowComponent.cs @@ -64,13 +64,13 @@ public partial class BrickThrowComponent : Node, ISkill var instance = BrickScene.Instantiate(); var init = instance.GetNodeOrNull("ProjectileInitComponent"); - if (init != null && PlayerController.CurrentMovement is PlatformMovementComponent) + if (init != null) { var @params = new ProjectileInitParams() { Position = PlayerController.GlobalPosition, Rotation = PlayerController.Rotation, - Direction = PlayerController.CurrentMovement.LastDirection, + Direction = PlayerController.LastDirection, PowerMultiplier = powerMultiplier, }; diff --git a/scripts/components/JumpPadComponent.cs b/scripts/components/JumpPadComponent.cs index e203bf0..0ac6b96 100644 --- a/scripts/components/JumpPadComponent.cs +++ b/scripts/components/JumpPadComponent.cs @@ -21,10 +21,11 @@ public partial class JumpPadComponent : Node var canBeLaunched = body.GetNodeOrNull("CanBeLaunchedComponent"); if (canBeLaunched == null) return; - if (body is not PlayerController { CurrentMovement: PlatformMovementComponent movement }) return; + if (body is not PlayerController player) return; + _ = HandleLaunchPadAnimation(); - movement.Body.Velocity = new Vector2(movement.Body.Velocity.X, -JumpForce); - movement.JumpSfx?.Play(); + player.Velocity = new Vector2(player.Velocity.X, -JumpForce); + player.EmitSignal(PlayerController.SignalName.JumpInitiated); } private async Task HandleLaunchPadAnimation() diff --git a/scripts/components/Movement/GravityAbility.cs b/scripts/components/Movement/GravityAbility.cs new file mode 100644 index 0000000..6c60bc3 --- /dev/null +++ b/scripts/components/Movement/GravityAbility.cs @@ -0,0 +1,28 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +[GlobalClass] +public partial class GravityAbility : MovementAbility +{ + public float AscendGravity { get; set; } + public float DescendGravity { get; set; } + + private float _gravity; + + public override void Initialize(PlayerController controller) + { + base.Initialize(controller); + _gravity = (float)ProjectSettings.GetSetting("physics/2d/default_gravity"); + } + + public override Vector2 ProcessMovement(Vector2 velocity, double delta) + { + if (_body.IsOnFloor()) return velocity; + + var gravityToApply = velocity.Y < 0 ? AscendGravity : DescendGravity; + velocity.Y += gravityToApply * (float)delta; + + return velocity; + } +} \ No newline at end of file diff --git a/scripts/components/Movement/GravityAbility.cs.uid b/scripts/components/Movement/GravityAbility.cs.uid new file mode 100644 index 0000000..7ab4926 --- /dev/null +++ b/scripts/components/Movement/GravityAbility.cs.uid @@ -0,0 +1 @@ +uid://chgw53qwt7rt8 diff --git a/scripts/components/Movement/GroundMovementAbility.cs b/scripts/components/Movement/GroundMovementAbility.cs new file mode 100644 index 0000000..4931a76 --- /dev/null +++ b/scripts/components/Movement/GroundMovementAbility.cs @@ -0,0 +1,26 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +[GlobalClass] +public partial class GroundMovementAbility : MovementAbility +{ + [Export] public float MaxSpeed { get; set; } = 300.0f; + [Export] public float Acceleration { get; set; } = 2000.0f; + [Export] public float Friction { get; set; } = 1500.0f; + + public override Vector2 ProcessMovement(Vector2 velocity, double delta) + { + if (_input == null) return Vector2.Zero; + + var direction = _input.MoveDirection.X; + var targetSpeed = direction * MaxSpeed; + + if (direction != 0) + velocity.X = Mathf.MoveToward(velocity.X, targetSpeed, Acceleration * (float)delta); + else + velocity.X = Mathf.MoveToward(velocity.X, 0, Friction * (float)delta); + + return velocity; + } +} \ No newline at end of file diff --git a/scripts/components/Movement/GroundMovementAbility.cs.uid b/scripts/components/Movement/GroundMovementAbility.cs.uid new file mode 100644 index 0000000..9e119f4 --- /dev/null +++ b/scripts/components/Movement/GroundMovementAbility.cs.uid @@ -0,0 +1 @@ +uid://bf4yclropol43 diff --git a/scripts/components/Movement/JumpAbility.cs b/scripts/components/Movement/JumpAbility.cs new file mode 100644 index 0000000..c14b14e --- /dev/null +++ b/scripts/components/Movement/JumpAbility.cs @@ -0,0 +1,41 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +[GlobalClass] +public partial class JumpAbility : MovementAbility +{ + [Export] public float JumpVelocity { get; set; } = -400.0f; + [Export] public int CoyoteFrames { get; set; } = 6; + + private Timer _coyoteTimer; + private bool _wasOnFloor = false; + + public override void Initialize(PlayerController controller) + { + base.Initialize(controller); + _coyoteTimer = new Timer { OneShot = true, WaitTime = CoyoteFrames / (float)Engine.GetPhysicsTicksPerSecond() }; + AddChild(_coyoteTimer); + } + + public override Vector2 ProcessMovement(Vector2 velocity, double delta) + { + if (!_body.IsOnFloor() && _wasOnFloor) + { + _coyoteTimer.Start(); + } + + if (_input.JumpHeld) + { + if (_body.IsOnFloor() || !_coyoteTimer.IsStopped()) + { + velocity.Y = JumpVelocity; + _controller.EmitSignal(PlayerController.SignalName.JumpInitiated); + _coyoteTimer.Stop(); + } + } + + _wasOnFloor = _body.IsOnFloor(); + return velocity; + } +} \ No newline at end of file diff --git a/scripts/components/Movement/JumpAbility.cs.uid b/scripts/components/Movement/JumpAbility.cs.uid new file mode 100644 index 0000000..3282269 --- /dev/null +++ b/scripts/components/Movement/JumpAbility.cs.uid @@ -0,0 +1 @@ +uid://d0bb48upefu20 diff --git a/scripts/components/Movement/MovementAbility.cs b/scripts/components/Movement/MovementAbility.cs new file mode 100644 index 0000000..c521948 --- /dev/null +++ b/scripts/components/Movement/MovementAbility.cs @@ -0,0 +1,38 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +[GlobalClass] +public abstract partial class MovementAbility : Node +{ + protected PlayerController _controller; + protected CharacterBody2D _body; + protected PlayerInputHandler _input; + + public virtual void Initialize(PlayerController controller) + { + Name = $"{GetType().Name}"; + + _controller = controller; + if (_controller == null) + { + GD.PushError($"Movement ability '{Name}' must be a child of a PlayerController."); + SetProcess(false); + SetPhysicsProcess(false); + return; + } + + _body = _controller; + _input = _controller.GetNode("PlayerInputHandler"); + if (_input == null) + { + GD.PushError($"PlayerController '{_controller.Name}' must have a PlayerInputHandler child."); + SetProcess(false); + SetPhysicsProcess(false); + } + + _body.Velocity = Vector2.Zero; + } + + public abstract Vector2 ProcessMovement(Vector2 currentVelocity, double delta); +} \ No newline at end of file diff --git a/scripts/components/Movement/MovementAbility.cs.uid b/scripts/components/Movement/MovementAbility.cs.uid new file mode 100644 index 0000000..e278caf --- /dev/null +++ b/scripts/components/Movement/MovementAbility.cs.uid @@ -0,0 +1 @@ +uid://cmlwisjpoxk7f diff --git a/scripts/components/Movement/OneWayPlatformAbility.cs b/scripts/components/Movement/OneWayPlatformAbility.cs new file mode 100644 index 0000000..82d5db6 --- /dev/null +++ b/scripts/components/Movement/OneWayPlatformAbility.cs @@ -0,0 +1,15 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +[GlobalClass] +public partial class OneWayPlatformAbility : MovementAbility +{ + public override Vector2 ProcessMovement(Vector2 velocity, double delta) + { + if (_input.DownHeld && _controller != null) + _controller.Position += new Vector2(0, 1); + + return velocity; + } +} \ No newline at end of file diff --git a/scripts/components/Movement/OneWayPlatformAbility.cs.uid b/scripts/components/Movement/OneWayPlatformAbility.cs.uid new file mode 100644 index 0000000..53d8e25 --- /dev/null +++ b/scripts/components/Movement/OneWayPlatformAbility.cs.uid @@ -0,0 +1 @@ +uid://ck6kmnbwhsttt diff --git a/scripts/components/Movement/PlayerInputHandler.cs b/scripts/components/Movement/PlayerInputHandler.cs new file mode 100644 index 0000000..dd093d5 --- /dev/null +++ b/scripts/components/Movement/PlayerInputHandler.cs @@ -0,0 +1,28 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +[GlobalClass] +public partial class PlayerInputHandler : Node +{ + public Vector2 MoveDirection { get; private set; } = Vector2.Zero; + public bool JumpPressed { get; private set; } + public bool JumpReleased { get; private set; } + public bool JumpHeld { get; private set; } + public bool DownPressed { get; private set; } + public bool DownReleased { get; private set; } + public bool DownHeld { get; private set; } + + public override void _Process(double delta) + { + MoveDirection = Input.GetVector("left", "right", "up", "down"); + + JumpPressed = Input.IsActionJustPressed("jump"); + JumpReleased = Input.IsActionJustReleased("jump"); + JumpHeld = Input.IsActionPressed("jump"); + + DownPressed = Input.IsActionJustPressed("down"); + DownReleased = Input.IsActionJustReleased("down"); + DownHeld = Input.IsActionPressed("down"); + } +} \ No newline at end of file diff --git a/scripts/components/Movement/PlayerInputHandler.cs.uid b/scripts/components/Movement/PlayerInputHandler.cs.uid new file mode 100644 index 0000000..60681d3 --- /dev/null +++ b/scripts/components/Movement/PlayerInputHandler.cs.uid @@ -0,0 +1 @@ +uid://dssa2taiwktis diff --git a/scripts/components/Movement/SpaceshipMovementAbility.cs b/scripts/components/Movement/SpaceshipMovementAbility.cs new file mode 100644 index 0000000..aea5baa --- /dev/null +++ b/scripts/components/Movement/SpaceshipMovementAbility.cs @@ -0,0 +1,29 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +[GlobalClass] +public partial class SpaceshipMovementAbility : MovementAbility +{ + [Export] public float MaxSpeed { get; set; } = 300f; + [Export] public float Acceleration { get; set; } = 2000f; + [Export] public float Friction { get; set; } = 1700f; + + public override Vector2 ProcessMovement(Vector2 currentVelocity, double delta) + { + if (_input == null) return Vector2.Zero; + + var inputVector = _input.MoveDirection; + + if (inputVector != Vector2.Zero) + { + currentVelocity = currentVelocity.MoveToward(inputVector * MaxSpeed, Acceleration * (float)delta); + } + else + { + currentVelocity = currentVelocity.MoveToward(Vector2.Zero, Friction * (float)delta); + } + + return currentVelocity; + } +} \ No newline at end of file diff --git a/scripts/components/Movement/SpaceshipMovementAbility.cs.uid b/scripts/components/Movement/SpaceshipMovementAbility.cs.uid new file mode 100644 index 0000000..7f5e46a --- /dev/null +++ b/scripts/components/Movement/SpaceshipMovementAbility.cs.uid @@ -0,0 +1 @@ +uid://drgwa5q5k2tbm diff --git a/scripts/components/Movement/VariableJumpAbility.cs b/scripts/components/Movement/VariableJumpAbility.cs new file mode 100644 index 0000000..4b173e2 --- /dev/null +++ b/scripts/components/Movement/VariableJumpAbility.cs @@ -0,0 +1,68 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +[GlobalClass] +public partial class VariableJumpAbility : MovementAbility +{ + [ExportGroup("Jump Design")] + [Export] public float JumpHeight { get; set; } = 100f; + [Export] public float JumpTimeToPeak { get; set; } = 0.5f; + [Export] public float JumpTimeToDescent { get; set; } = 0.4f; + + [ExportGroup("Jump Feel")] + // How much to reduce upward velocity when the jump button is released mid-air. + [Export(PropertyHint.Range, "0.0, 1.0, 0.05")] public float JumpCutMultiplier { get; set; } = 0.5f; + [Export(PropertyHint.Range, "0,10,1")] public int CoyoteFrames { get; set; } = 6; + + private float _jumpVelocity; + private bool _wasOnFloor = false; + private bool _hasJumpedInAir = false; + private Timer _coyoteTimer; + + public float AscendGravity { get; private set; } + public float DescendGravity { get; private set; } + + public override void Initialize(PlayerController controller) + { + base.Initialize(controller); + + _jumpVelocity = (2.0f * JumpHeight) / JumpTimeToPeak * -1.0f; + AscendGravity = (-2.0f * JumpHeight) / (JumpTimeToPeak * JumpTimeToPeak) * -1.0f; + DescendGravity = (-2.0f * JumpHeight) / (JumpTimeToDescent * JumpTimeToDescent) * -1.0f; + + _coyoteTimer = new Timer { OneShot = true, WaitTime = CoyoteFrames / (float)Engine.GetPhysicsTicksPerSecond() }; + AddChild(_coyoteTimer); + } + + + public override Vector2 ProcessMovement(Vector2 velocity, double delta) + { + var isGrounded = _body.IsOnFloor(); + + if (!isGrounded && _wasOnFloor) _coyoteTimer.Start(); + if (isGrounded) _hasJumpedInAir = false; + + if (_input.JumpHeld && !_hasJumpedInAir) + { + if (isGrounded || !_coyoteTimer.IsStopped()) + { + velocity.Y = _jumpVelocity; + _controller.EmitSignal(PlayerController.SignalName.JumpInitiated); + _coyoteTimer.Stop(); + _hasJumpedInAir = true; + } + } + + if (_input.JumpReleased) + { + if (velocity.Y < 0.0f) + { + velocity.Y *= JumpCutMultiplier; + } + } + + _wasOnFloor = isGrounded; + return velocity; + } +} \ No newline at end of file diff --git a/scripts/components/Movement/VariableJumpAbility.cs.uid b/scripts/components/Movement/VariableJumpAbility.cs.uid new file mode 100644 index 0000000..0d5796b --- /dev/null +++ b/scripts/components/Movement/VariableJumpAbility.cs.uid @@ -0,0 +1 @@ +uid://ccksp2e76s7sr diff --git a/scripts/components/Movement/WallJumpAbility.cs b/scripts/components/Movement/WallJumpAbility.cs new file mode 100644 index 0000000..eaa58ae --- /dev/null +++ b/scripts/components/Movement/WallJumpAbility.cs @@ -0,0 +1,37 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +[GlobalClass] +public partial class WallJumpAbility : MovementAbility +{ + [ExportGroup("Wall Jump Design")] + [Export] public Vector2 WallJumpVelocity { get; set; } = new(500.0f, -350.0f); + + [ExportGroup("Wall Slide Feel")] + [Export(PropertyHint.Range, "0.0, 1.0, 0.05")] public float WallSlideGravityMultiplier { get; set; } = 0.7f; + [Export] public float MaxWallSlideSpeed { get; set; } = 150.0f; + + public override Vector2 ProcessMovement(Vector2 velocity, double delta) + { + var isOnWall = _body.IsOnWall(); + + if (isOnWall && !_body.IsOnFloor() && velocity.Y > 0f) + { + var gravity = (float)ProjectSettings.GetSetting("physics/2d/default_gravity"); + var newYVelocity = velocity.Y + gravity * WallSlideGravityMultiplier * (float)delta; + + velocity.Y = Mathf.Min(newYVelocity, MaxWallSlideSpeed); + } + + if (isOnWall && _input.JumpHeld) + { + var wallNormal = _body.GetWallNormal(); + + _controller.EmitSignal(PlayerController.SignalName.JumpInitiated); + velocity = new Vector2(wallNormal.X * WallJumpVelocity.X, WallJumpVelocity.Y); + } + + return velocity; + } +} \ No newline at end of file diff --git a/scripts/components/Movement/WallJumpAbility.cs.uid b/scripts/components/Movement/WallJumpAbility.cs.uid new file mode 100644 index 0000000..e4abe99 --- /dev/null +++ b/scripts/components/Movement/WallJumpAbility.cs.uid @@ -0,0 +1 @@ +uid://6foetukqmyoe diff --git a/scripts/components/PlayerController.cs b/scripts/components/PlayerController.cs index dd5387a..1a4ee5f 100644 --- a/scripts/components/PlayerController.cs +++ b/scripts/components/PlayerController.cs @@ -1,103 +1,125 @@ using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; using Godot; -using Mr.BrickAdventures.scripts.interfaces; namespace Mr.BrickAdventures.scripts.components; +[GlobalClass] public partial class PlayerController : CharacterBody2D { - [Export] - public string DefaultMovementType { get; set; } = "platform"; - - [Export] - public Godot.Collections.Dictionary MovementTypes { get; set; } - - [Export] - public Sprite2D ShipSprite { get; set; } - - public IMovement CurrentMovement = null; - [Signal] - public delegate void MovementSwitchedEventHandler(string movementType); - + [Export] private Node MovementAbilitiesContainer { get; set; } + + [ExportGroup("Movement Ability Scenes")] + [Export] public PackedScene GroundMovementScene { get; set; } + [Export] public PackedScene JumpMovementScene { get; set; } + [Export] public PackedScene GravityScene { get; set; } + [Export] public PackedScene OneWayPlatformScene { get; set; } + [Export] public PackedScene SpaceshipMovementScene { get; set; } + [Export] public PackedScene WallJumpScene { get; set; } + + [Signal] public delegate void JumpInitiatedEventHandler(); + + public Vector2 LastDirection { get; private set; } = Vector2.Right; + public Vector2 PreviousVelocity { get; private set; } = Vector2.Zero; + + private List _abilities = []; + private PlayerInputHandler _inputHandler; + public override void _Ready() { - base._Ready(); - - foreach (var movementType in MovementTypes.Keys) + _inputHandler = GetNode("PlayerInputHandler"); + foreach (var child in MovementAbilitiesContainer.GetChildren()) { - var movementNode = GetNodeOrNull(movementType); - if (movementNode is IMovement playerMovement) + if (child is MovementAbility ability) { - playerMovement.Enabled = false; + ability.Initialize(this); + _abilities.Add(ability); } } - - SwitchMovement(DefaultMovementType); + + _ = ConnectJumpAndGravityAbilities(); } - - public override void _UnhandledInput(InputEvent @event) + + public override void _PhysicsProcess(double delta) { - base._UnhandledInput(@event); - - if (@event is InputEventKey inputEventKey && inputEventKey.IsActionPressed("switch_movement")) + var velocity = Velocity; + + foreach (var ability in _abilities) { - var nextMovementType = GetNextMovementType(); - SwitchMovement(nextMovementType); + velocity = ability.ProcessMovement(velocity, delta); } - } - - private void SwitchMovement(string movementType) - { - if (CurrentMovement != null) + + if (_inputHandler.MoveDirection.X != 0) { - CurrentMovement.Enabled = false; + LastDirection = new Vector2(_inputHandler.MoveDirection.X > 0 ? 1 : -1, 0); } - if (MovementTypes.TryGetValue(movementType, out var movement)) + PreviousVelocity = Velocity; + Velocity = velocity; + MoveAndSlide(); + } + + public void AddAbility(MovementAbility ability) + { + MovementAbilitiesContainer.AddChild(ability); + ability.Initialize(this); + _abilities.Add(ability); + } + + private void ClearMovementAbilities() + { + foreach (var ability in _abilities) { - CurrentMovement = GetNodeOrNull(movement); - if (CurrentMovement == null) + ability.QueueFree(); + } + _abilities.Clear(); + } + + public void RemoveAbility() where T : MovementAbility + { + for (var i = _abilities.Count - 1; i >= 0; i--) + { + if (_abilities[i] is T) { - GD.PushError($"Movement type '{movementType}' not found in MovementTypes."); - return; + var ability = _abilities[i]; + _abilities.RemoveAt(i); + ability.QueueFree(); + break; } - CurrentMovement.Enabled = true; - EmitSignalMovementSwitched(movementType); - } - else - { - GD.PushError($"Movement type '{movementType}' not found in MovementTypes."); - } - - if (CurrentMovement == null) - { - GD.PushError("No current movement set after switching."); } } - private string GetNextMovementType() + public void SetPlatformMovement() { - var keys = new List(MovementTypes.Keys); - var currentIndex = keys.IndexOf(CurrentMovement?.MovementType); - - if (currentIndex == -1) + ClearMovementAbilities(); + + if (GroundMovementScene != null) AddAbility(GroundMovementScene.Instantiate()); + if (JumpMovementScene != null) AddAbility(JumpMovementScene.Instantiate()); + if (GravityScene != null) AddAbility(GravityScene.Instantiate()); + if (OneWayPlatformScene != null) AddAbility(OneWayPlatformScene.Instantiate()); + + _ = ConnectJumpAndGravityAbilities(); + } + + public void SetSpaceshipMovement() + { + ClearMovementAbilities(); + + if (SpaceshipMovementScene != null) AddAbility(SpaceshipMovementScene.Instantiate()); + } + + private async Task ConnectJumpAndGravityAbilities() + { + await ToSignal(GetTree(), SceneTree.SignalName.ProcessFrame); + + var jumpAbility = _abilities.OfType().FirstOrDefault(); + var gravityAbility = _abilities.OfType().FirstOrDefault(); + + if (jumpAbility != null && gravityAbility != null) { - return DefaultMovementType; + gravityAbility.AscendGravity = jumpAbility.AscendGravity; + gravityAbility.DescendGravity = jumpAbility.DescendGravity; } - - currentIndex = (currentIndex + 1) % keys.Count; - return keys[currentIndex]; - } - - public void OnSpaceshipEntered() - { - SwitchMovement("ship"); - ShipSprite.Visible = true; - } - - public void OnSpaceshipExited() - { - SwitchMovement(DefaultMovementType); - ShipSprite.Visible = false; } } \ No newline at end of file diff --git a/scripts/components/PlayerSfxComponent.cs b/scripts/components/PlayerSfxComponent.cs new file mode 100644 index 0000000..28f3e3f --- /dev/null +++ b/scripts/components/PlayerSfxComponent.cs @@ -0,0 +1,29 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +[GlobalClass] +public partial class PlayerSfxComponent : Node +{ + [Export] public AudioStreamPlayer2D JumpSfx { get; set; } + + private PlayerController _controller; + + public override void _Ready() + { + _controller = GetOwner(); + if (_controller == null) + { + GD.PrintErr("PlayerSfxComponent must be a child of a PlayerController."); + SetProcess(false); + } + + _controller.JumpInitiated += OnJumpInitiated; + } + + private void OnJumpInitiated() + { + if (JumpSfx is { Playing: false }) + JumpSfx.Play(); + } +} \ No newline at end of file diff --git a/scripts/components/PlayerSfxComponent.cs.uid b/scripts/components/PlayerSfxComponent.cs.uid new file mode 100644 index 0000000..1409f77 --- /dev/null +++ b/scripts/components/PlayerSfxComponent.cs.uid @@ -0,0 +1 @@ +uid://b1h8r5irryxcx diff --git a/scripts/components/SpaceshipEnterComponent.cs b/scripts/components/SpaceshipEnterComponent.cs index 16b246e..b14e467 100644 --- a/scripts/components/SpaceshipEnterComponent.cs +++ b/scripts/components/SpaceshipEnterComponent.cs @@ -13,7 +13,8 @@ public partial class SpaceshipEnterComponent : Area2D private void OnBodyEntered(Node2D body) { - if (body is not PlayerController) return; + if (body is not PlayerController player) return; + player.SetSpaceshipMovement(); EmitSignalSpaceshipEntered(); QueueFree(); } diff --git a/scripts/components/SpaceshipExitComponent.cs b/scripts/components/SpaceshipExitComponent.cs index 6d75270..8b0555e 100644 --- a/scripts/components/SpaceshipExitComponent.cs +++ b/scripts/components/SpaceshipExitComponent.cs @@ -13,7 +13,8 @@ public partial class SpaceshipExitComponent : Area2D private void OnBodyEntered(Node2D body) { - if (body is not PlayerController) return; + if (body is not PlayerController player) return; EmitSignalSpaceshipExit(); + player.SetPlatformMovement(); } } \ No newline at end of file diff --git a/scripts/components/SpriteTilterComponent.cs b/scripts/components/SpriteTilterComponent.cs new file mode 100644 index 0000000..bc4313f --- /dev/null +++ b/scripts/components/SpriteTilterComponent.cs @@ -0,0 +1,40 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +[GlobalClass] +public partial class SpriteTilterComponent : Node +{ + [Export] public Node2D RotationTarget { get; set; } + [Export(PropertyHint.Range, "0,45,1")] public float MaxTiltAngle { get; set; } = 10.0f; + + private CharacterBody2D _body; + + public override void _Ready() + { + _body = GetOwner(); + if (_body == null) + { + GD.PrintErr("SpriteTilterComponent must be a direct child of a CharacterBody2D."); + SetProcess(false); + } + if (RotationTarget == null) + { + GD.PrintErr("SpriteTilterComponent needs a RotationTarget to be set in the inspector."); + SetProcess(false); + } + } + + public override void _Process(double delta) + { + var targetAngleRad = 0.0f; + var horizontalVelocity = _body.Velocity.X; + + if (horizontalVelocity > 0.1f) + targetAngleRad = -Mathf.DegToRad(MaxTiltAngle); + else if (horizontalVelocity < -0.1f) targetAngleRad = Mathf.DegToRad(MaxTiltAngle); + else targetAngleRad = 0.0f; + + RotationTarget.Rotation = targetAngleRad; + } +} \ No newline at end of file diff --git a/scripts/components/SpriteTilterComponent.cs.uid b/scripts/components/SpriteTilterComponent.cs.uid new file mode 100644 index 0000000..e221b90 --- /dev/null +++ b/scripts/components/SpriteTilterComponent.cs.uid @@ -0,0 +1 @@ +uid://ceoxet1nqws8w diff --git a/scripts/components/StompDamageComponent.cs b/scripts/components/StompDamageComponent.cs index 9f16b26..0efe228 100644 --- a/scripts/components/StompDamageComponent.cs +++ b/scripts/components/StompDamageComponent.cs @@ -23,7 +23,7 @@ public partial class StompDamageComponent : Node if (!(Root.GlobalPosition.Y < body.GlobalPosition.Y)) return; - var velocity = Root.CurrentMovement.PreviousVelocity; + var velocity = Root.PreviousVelocity; if (!(velocity.Y > 0f)) return; DealDamage(health);