Skip to content

Commit 5550cff

Browse files
committed
NeonSnake: improve canvas drawing on mobile devices
1 parent 57b6f14 commit 5550cff

5 files changed

Lines changed: 29 additions & 17 deletions

File tree

BlazorExperiments/Layout/MainLayout.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
</div>
1010

1111
<main>
12-
<article class="content px-4">
12+
<article class="content px-2">
1313
@Body
1414
</article>
1515
</main>

BlazorExperiments/Models/NeonSnakeGame/Snake.cs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ public class Snake {
1212
public const double DeathAnimDuration = 1500;
1313

1414
public readonly Vector2[] CenterCoords;
15-
readonly Dictionary<(int Col, int Row), int> _validCells = [];
1615

1716
public List<SnakeBodyPart> Parts = [];
1817
public SnakeBodyPart Head => Parts[0];
@@ -33,7 +32,10 @@ public class Snake {
3332
public double DeathTimer;
3433
public List<DeathSegment> DeathSegments = [];
3534
public bool ShowDeathScreen;
36-
public Queue<int> KeyQueue = new();
35+
public Queue<int> KeyQueue = new(3);
36+
37+
readonly double _eatDistSq;
38+
readonly Dictionary<(int Col, int Row), int> _validCells;
3739

3840
static readonly string[] EatColors = ["#ffe080", "#ffb840", "#fff4c0", "#ff9420", Neon.TextAccent];
3941
static readonly string[] DeathColors = [Neon.Danger, "#ff6a9d", Neon.TextAccent, "#8b5dff", "#ffc2ff"];
@@ -46,6 +48,9 @@ public Snake(int cellSize, int visibleCols, int visibleRows) {
4648
Rows = visibleRows * 5;
4749
WorldW = Cols * CellSize;
4850
WorldH = Rows * CellSize;
51+
_eatDistSq = CellSize * (double)CellSize;
52+
_validCells = new(Rows * Cols);
53+
4954
CenterCoords = new Vector2[Cols * Rows];
5055
float centerOffset = CellSize * 0.5f;
5156
for (int y = 0; y < Rows; y++)
@@ -67,8 +72,9 @@ public Snake(int cellSize, int visibleCols, int visibleRows) {
6772
}
6873

6974
int numObstacles = (int)(Cols * Rows * 0.02);
75+
const int numFood = 50;
7076
for (int i = 0; i < numObstacles; i++) SpawnObstacle();
71-
for (int i = 0; i < 50; i++) SpawnFood();
77+
for (int i = 0; i < numFood; i++) SpawnFood();
7278
}
7379

7480
public int GetIndex(int col, int row) {
@@ -130,7 +136,7 @@ bool EggBlocked(int x, int y, Egg skipEgg) {
130136
}
131137

132138
void StepEgg(Egg egg) {
133-
Span<int> order = stackalloc int[4] { 0, 1, 2, 3 };
139+
Span<int> order = [0, 1, 2, 3];
134140
for (int i = order.Length - 1; i > 0; i--) {
135141
int j = Random.Shared.Next(i + 1);
136142
(order[i], order[j]) = (order[j], order[i]);
@@ -236,6 +242,11 @@ public void Update(double deltaTime, double screenW, double screenH) {
236242
}
237243

238244
if (Dead) {
245+
if (DeathTimer >= DeathAnimDuration) {
246+
ShowDeathScreen = true;
247+
return;
248+
}
249+
239250
DeathTimer += deltaTime;
240251
double progress = Math.Min(1, DeathTimer / DeathAnimDuration);
241252
for (int si = 0; si < DeathSegments.Count; si++) {
@@ -246,7 +257,6 @@ public void Update(double deltaTime, double screenW, double screenH) {
246257
seg.Alpha = Math.Max(0, 1 - progress * 0.8);
247258
DeathSegments[si] = seg;
248259
}
249-
if (DeathTimer >= DeathAnimDuration) ShowDeathScreen = true;
250260
return;
251261
}
252262

@@ -300,11 +310,11 @@ public void Update(double deltaTime, double screenW, double screenH) {
300310
}
301311

302312
void CheckFoodCollision() {
303-
double eatDistSq = CellSize * (double)CellSize;
313+
304314
for (int fi = Food.Count - 1; fi >= 0; fi--) {
305315
var egg = Food[fi];
306316
double dx = Head.CurrentScreenPos.X - egg.ScreenX, dy = Head.CurrentScreenPos.Y - egg.ScreenY;
307-
if (dx * dx + dy * dy >= eatDistSq) continue;
317+
if (dx * dx + dy * dy >= _eatDistSq) continue;
308318
Score++;
309319
for (int p = 0; p < 8; p++) {
310320
double angle = (p / 8.0) * Math.PI * 2 + Random.Shared.NextDouble() * 0.5;
@@ -336,6 +346,10 @@ void CheckFoodCollision() {
336346
}
337347
}
338348

349+
public void AddCommand(int key) {
350+
if (KeyQueue.Count < 3) KeyQueue.Enqueue(key);
351+
}
352+
339353
void ProcessInput() {
340354
bool processed = false;
341355
var dir = Head.Direction;

BlazorExperiments/Pages/NeonSnake.razor.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -708,11 +708,9 @@ async ValueTask DrawHeartAsync(Batch2D ctx, double cx, double cy, double size, s
708708
await ctx.BezierCurveToAsync(cx + size, cy - size * 0.6, cx, cy - size * 0.2, cx, cy + size * 0.35);
709709
await ctx.ClosePathAsync();
710710
await ctx.FillAsync(FillRule.NonZero);
711-
if (!isOff) {
712-
await ctx.RestoreAsync();
713-
}
714711

715712
if (!isOff) {
713+
await ctx.RestoreAsync();
716714
await ctx.FillStyleAsync("rgba(255,255,255,0.45)");
717715
await ctx.BeginPathAsync();
718716
await ctx.ArcAsync(cx - size * 0.35, cy + size * 0.05, size * 0.25, 0, DoublePI);
@@ -776,7 +774,7 @@ void HandleInput(KeyboardEventArgs e) {
776774
};
777775

778776
if (mapped.HasValue) {
779-
_snake.KeyQueue.Enqueue(mapped.Value);
777+
_snake.AddCommand(mapped.Value);
780778
}
781779
}
782780

@@ -804,10 +802,10 @@ void HandleTouchMove(TouchEventArgs e) {
804802

805803
// most significant
806804
if (Math.Abs(xDiff) > Math.Abs(yDiff)) {
807-
_snake.KeyQueue.Enqueue(xDiff > 0 ? KeyLeft : KeyRight);
805+
_snake.AddCommand(xDiff > 0 ? KeyLeft : KeyRight);
808806
}
809807
else {
810-
_snake.KeyQueue.Enqueue(yDiff > 0 ? KeyUp : KeyDown);
808+
_snake.AddCommand(yDiff > 0 ? KeyUp : KeyDown);
811809
}
812810

813811
_previousTouch = e.Touches[^1];

BlazorExperiments/Shared/CanvasComponent.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<div id="canvas-container"
77
tabindex="0"
8-
style="width: @(Width + 4)px; height: @(Height + 4)px !important; display: grid; align-items: center; justify-content: center;touch-action: none;"
8+
style="width: @(Width + 4)px; height: @(Height + 4)px !important; display: grid; align-items: center; justify-content: center; touch-action: pinch-zoom;"
99
@onkeydown="HandleKeyDown"
1010
@onkeydown:preventDefault="true"
1111
@onmouseup="@(async (mouseEventArgs) => await HandleMouseUp(mouseEventArgs))"

BlazorExperiments/Shared/CanvasComponent.razor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ namespace BlazorExperiments.UI.Shared;
99
public partial class CanvasComponent : IAsyncDisposable {
1010
string _style = "";
1111
double _devicePixelRatio = 1;
12-
const int Margin = 50;
12+
const int Margin = 20;
1313
const int MediaMinWidth = 641;
1414
const int SideBarWidth = 250;
15-
const double Interval = 1_000 / 60; // 60 fps
15+
const double Interval = 1_000 / 30; // 60 fps
1616

1717
double _fps = 0;
1818

0 commit comments

Comments
 (0)