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:
Heller
2026-06-19 10:02:07 +00:00
parent 2e89c6dca3
commit 7d55a08380
9 changed files with 1027 additions and 150 deletions

View File

@@ -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);