diff --git a/Scripts/Pieces/TrajectView.cs b/Scripts/Pieces/TrajectView.cs index 801a235..7a1a6ad 100644 --- a/Scripts/Pieces/TrajectView.cs +++ b/Scripts/Pieces/TrajectView.cs @@ -5,34 +5,54 @@ namespace Chessistics.Scripts.Pieces; public partial class TrajectView : Line2D { public int PieceId { get; private set; } - private Polygon2D? _arrow; + private Polygon2D? _arrowEnd; + private Polygon2D? _arrowStart; + private Tween? _pulseTween; + private Color _baseColor; public void Setup(int pieceId, Vector2 from, Vector2 to, Color color) { PieceId = pieceId; - Width = 2.5f; - DefaultColor = new Color(color, 0.35f); + _baseColor = color; + Width = 3f; + DefaultColor = new Color(color, 0.4f); Antialiased = true; ClearPoints(); AddPoint(from); AddPoint(to); ZIndex = -1; - // Arrowhead at the end point + _arrowEnd = BuildArrow(from, to, color); + _arrowStart = BuildArrow(to, from, color); + AddChild(_arrowEnd); + AddChild(_arrowStart); + + StartPulse(); + } + + private static Polygon2D BuildArrow(Vector2 from, Vector2 to, Color color) + { var dir = (to - from).Normalized(); var perp = new Vector2(-dir.Y, dir.X); - float arrowSize = 8f; - var tip = to - dir * 4f; // slightly inset from end + const float arrowSize = 9f; + var tip = to - dir * 4f; var baseL = tip - dir * arrowSize + perp * arrowSize * 0.5f; var baseR = tip - dir * arrowSize - perp * arrowSize * 0.5f; - - _arrow = new Polygon2D + return new Polygon2D { - Polygon = [tip - Position, baseL - Position, baseR - Position], - Color = new Color(color, 0.4f), - Position = Vector2.Zero + Polygon = [tip, baseL, baseR], + Color = new Color(color, 0.5f) }; - // Position relative to parent, not this Line2D - AddChild(_arrow); + } + + private void StartPulse() + { + _pulseTween?.Kill(); + _pulseTween = CreateTween(); + _pulseTween.SetLoops(); + _pulseTween.TweenProperty(this, "default_color:a", 0.75f, 1.1f) + .SetEase(Tween.EaseType.InOut).SetTrans(Tween.TransitionType.Sine); + _pulseTween.TweenProperty(this, "default_color:a", 0.3f, 1.1f) + .SetEase(Tween.EaseType.InOut).SetTrans(Tween.TransitionType.Sine); } } diff --git a/docs/PLAN.md b/docs/PLAN.md index 7eebdc2..8a076d2 100644 --- a/docs/PLAN.md +++ b/docs/PLAN.md @@ -12,15 +12,6 @@ et l'extension de la campagne. Le moteur expose deja les commandes et events requis ; cote Godot il manque les surfaces d'interaction et d'animation. -### 1.5 Cinematique de transition de mission -Sur `MissionStartedEvent` (hors mission 0) : -- Titre "Nouvelle mission" plein ecran en fade-in. -- Lock pan/zoom ; la camera se deplace vers la nouvelle zone. -- Animation d'expansion pour les cases debloquees par le `TerrainPatch`. -- Le titre glisse ensuite vers le panneau d'objectifs avant de disparaitre - (guide l'oeil). -- Unlock pan/zoom, la simulation reprend. - ### 1.6 Visualisation des trajets `TrajectView` existe. Manque : - Fleches directionnelles sur le trait. diff --git a/tools/automation/test_trajectory.py b/tools/automation/test_trajectory.py new file mode 100644 index 0000000..44c3939 --- /dev/null +++ b/tools/automation/test_trajectory.py @@ -0,0 +1,24 @@ +"""Visual smoke for trajectory arrows + pulsation.""" +import sys, time +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parents[2])) + +from tools.automation.harness import Harness + + +def main(): + with Harness.launch(run_name="trajectory") as h: + h.load_mission("campaign_01", 0) + h.place("Pawn", (0, 1), (1, 1)) + h.place("Pawn", (2, 1), (3, 1)) + + # Capture two frames at different phases of the pulse loop + h.screenshot("01_placed_a") + time.sleep(0.8) + h.screenshot("02_placed_b_pulse") + print("OK — trajectories rendered; see screens for arrows + pulse") + + +if __name__ == "__main__": + main()