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);