using Godot; using Chessistics.Engine.Model; using Chessistics.Scripts.Board; namespace Chessistics.Scripts.Pieces; public partial class PieceView : Node2D { private Sprite2D _shadow = null!; private Sprite2D _sprite = null!; private ColorRect _cargoIndicator = null!; private Label _label = null!; private Tween? _cargoPulseTween; public int PieceId { get; private set; } public PieceKind Kind { get; private set; } public Coords StartCell { get; private set; } public Coords EndCell { get; private set; } // Muted, earthy palette — teal, sienna, gold tones private static readonly Color PawnColor = new("#5A8C6B"); // sage green private static readonly Color RookColor = new("#3D6B8E"); // deep teal private static readonly Color BishopColor = new("#8E5A6B"); // dusty rose private static readonly Color KnightColor = new("#8E7A3D"); // burnt sienna private static readonly Color WoodCargoColor = new("#A67C32"); private static readonly Color StoneCargoColor = new("#7A7A7A"); private static readonly Color ShadowColor = new Color(0, 0, 0, 0.18f); public void Setup(int pieceId, PieceKind kind, Coords startCell, Coords endCell, BoardView boardView) { PieceId = pieceId; Kind = kind; StartCell = startCell; EndCell = endCell; Position = boardView.CoordsToPixel(startCell); var color = GetPieceColor(kind); // Shadow (slightly offset, rendered first) _shadow = new Sprite2D(); var shadowTex = new GradientTexture2D { Width = 44, Height = 44, Fill = GradientTexture2D.FillEnum.Radial, Gradient = new Gradient() }; shadowTex.Gradient.SetColor(0, ShadowColor); shadowTex.Gradient.SetColor(1, new Color(0, 0, 0, 0)); _shadow.Texture = shadowTex; _shadow.Position = new Vector2(3, 5); // subtle offset down-right AddChild(_shadow); // Piece body (circle with inner glow) _sprite = new Sprite2D(); var texture = new GradientTexture2D { Width = 48, Height = 48, Fill = GradientTexture2D.FillEnum.Radial, Gradient = new Gradient() }; texture.Gradient.Colors = [ color.Lightened(0.15f), // bright center color, // main color color.Darkened(0.25f) // dark rim ]; texture.Gradient.Offsets = [0f, 0.5f, 1f]; _sprite.Texture = texture; AddChild(_sprite); // Label _label = new Label { Text = kind switch { PieceKind.Pawn => "P", PieceKind.Rook => "T", PieceKind.Bishop => "F", PieceKind.Knight => "C", _ => "?" }, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, Position = new Vector2(-8, -10), MouseFilter = Control.MouseFilterEnum.Ignore }; _label.AddThemeFontSizeOverride("font_size", 16); _label.AddThemeColorOverride("font_color", new Color(1, 1, 1, 0.9f)); AddChild(_label); // Cargo indicator (hidden by default) _cargoIndicator = new ColorRect { Size = new Vector2(12, 12), Position = new Vector2(-6, -28), Visible = false, MouseFilter = Control.MouseFilterEnum.Ignore }; AddChild(_cargoIndicator); // Entrance animation: scale bounce Scale = Vector2.Zero; var entranceTween = CreateTween(); entranceTween.TweenProperty(this, "scale", new Vector2(1.15f, 1.15f), 0.12f) .SetEase(Tween.EaseType.Out).SetTrans(Tween.TransitionType.Back); entranceTween.TweenProperty(this, "scale", Vector2.One, 0.08f) .SetEase(Tween.EaseType.InOut); } public static Color GetPieceColor(PieceKind kind) => kind switch { PieceKind.Pawn => PawnColor, PieceKind.Rook => RookColor, PieceKind.Bishop => BishopColor, PieceKind.Knight => KnightColor, _ => Colors.White }; public void SetCargo(CargoType? cargo) { _cargoPulseTween?.Kill(); _cargoPulseTween = null; if (cargo == null) { _cargoIndicator.Visible = false; _cargoIndicator.Scale = Vector2.One; return; } _cargoIndicator.Visible = true; _cargoIndicator.Color = cargo.Value switch { CargoType.Wood => WoodCargoColor, CargoType.Stone => StoneCargoColor, _ => Colors.White }; // Cargo pulse: gentle breathing _cargoPulseTween = CreateTween(); _cargoPulseTween.SetLoops(); _cargoPulseTween.TweenProperty(_cargoIndicator, "scale", new Vector2(1.25f, 1.25f), 0.5f) .SetEase(Tween.EaseType.InOut).SetTrans(Tween.TransitionType.Sine); _cargoPulseTween.TweenProperty(_cargoIndicator, "scale", Vector2.One, 0.5f) .SetEase(Tween.EaseType.InOut).SetTrans(Tween.TransitionType.Sine); } public void AnimateMoveTo(Vector2 target, float duration = 0.3f) { var tween = CreateTween(); if (Kind == PieceKind.Knight) { var mid = (Position + target) / 2 + new Vector2(0, -30); tween.TweenMethod(Callable.From(t => { var a = Position.Lerp(mid, t); var b = mid.Lerp(target, t); Position = a.Lerp(b, t); }), 0f, 1f, duration); tween.Finished += () => Position = target; } else { tween.TweenProperty(this, "position", target, duration) .SetEase(Tween.EaseType.InOut).SetTrans(Tween.TransitionType.Sine); } } }