Add achievement system with unlock and UI popup functionality (#8)

This commit is contained in:
2025-08-31 00:50:53 +02:00
committed by GitHub
parent 88c7a0a055
commit 53b5f968fd
46 changed files with 464 additions and 243 deletions

View File

@@ -0,0 +1,13 @@
using Godot;
namespace Mr.BrickAdventures.scripts.Resources;
[GlobalClass]
public partial class AchievementResource : Resource
{
[Export] public string Id { get; set; } = ""; // e.g., "level_1_complete"
[Export] public string DisplayName { get; set; } = "New Achievement";
[Export(PropertyHint.MultilineText)] public string Description { get; set; } = "";
[Export] public Texture2D Icon { get; set; }
[Export] public bool IsSecret { get; set; } = false;
}

View File

@@ -0,0 +1 @@
uid://duib5phrmpro5

View File

@@ -0,0 +1,52 @@
using System.Threading.Tasks;
using Godot;
using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.scripts.UI;
[GlobalClass]
public partial class AchievementPopup : CanvasLayer
{
[Export] public Label TitleLabel { get; set; }
[Export] public Label DescriptionLabel { get; set; }
[Export] public TextureRect IconRect { get; set; }
[Export] public float DisplayDuration { get; set; } = 3.0f;
private Control _container;
private Vector2 _startPosition;
private Vector2 _onScreenPosition;
public override void _Ready()
{
_container = GetNode<Control>("Container");
_startPosition = new Vector2(_container.Position.X, -_container.Size.Y - 50);
_onScreenPosition = _container.Position;
_container.Position = _startPosition;
}
public async Task ShowAchievement(AchievementResource achievement)
{
TitleLabel.Text = achievement.DisplayName;
DescriptionLabel.Text = achievement.Description;
IconRect.Texture = achievement.Icon;
var tween = CreateTween();
tween.TweenProperty(_container, "position", _onScreenPosition, 0.5f)
.SetTrans(Tween.TransitionType.Cubic)
.SetEase(Tween.EaseType.Out);
await ToSignal(tween, Tween.SignalName.Finished);
await ToSignal(GetTree().CreateTimer(DisplayDuration), Timer.SignalName.Timeout);
tween = CreateTween();
tween.TweenProperty(_container, "position", _startPosition, 0.5f)
.SetTrans(Tween.TransitionType.Cubic)
.SetEase(Tween.EaseType.In);
await ToSignal(tween, Tween.SignalName.Finished);
QueueFree();
}
}

View File

@@ -0,0 +1 @@
uid://cejjan582nhfn

View File

@@ -4,29 +4,25 @@ using Mr.BrickAdventures.scripts.interfaces;
namespace Mr.BrickAdventures.scripts.components;
public partial class ExitDoorComponent : Node, IUnlockable
public partial class ExitDoorComponent : Area2D, IUnlockable
{
[Export] public bool Locked { get; set; } = true;
[Export] public Area2D ExitArea { get; set; }
[Export] public Sprite2D DoorSprite { get; set; }
[Export] public AudioStreamPlayer2D OpenDoorSfx { get; set; }
[Export] public int OpenedDoorFrame { get; set; } = 0;
[Export] public string AchievementId = "level_complete_1";
[Signal] public delegate void ExitTriggeredEventHandler();
private GameManager _gameManager;
private AchievementManager _achievementManager;
public override void _Ready()
{
_gameManager = GetNode<GameManager>("/root/GameManager");
_achievementManager = GetNode<AchievementManager>("/root/AchievementManager");
if (ExitArea == null)
{
GD.PushError("ExitDoorComponent: ExitArea is not set.");
return;
}
ExitArea.BodyEntered += OnExitAreaBodyEntered;
BodyEntered += OnExitAreaBodyEntered;
}
@@ -35,6 +31,7 @@ public partial class ExitDoorComponent : Node, IUnlockable
if (Locked) return;
EmitSignalExitTriggered();
_achievementManager.UnlockAchievement(AchievementId);
_gameManager.UnlockLevel((int)_gameManager.PlayerState["current_level"] + 1);
CallDeferred(nameof(GoToNextLevel));
}