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

@@ -0,0 +1,58 @@
using System.Text.Json;
namespace Snake.Avalonia.Views;
/// <summary>
/// Persists high score to a JSON file in the user's local app data.
/// </summary>
public static class HighScoreManager
{
private static readonly string FilePath;
static HighScoreManager()
{
var appData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var dir = Path.Combine(appData, "SnakeAvalonia");
Directory.CreateDirectory(dir);
FilePath = Path.Combine(dir, "highscore.json");
}
public static int Load()
{
try
{
if (File.Exists(FilePath))
{
var json = File.ReadAllText(FilePath);
var data = JsonSerializer.Deserialize<HighScoreData>(json);
return data?.Score ?? 0;
}
}
catch
{
// Corrupted file — reset
}
return 0;
}
public static void Save(int score)
{
try
{
var data = new HighScoreData { Score = score, Date = DateTime.UtcNow.ToString("O") };
var json = JsonSerializer.Serialize(data);
File.WriteAllText(FilePath, json);
}
catch
{
// Silently fail — high score is non-critical
}
}
private sealed class HighScoreData
{
public int Score { get; set; }
public string Date { get; set; } = string.Empty;
}
}