feat: smooth snake animation + beautiful Avalonia UI overhaul
- Two-timer architecture: game timer + 60fps render timer for smooth interpolation - Snake body: StreamGeometry path with teal gradient, rounded joins - Directional head with white eyes and dark pupils - Food: pulsating glow, highlight, green leaf animation - Modern dark theme (#0D1117), glassmorphism HUD - Speed indicator bar, score +N popup - High score persistence to JSON - All keyboard shortcuts: Arrows, WASD, Space/P pause, Enter start, R restart, Esc quit - Window resizable, 640x540 default New files: AnimationHelper.cs, HighScoreManager.cs, SnakeRenderer.cs
This commit is contained in:
@@ -15,18 +15,28 @@ public sealed class Snake
|
||||
var offset = DirectionToOffset(direction);
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
_segments.AddLast(new Position(
|
||||
var pos = new Position(
|
||||
start.X - offset.X * i,
|
||||
start.Y - offset.Y * i));
|
||||
start.Y - offset.Y * i);
|
||||
_segments.AddLast(pos);
|
||||
_previousSegments.Add(pos);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<Position> _previousSegments = new();
|
||||
|
||||
public Direction Direction { get; private set; }
|
||||
|
||||
public Position Head => _segments.First!.Value;
|
||||
|
||||
public IReadOnlyCollection<Position> Segments => _segments;
|
||||
|
||||
/// <summary>
|
||||
/// Segment positions before the last Move() call, used for interpolation.
|
||||
/// Empty (Count == 0) before first move.
|
||||
/// </summary>
|
||||
public IReadOnlyList<Position> PreviousSegments => _previousSegments;
|
||||
|
||||
/// <summary>
|
||||
/// Enqueues a direction change to be applied on a future tick.
|
||||
/// </summary>
|
||||
@@ -56,6 +66,11 @@ public sealed class Snake
|
||||
if (_pendingDirections.Count > 0)
|
||||
Direction = _pendingDirections.Dequeue();
|
||||
|
||||
// Capture current segments as "previous" for interpolation
|
||||
_previousSegments.Clear();
|
||||
foreach (var seg in _segments)
|
||||
_previousSegments.Add(seg);
|
||||
|
||||
var offset = DirectionToOffset(Direction);
|
||||
var newHead = new Position(Head.X + offset.X, Head.Y + offset.Y);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user