feat: Implement a skill pickup system with a new collectable type, event handling, and dedicated pickup objects.
This commit is contained in:
@@ -82,6 +82,7 @@ public partial class EventBus : Node
|
||||
[Signal] public delegate void CoinCollectedEventHandler(int amount, Vector2 position);
|
||||
[Signal] public delegate void ItemCollectedEventHandler(CollectableType itemType, float amount, Vector2 position);
|
||||
[Signal] public delegate void ChildRescuedEventHandler(Vector2 position);
|
||||
[Signal] public delegate void SkillCollectedEventHandler(SkillData skill, Vector2 position);
|
||||
|
||||
public static void EmitCoinCollected(int amount, Vector2 position)
|
||||
=> Instance?.EmitSignal(SignalName.CoinCollected, amount, position);
|
||||
@@ -92,6 +93,9 @@ public partial class EventBus : Node
|
||||
public static void EmitChildRescued(Vector2 position)
|
||||
=> Instance?.EmitSignal(SignalName.ChildRescued, position);
|
||||
|
||||
public static void EmitSkillCollected(SkillData skill, Vector2 position)
|
||||
=> Instance?.EmitSignal(SignalName.SkillCollected, skill, position);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Skill Events
|
||||
|
||||
34
objects/entities/double_jump_skill_pickup.tscn
Normal file
34
objects/entities/double_jump_skill_pickup.tscn
Normal file
@@ -0,0 +1,34 @@
|
||||
[gd_scene load_steps=6 format=3 uid="uid://dk2cu8qs7odib"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://djifxc5x0dyrw" path="res://sprites/ppc_tileset.png" id="1_214vd"]
|
||||
[ext_resource type="Script" uid="uid://r4jybneigfcn" path="res://scripts/components/CollectableComponent.cs" id="2_h7fi3"]
|
||||
[ext_resource type="Script" uid="uid://bjln6jb1sigx2" path="res://scripts/components/FadeAwayComponent.cs" id="3_b687r"]
|
||||
[ext_resource type="Resource" path="res://resources/collectables/double_jump_pickup.tres" id="3_h7fi3"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_pickup"]
|
||||
radius = 12.0
|
||||
|
||||
[node name="SkillPickup" type="Area2D" groups=["Collectables"]]
|
||||
collision_layer = 2
|
||||
collision_mask = 4
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource("CircleShape2D_pickup")
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||
texture = ExtResource("1_214vd")
|
||||
hframes = 12
|
||||
vframes = 12
|
||||
frame = 24
|
||||
|
||||
[node name="CollectableComponent" type="Node" parent="." node_paths=PackedStringArray("Area2D", "CollisionShape")]
|
||||
script = ExtResource("2_h7fi3")
|
||||
Area2D = NodePath("..")
|
||||
CollisionShape = NodePath("../CollisionShape2D")
|
||||
Data = ExtResource("3_h7fi3")
|
||||
|
||||
[node name="FadeAwayComponent" type="Node" parent="." node_paths=PackedStringArray("Sprite", "Area")]
|
||||
script = ExtResource("3_b687r")
|
||||
Sprite = NodePath("../Sprite2D")
|
||||
FadeDuration = 0.5
|
||||
Area = NodePath("..")
|
||||
32
objects/entities/skill_pickup.tscn
Normal file
32
objects/entities/skill_pickup.tscn
Normal file
@@ -0,0 +1,32 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://0idmnkwids1r"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://djifxc5x0dyrw" path="res://sprites/ppc_tileset.png" id="1_sprite"]
|
||||
[ext_resource type="Script" uid="uid://r4jybneigfcn" path="res://scripts/components/CollectableComponent.cs" id="2_collectable"]
|
||||
[ext_resource type="Script" uid="uid://bjln6jb1sigx2" path="res://scripts/components/FadeAwayComponent.cs" id="3_fadeaway"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_pickup"]
|
||||
radius = 12.0
|
||||
|
||||
[node name="SkillPickup" type="Area2D" groups=["Collectables"]]
|
||||
collision_layer = 2
|
||||
collision_mask = 4
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource("CircleShape2D_pickup")
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||
texture = ExtResource("1_sprite")
|
||||
hframes = 12
|
||||
vframes = 12
|
||||
frame = 24
|
||||
|
||||
[node name="CollectableComponent" type="Node" parent="." node_paths=PackedStringArray("Area2D", "CollisionShape")]
|
||||
script = ExtResource("2_collectable")
|
||||
Area2D = NodePath("..")
|
||||
CollisionShape = NodePath("../CollisionShape2D")
|
||||
|
||||
[node name="FadeAwayComponent" type="Node" parent="." node_paths=PackedStringArray("Sprite", "Area")]
|
||||
script = ExtResource("3_fadeaway")
|
||||
Sprite = NodePath("../Sprite2D")
|
||||
FadeDuration = 0.5
|
||||
Area = NodePath("..")
|
||||
@@ -49,6 +49,7 @@ StatisticsEventHandler="*res://scripts/Events/StatisticsEventHandler.cs"
|
||||
CoinStateHandler="*res://scripts/Events/CoinStateHandler.cs"
|
||||
LevelStateHandler="*res://scripts/Events/LevelStateHandler.cs"
|
||||
LivesStateHandler="*res://scripts/Events/LivesStateHandler.cs"
|
||||
SkillCollectHandler="*res://scripts/Events/SkillCollectHandler.cs"
|
||||
GameStateStore="*res://Autoloads/GameStateStore.cs"
|
||||
GameManager="*res://objects/game_manager.tscn"
|
||||
|
||||
|
||||
10
resources/collectables/double_jump_pickup.tres
Normal file
10
resources/collectables/double_jump_pickup.tres
Normal file
@@ -0,0 +1,10 @@
|
||||
[gd_resource type="Resource" script_class="CollectableResource" load_steps=3 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/Resources/CollectableResource.cs" id="1_script"]
|
||||
[ext_resource type="Resource" uid="uid://bxsgq8703qx4u" path="res://resources/skills/double_jump.tres" id="2_skill"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_script")
|
||||
Amount = 0.0
|
||||
Type = 3
|
||||
Skill = ExtResource("2_skill")
|
||||
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=33 format=4 uid="uid://h60obxmju6mo"]
|
||||
[gd_scene load_steps=34 format=4 uid="uid://h60obxmju6mo"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://dyp4i4ru2j2jh" path="res://objects/fxs/explosion_fx.tscn" id="1_p30ax"]
|
||||
[ext_resource type="PackedScene" uid="uid://dx80ivlvuuew4" path="res://objects/fxs/fire_fx.tscn" id="2_a7yjf"]
|
||||
@@ -23,6 +23,7 @@
|
||||
[ext_resource type="PackedScene" uid="uid://bqom4cm7r18db" path="res://objects/entities/killzone.tscn" id="21_p30ax"]
|
||||
[ext_resource type="PackedScene" uid="uid://12jnkdygpxwc" path="res://objects/entities/exit_level.tscn" id="22_a7yjf"]
|
||||
[ext_resource type="PackedScene" uid="uid://t6h2ra7kjyq" path="res://objects/entities/small_heal_potion.tscn" id="23_m6h4x"]
|
||||
[ext_resource type="PackedScene" uid="uid://dk2cu8qs7odib" path="res://objects/entities/double_jump_skill_pickup.tscn" id="24_6fdf4"]
|
||||
|
||||
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_j7bvy"]
|
||||
texture = ExtResource("7_uvxky")
|
||||
@@ -300,7 +301,7 @@ z_index = 5
|
||||
position = Vector2(903, -118)
|
||||
metadata/_edit_group_ = true
|
||||
|
||||
[node name="HitParticles" parent="Brick Player" index="24"]
|
||||
[node name="HitParticles" parent="Brick Player" index="23"]
|
||||
process_material = SubResource("ParticleProcessMaterial_lgb3u")
|
||||
|
||||
[node name="Camera2D" parent="." instance=ExtResource("12_qhkyq")]
|
||||
@@ -364,6 +365,9 @@ position = Vector2(1359, -42)
|
||||
[node name="Killzone" parent="." instance=ExtResource("21_p30ax")]
|
||||
position = Vector2(2456, 815)
|
||||
|
||||
[node name="SkillPickup" parent="." instance=ExtResource("24_6fdf4")]
|
||||
position = Vector2(1136, -109)
|
||||
|
||||
[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"]
|
||||
|
||||
|
||||
44
scripts/Events/SkillCollectHandler.cs
Normal file
44
scripts/Events/SkillCollectHandler.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using Godot;
|
||||
using Mr.BrickAdventures.Autoloads;
|
||||
using Mr.BrickAdventures.scripts.Resources;
|
||||
|
||||
namespace Mr.BrickAdventures.scripts.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Handles skill collection events and unlocks skills via GameStateStore.
|
||||
/// Skills are immediately activated but only persisted on level complete.
|
||||
/// </summary>
|
||||
public partial class SkillCollectHandler : Node
|
||||
{
|
||||
private SkillManager _skillManager;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_skillManager = GetNode<SkillManager>(Constants.SkillManagerPath);
|
||||
EventBus.Instance.SkillCollected += OnSkillCollected;
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
if (EventBus.Instance != null)
|
||||
{
|
||||
EventBus.Instance.SkillCollected -= OnSkillCollected;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSkillCollected(SkillData skill, Vector2 position)
|
||||
{
|
||||
if (skill == null) return;
|
||||
|
||||
// Unlock in session (will be committed on level complete, lost on death)
|
||||
GameStateStore.Instance?.UnlockSkillInSession(skill);
|
||||
|
||||
// Immediately activate the skill for the player
|
||||
skill.IsActive = true;
|
||||
skill.Level = 1;
|
||||
_skillManager?.AddSkill(skill);
|
||||
|
||||
// Emit skill unlocked event for UI/achievements
|
||||
EventBus.EmitSkillUnlocked(skill.Name, skill.Level);
|
||||
}
|
||||
}
|
||||
1
scripts/Events/SkillCollectHandler.cs.uid
Normal file
1
scripts/Events/SkillCollectHandler.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://c1po4hjvqbslm
|
||||
@@ -6,4 +6,9 @@ public partial class CollectableResource : Resource
|
||||
{
|
||||
[Export] public float Amount { get; set; } = 0.0f;
|
||||
[Export] public CollectableType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The skill to unlock when collected. Only used when Type is Skill.
|
||||
/// </summary>
|
||||
[Export] public SkillData Skill { get; set; }
|
||||
}
|
||||
@@ -5,4 +5,5 @@ public enum CollectableType
|
||||
Coin,
|
||||
Kid,
|
||||
Health,
|
||||
Skill,
|
||||
}
|
||||
@@ -64,6 +64,13 @@ public partial class CollectableComponent : Node
|
||||
_floatingTextManager?.ShowMessage("Rescued!", ownerNode.GlobalPosition);
|
||||
EventBus.EmitChildRescued(ownerNode.GlobalPosition);
|
||||
break;
|
||||
case CollectableType.Skill:
|
||||
if (Data.Skill != null)
|
||||
{
|
||||
_floatingTextManager?.ShowMessage($"{Data.Skill.Name} Unlocked!", ownerNode.GlobalPosition);
|
||||
EventBus.EmitSkillCollected(Data.Skill, ownerNode.GlobalPosition);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
EventBus.EmitItemCollected(Data.Type, Data.Amount, ownerNode.GlobalPosition);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user