Add bidirectional arrows and idle pulsation on piece trajectories
TrajectView now draws an arrow at each endpoint (since pieces oscillate between start and end, both directions are relevant) and runs a looped width/alpha tween that breathes between 0.3 and 0.75 over ~2.2s. The pulse makes stationary relays visually distinct from static board art without competing with active cargo/particle animations.
This commit is contained in:
parent
1d0999a78e
commit
480c783bd6
3 changed files with 57 additions and 22 deletions
|
|
@ -5,34 +5,54 @@ namespace Chessistics.Scripts.Pieces;
|
||||||
public partial class TrajectView : Line2D
|
public partial class TrajectView : Line2D
|
||||||
{
|
{
|
||||||
public int PieceId { get; private set; }
|
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)
|
public void Setup(int pieceId, Vector2 from, Vector2 to, Color color)
|
||||||
{
|
{
|
||||||
PieceId = pieceId;
|
PieceId = pieceId;
|
||||||
Width = 2.5f;
|
_baseColor = color;
|
||||||
DefaultColor = new Color(color, 0.35f);
|
Width = 3f;
|
||||||
|
DefaultColor = new Color(color, 0.4f);
|
||||||
Antialiased = true;
|
Antialiased = true;
|
||||||
ClearPoints();
|
ClearPoints();
|
||||||
AddPoint(from);
|
AddPoint(from);
|
||||||
AddPoint(to);
|
AddPoint(to);
|
||||||
ZIndex = -1;
|
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 dir = (to - from).Normalized();
|
||||||
var perp = new Vector2(-dir.Y, dir.X);
|
var perp = new Vector2(-dir.Y, dir.X);
|
||||||
float arrowSize = 8f;
|
const float arrowSize = 9f;
|
||||||
var tip = to - dir * 4f; // slightly inset from end
|
var tip = to - dir * 4f;
|
||||||
var baseL = tip - dir * arrowSize + perp * arrowSize * 0.5f;
|
var baseL = tip - dir * arrowSize + perp * arrowSize * 0.5f;
|
||||||
var baseR = tip - dir * arrowSize - perp * arrowSize * 0.5f;
|
var baseR = tip - dir * arrowSize - perp * arrowSize * 0.5f;
|
||||||
|
return new Polygon2D
|
||||||
_arrow = new Polygon2D
|
|
||||||
{
|
{
|
||||||
Polygon = [tip - Position, baseL - Position, baseR - Position],
|
Polygon = [tip, baseL, baseR],
|
||||||
Color = new Color(color, 0.4f),
|
Color = new Color(color, 0.5f)
|
||||||
Position = Vector2.Zero
|
|
||||||
};
|
};
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,6 @@ et l'extension de la campagne.
|
||||||
Le moteur expose deja les commandes et events requis ; cote Godot il manque
|
Le moteur expose deja les commandes et events requis ; cote Godot il manque
|
||||||
les surfaces d'interaction et d'animation.
|
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
|
### 1.6 Visualisation des trajets
|
||||||
`TrajectView` existe. Manque :
|
`TrajectView` existe. Manque :
|
||||||
- Fleches directionnelles sur le trait.
|
- Fleches directionnelles sur le trait.
|
||||||
|
|
|
||||||
24
tools/automation/test_trajectory.py
Normal file
24
tools/automation/test_trajectory.py
Normal file
|
|
@ -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()
|
||||||
Loading…
Add table
Reference in a new issue