Implement MVP for the statue decoration minigame (#65)

MVP implemented with:
- placing, removing etc. decorations
- saving the state, displaying it on the map, restoring when game restarts
- saving screenshots to folder on device

Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com>
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: #65
This commit is contained in:
2025-11-27 13:21:22 +00:00
parent 5ad84ca3e8
commit 83aa3d5e6d
71 changed files with 6421 additions and 976 deletions

View File

@@ -0,0 +1,172 @@
using Core;
using Core.Lifecycle;
using Minigames.StatueDressup.Data;
namespace Minigames.StatueDressup.Events
{
/// <summary>
/// Manager for decoration VFX/SFX events.
/// Listens to decoration state changes and triggers audio/visual feedback.
/// </summary>
public class DecorationEventsManager : ManagedBehaviour
{
public static DecorationEventsManager Instance { get; private set; }
// Static events for decoration state changes
public static event System.Action<DecorationEventData> OnDecorationTappedInGrid;
public static event System.Action<DecorationEventData> OnDecorationTappedOnStatue;
public static event System.Action<DecorationEventData> OnDecorationStartedDragging;
public static event System.Action<DecorationEventData> OnDecorationFinishedDragging;
public static event System.Action<DecorationEventData> OnDecorationDroppedOnStatue;
public static event System.Action<DecorationEventData> OnDecorationDroppedOut;
public static event System.Action<DecorationEventData> OnDecorationFinishedDroppingOut;
internal override void OnManagedAwake()
{
base.OnManagedAwake();
// Singleton pattern
if (Instance != null && Instance != this)
{
Logging.Warning("[DecorationEventsManager] Duplicate instance detected. Destroying duplicate.");
Destroy(gameObject);
return;
}
Instance = this;
// Subscribe to all events
OnDecorationTappedInGrid += HandleDecorationTappedInGrid;
OnDecorationTappedOnStatue += HandleDecorationTappedOnStatue;
OnDecorationStartedDragging += HandleDecorationStartedDragging;
OnDecorationFinishedDragging += HandleDecorationFinishedDragging;
OnDecorationDroppedOnStatue += HandleDecorationDroppedOnStatue;
OnDecorationDroppedOut += HandleDecorationDroppedOut;
OnDecorationFinishedDroppingOut += HandleDecorationFinishedDroppingOut;
}
private void OnDestroy()
{
// Unsubscribe from all events
if (Instance == this)
{
OnDecorationTappedInGrid -= HandleDecorationTappedInGrid;
OnDecorationTappedOnStatue -= HandleDecorationTappedOnStatue;
OnDecorationStartedDragging -= HandleDecorationStartedDragging;
OnDecorationFinishedDragging -= HandleDecorationFinishedDragging;
OnDecorationDroppedOnStatue -= HandleDecorationDroppedOnStatue;
OnDecorationDroppedOut -= HandleDecorationDroppedOut;
OnDecorationFinishedDroppingOut -= HandleDecorationFinishedDroppingOut;
Instance = null;
}
}
#region Static Broadcasting Methods
/// <summary>
/// Broadcast that a decoration was tapped in the grid menu
/// </summary>
public static void BroadcastDecorationTappedInGrid(DecorationEventData eventData)
{
OnDecorationTappedInGrid?.Invoke(eventData);
}
/// <summary>
/// Broadcast that a decoration already on the statue was tapped
/// </summary>
public static void BroadcastDecorationTappedOnStatue(DecorationEventData eventData)
{
OnDecorationTappedOnStatue?.Invoke(eventData);
}
/// <summary>
/// Broadcast that a decoration started being dragged
/// </summary>
public static void BroadcastDecorationStartedDragging(DecorationEventData eventData)
{
OnDecorationStartedDragging?.Invoke(eventData);
}
/// <summary>
/// Broadcast that a decoration finished being dragged (released)
/// </summary>
public static void BroadcastDecorationFinishedDragging(DecorationEventData eventData)
{
OnDecorationFinishedDragging?.Invoke(eventData);
}
/// <summary>
/// Broadcast that a decoration was successfully dropped on the statue
/// </summary>
public static void BroadcastDecorationDroppedOnStatue(DecorationEventData eventData)
{
OnDecorationDroppedOnStatue?.Invoke(eventData);
}
/// <summary>
/// Broadcast that a decoration was dropped outside the statue (animation starts)
/// </summary>
public static void BroadcastDecorationDroppedOut(DecorationEventData eventData)
{
OnDecorationDroppedOut?.Invoke(eventData);
}
/// <summary>
/// Broadcast that a decoration finished its drop-out animation
/// </summary>
public static void BroadcastDecorationFinishedDroppingOut(DecorationEventData eventData)
{
OnDecorationFinishedDroppingOut?.Invoke(eventData);
}
#endregion
#region Event Handlers (Stubbed with Logs)
private void HandleDecorationTappedInGrid(DecorationEventData eventData)
{
Logging.Debug($"[DecorationEventsManager] Decoration tapped in grid: {eventData.DecorationData?.DecorationId}");
// TODO: Play tap SFX/VFX
}
private void HandleDecorationTappedOnStatue(DecorationEventData eventData)
{
Logging.Debug($"[DecorationEventsManager] Decoration tapped on statue: {eventData.DecorationData?.DecorationId}");
// TODO: Play tap SFX/VFX (different from grid tap?)
}
private void HandleDecorationStartedDragging(DecorationEventData eventData)
{
Logging.Debug($"[DecorationEventsManager] Decoration started dragging: {eventData.DecorationData?.DecorationId} (FromStatue: {eventData.FromStatue})");
// TODO: Play drag start SFX, maybe show drag VFX
}
private void HandleDecorationFinishedDragging(DecorationEventData eventData)
{
Logging.Debug($"[DecorationEventsManager] Decoration finished dragging: {eventData.DecorationData?.DecorationId}");
// TODO: Play drag release SFX
}
private void HandleDecorationDroppedOnStatue(DecorationEventData eventData)
{
Logging.Debug($"[DecorationEventsManager] Decoration dropped on statue: {eventData.DecorationData?.DecorationId}");
// TODO: Play success SFX, maybe show placement VFX
}
private void HandleDecorationDroppedOut(DecorationEventData eventData)
{
Logging.Debug($"[DecorationEventsManager] Decoration dropped out (animation starting): {eventData.DecorationData?.DecorationId}");
// TODO: Play drop-out SFX (whoosh/disappear sound?)
}
private void HandleDecorationFinishedDroppingOut(DecorationEventData eventData)
{
Logging.Debug($"[DecorationEventsManager] Decoration finished dropping out: {eventData.DecorationData?.DecorationId}");
// TODO: Play finish SFX (poof sound?), maybe show VFX
}
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5c9796e0044a4fcd95b02a19925a6b2b
timeCreated: 1764248911