170 lines
5.7 KiB
C#
170 lines
5.7 KiB
C#
|
|
using Godot;
|
||
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using Chessistics.Engine.Events;
|
||
|
|
using Chessistics.Engine.Model;
|
||
|
|
using Chessistics.Scripts.Board;
|
||
|
|
using Chessistics.Scripts.Pieces;
|
||
|
|
using Chessistics.Scripts.UI;
|
||
|
|
|
||
|
|
namespace Chessistics.Scripts.Presentation;
|
||
|
|
|
||
|
|
public partial class EventAnimator : Node
|
||
|
|
{
|
||
|
|
private BoardView _boardView = null!;
|
||
|
|
private ObjectivePanel _objectivePanel = null!;
|
||
|
|
private ControlBar _controlBar = null!;
|
||
|
|
private MetricsOverlay _metricsOverlay = null!;
|
||
|
|
|
||
|
|
private readonly Dictionary<int, PieceView> _pieceViews = new();
|
||
|
|
private readonly Dictionary<int, TrajectView> _trajectViews = new();
|
||
|
|
|
||
|
|
private bool _animating;
|
||
|
|
public bool IsAnimating => _animating;
|
||
|
|
|
||
|
|
[Signal]
|
||
|
|
public delegate void TurnAnimationCompletedEventHandler();
|
||
|
|
[Signal]
|
||
|
|
public delegate void VictoryReachedEventHandler();
|
||
|
|
[Signal]
|
||
|
|
public delegate void CollisionOccurredEventHandler();
|
||
|
|
|
||
|
|
public void Initialize(BoardView boardView, ObjectivePanel objectivePanel,
|
||
|
|
ControlBar controlBar, MetricsOverlay metricsOverlay)
|
||
|
|
{
|
||
|
|
_boardView = boardView;
|
||
|
|
_objectivePanel = objectivePanel;
|
||
|
|
_controlBar = controlBar;
|
||
|
|
_metricsOverlay = metricsOverlay;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void RegisterPiece(int pieceId, PieceView pieceView, TrajectView trajectView)
|
||
|
|
{
|
||
|
|
_pieceViews[pieceId] = pieceView;
|
||
|
|
_trajectViews[pieceId] = trajectView;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void UnregisterPiece(int pieceId)
|
||
|
|
{
|
||
|
|
if (_pieceViews.TryGetValue(pieceId, out var pv))
|
||
|
|
{
|
||
|
|
pv.QueueFree();
|
||
|
|
_pieceViews.Remove(pieceId);
|
||
|
|
}
|
||
|
|
if (_trajectViews.TryGetValue(pieceId, out var tv))
|
||
|
|
{
|
||
|
|
tv.QueueFree();
|
||
|
|
_trajectViews.Remove(pieceId);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void ProcessEvents(IReadOnlyList<IWorldEvent> events)
|
||
|
|
{
|
||
|
|
_animating = true;
|
||
|
|
var tween = CreateTween();
|
||
|
|
tween.SetParallel(false);
|
||
|
|
|
||
|
|
foreach (var evt in events)
|
||
|
|
{
|
||
|
|
switch (evt)
|
||
|
|
{
|
||
|
|
case TurnStartedEvent ts:
|
||
|
|
tween.TweenCallback(Callable.From(() => _controlBar.UpdateTurn(ts.TurnNumber)));
|
||
|
|
break;
|
||
|
|
|
||
|
|
case PieceMovedEvent moved:
|
||
|
|
if (_pieceViews.TryGetValue(moved.PieceId, out var pv))
|
||
|
|
{
|
||
|
|
var target = _boardView.CoordsToPixel(moved.To);
|
||
|
|
var piece = pv;
|
||
|
|
var kind = piece.Kind;
|
||
|
|
float duration = kind == PieceKind.Knight ? 0.4f : 0.3f;
|
||
|
|
tween.TweenProperty(piece, "position", target, duration);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CollisionDetectedEvent collision:
|
||
|
|
tween.TweenCallback(Callable.From(() =>
|
||
|
|
{
|
||
|
|
FlashPiece(collision.PieceIdA);
|
||
|
|
FlashPiece(collision.PieceIdB);
|
||
|
|
EmitSignal(SignalName.CollisionOccurred);
|
||
|
|
}));
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CargoTransferredEvent transfer:
|
||
|
|
tween.TweenCallback(Callable.From(() =>
|
||
|
|
{
|
||
|
|
if (transfer.GivingPieceId != null && _pieceViews.ContainsKey(transfer.GivingPieceId.Value))
|
||
|
|
_pieceViews[transfer.GivingPieceId.Value].SetCargo(null);
|
||
|
|
if (transfer.ReceivingPieceId != null && _pieceViews.ContainsKey(transfer.ReceivingPieceId.Value))
|
||
|
|
_pieceViews[transfer.ReceivingPieceId.Value].SetCargo(transfer.Type);
|
||
|
|
}));
|
||
|
|
tween.TweenInterval(0.15f);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case CargoProducedEvent:
|
||
|
|
break; // visual pulse could go here
|
||
|
|
|
||
|
|
case DemandProgressEvent progress:
|
||
|
|
tween.TweenCallback(Callable.From(() =>
|
||
|
|
_objectivePanel.UpdateProgress(progress.DemandCell, progress.Name, progress.Current, progress.Required)));
|
||
|
|
break;
|
||
|
|
|
||
|
|
case VictoryEvent victory:
|
||
|
|
tween.TweenCallback(Callable.From(() =>
|
||
|
|
{
|
||
|
|
_metricsOverlay.ShowMetrics(victory.Metrics);
|
||
|
|
EmitSignal(SignalName.VictoryReached);
|
||
|
|
}));
|
||
|
|
break;
|
||
|
|
|
||
|
|
case DeadlineExpiredEvent:
|
||
|
|
tween.TweenCallback(Callable.From(() =>
|
||
|
|
EmitSignal(SignalName.CollisionOccurred))); // reuse for pause
|
||
|
|
break;
|
||
|
|
|
||
|
|
case TurnEndedEvent:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
tween.TweenCallback(Callable.From(() =>
|
||
|
|
{
|
||
|
|
_animating = false;
|
||
|
|
EmitSignal(SignalName.TurnAnimationCompleted);
|
||
|
|
}));
|
||
|
|
}
|
||
|
|
|
||
|
|
private void FlashPiece(int pieceId)
|
||
|
|
{
|
||
|
|
if (!_pieceViews.TryGetValue(pieceId, out var pv)) return;
|
||
|
|
var tween = pv.CreateTween();
|
||
|
|
tween.TweenProperty(pv, "modulate", new Color(1, 0.2f, 0.2f), 0.1f);
|
||
|
|
tween.TweenProperty(pv, "modulate", Colors.White, 0.1f);
|
||
|
|
tween.SetLoops(3);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void ResetPiecePositions(BoardSnapshot snapshot)
|
||
|
|
{
|
||
|
|
foreach (var ps in snapshot.Pieces)
|
||
|
|
{
|
||
|
|
if (_pieceViews.TryGetValue(ps.Id, out var pv))
|
||
|
|
{
|
||
|
|
pv.Position = _boardView.CoordsToPixel(ps.StartCell);
|
||
|
|
pv.SetCargo(null);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void ClearAll()
|
||
|
|
{
|
||
|
|
foreach (var pv in _pieceViews.Values)
|
||
|
|
pv.QueueFree();
|
||
|
|
foreach (var tv in _trajectViews.Values)
|
||
|
|
tv.QueueFree();
|
||
|
|
_pieceViews.Clear();
|
||
|
|
_trajectViews.Clear();
|
||
|
|
}
|
||
|
|
}
|