@@ -15,6 +15,7 @@ public partial class NeonSnake {
1515 const int KeyDown = 40 ;
1616 const int KeyLeft = 37 ;
1717 const int KeyRight = 39 ;
18+ const double DoublePI = Math . PI * 2 ;
1819 double _screenW , _screenH , _gameAreaH ;
1920 int _visibleRows ;
2021
@@ -26,20 +27,20 @@ public partial class NeonSnake {
2627 bool _audioEnabled = true ;
2728 double _obstacleInset = 0 ;
2829 double _obstacleSize = 0 ;
30+ double _baseR , _tailR ;
2931 const int ObstaclePadding = 14 ;
3032 double _cacheW = 0 ;
3133 double _eggEr , _eggEh , _eggCacheSize ;
3234 const int EggCachePadding = 20 ;
3335 readonly List < Vector2 > _bodyPoints = new ( 256 ) ;
34- static readonly ( double Ox , double Oy , double Rx , double Ry , double A ) [ ] EggSpeckles =
35- [ ( - 0.35 , - 0.18 , 0.18 , 0.09 , 0.4 ) , ( 0.38 , 0.2 , 0.13 , 0.07 , - 0.6 ) , ( - 0.1 , 0.35 , 0.1 , 0.06 , 0.9 ) ] ;
3636 static readonly ( double Offset , string Color ) [ ] TailGradientStops = [ ( 0d , "#9bb6ff" ) , ( 1d , Neon . SnakeSecondary ) ] ;
3737 int _lastScore , _lastBestScore ;
3838 string _scoreText = "Score: 0" ;
3939 string _bestText = "Best: 0" ;
4040 const string BestScoreKey = "neonSnakeBestScore" ;
4141
4242 public async Task InitializeAsync ( ) {
43+ _canvas . Timer . Enabled = false ;
4344 _cellSize = _canvas . CellSize ;
4445 _screenW = _canvas . Width ;
4546 _screenH = _canvas . Height ;
@@ -48,10 +49,12 @@ public async Task InitializeAsync() {
4849 _obstacleInset = _cellSize * 0.08 ;
4950 _obstacleSize = _cellSize - _obstacleInset * 2 ;
5051 _cacheW = _obstacleSize + ObstaclePadding * 2 ;
51- var dpr = _canvas . WindowProperties . DevicePixelRatio ;
52- await JS . InvokeVoidAsync ( "neonSnakeCache.renderObstacle" , _obstacleSize , ObstaclePadding , dpr ) ;
52+ _baseR = _cellSize * 0.44 ;
53+ _tailR = _baseR * 0.35 ;
5354 _eggEr = _cellSize * 0.22 ;
5455 _eggEh = _cellSize * 0.3 ;
56+ var dpr = _canvas . WindowProperties . DevicePixelRatio ;
57+ await JS . InvokeVoidAsync ( "neonSnakeCache.renderObstacle" , _obstacleSize , ObstaclePadding , dpr ) ;
5558 _eggCacheSize = await JS . InvokeAsync < double > ( "neonSnakeEggCache.renderStaticEgg" , _eggEr , _eggEh , EggCachePadding , dpr ) ;
5659 await JS . InvokeVoidAsync ( "neonSnakeEggCache.renderRunningEgg" , _eggEr , _eggEh , EggCachePadding , dpr ) ;
5760 var raw = await JS . InvokeAsync < string ? > ( "localStorage.getItem" , BestScoreKey ) ;
@@ -238,16 +241,13 @@ async ValueTask DrawObstaclesAsync(Batch2D ctx) {
238241 }
239242
240243 async ValueTask DrawEggsAsync ( Batch2D ctx ) {
241- var now = DateTimeOffset . UtcNow . ToUnixTimeMilliseconds ( ) ;
242- var er = _eggEr ;
243- var eh = _eggEh ;
244244 var halfCache = _eggCacheSize * 0.5 ;
245245 var camX = _snake . CamX ;
246246 var camY = _snake . CamY ;
247247 var viewRight = camX + _screenW ;
248248 var viewBottom = camY + _gameAreaH ;
249249 var cullMargin = _cellSize * 1.5 ;
250- var glowMargin = _cellSize * 0.5 ;
250+ var now = DateTimeOffset . UtcNow . ToUnixTimeMilliseconds ( ) ;
251251
252252 // Pass 1: non-running (static) eggs — use cached sprite
253253 foreach ( var egg in _snake . Food ) {
@@ -266,11 +266,11 @@ async ValueTask DrawEggsAsync(Batch2D ctx) {
266266
267267 // Timer ring (dynamic per egg)
268268 var frac = Math . Max ( 0 , egg . Timer / 5000 ) ;
269- var ringR = eh * 1.48 ;
269+ var ringR = _eggEh * 1.48 ;
270270 await ctx . StrokeStyleAsync ( "rgba(60,200,175,0.2)" ) ;
271271 await ctx . LineWidthAsync ( 2.2 ) ;
272272 await ctx . BeginPathAsync ( ) ;
273- await ctx . ArcAsync ( cx , dy , ringR , 0 , Math . PI * 2 ) ;
273+ await ctx . ArcAsync ( cx , dy , ringR , 0 , DoublePI ) ;
274274 await ctx . StrokeAsync ( ) ;
275275
276276 var tColor = frac > 0.6 ? "#38ffda" : frac > 0.3 ? "#ffd050" : "#ff6830" ;
@@ -281,13 +281,13 @@ async ValueTask DrawEggsAsync(Batch2D ctx) {
281281 await ctx . LineWidthAsync ( 2.2 ) ;
282282 await ctx . LineCapAsync ( LineCap . Round ) ;
283283 await ctx . BeginPathAsync ( ) ;
284- await ctx . ArcAsync ( cx , dy , ringR , - Math . PI / 2 , - Math . PI / 2 + frac * Math . PI * 2 ) ;
284+ await ctx . ArcAsync ( cx , dy , ringR , - Math . PI / 2 , - Math . PI / 2 + frac * DoublePI ) ;
285285 await ctx . StrokeAsync ( ) ;
286286 await ctx . RestoreAsync ( ) ;
287287 }
288288
289289 // Pass 2: running eggs — cached sprite + animated legs & eyes
290- var walkPhase = ( now * 0.007 ) % ( Math . PI * 2 ) ;
290+ var walkPhase = ( now * 0.007 ) % DoublePI ;
291291 foreach ( var egg in _snake . Food ) {
292292 if ( ! egg . Running ) continue ;
293293 var cx = egg . ScreenX ;
@@ -302,18 +302,18 @@ async ValueTask DrawEggsAsync(Batch2D ctx) {
302302 for ( var si = 0 ; si < 2 ; si ++ ) {
303303 var side = si == 0 ? - 1 : 1 ;
304304 var extend = 0.65 + 0.35 * Math . Sin ( walkPhase + ( si == 0 ? 0 : Math . PI ) ) ;
305- var lx = cx + side * er * 0.5 ;
306- var ly = dy + eh * 0.7 ;
307- var lw = er * 0.48 ;
308- var lh = eh * 0.72 * extend ;
305+ var lx = cx + side * _eggEr * 0.5 ;
306+ var ly = dy + _eggEh * 0.7 ;
307+ var lw = _eggEr * 0.48 ;
308+ var lh = _eggEh * 0.72 * extend ;
309309
310310 await ctx . FillStyleAsync ( "#ffdc96" ) ;
311311 await ctx . FillRectAsync ( lx - lw / 2 , ly , lw , lh ) ;
312312
313- var footDirX = egg . RunDir . X != 0 ? egg . RunDir . X * er * 0.2 : 0 ;
313+ var footDirX = egg . RunDir . X != 0 ? egg . RunDir . X * _eggEr * 0.2 : 0 ;
314314 await ctx . FillStyleAsync ( "#ffb855" ) ;
315315 await ctx . BeginPathAsync ( ) ;
316- await ctx . EllipseAsync ( lx + footDirX , ly + lh , lw * 0.95 , lw * 0.52 , 0 , 0 , Math . PI * 2 ) ;
316+ await ctx . EllipseAsync ( lx + footDirX , ly + lh , lw * 0.95 , lw * 0.52 , 0 , 0 , DoublePI ) ;
317317 await ctx . FillAsync ( FillRule . NonZero ) ;
318318 }
319319
@@ -322,38 +322,35 @@ async ValueTask DrawEggsAsync(Batch2D ctx) {
322322
323323 // Animated eyes
324324 var rd = egg . RunDir ;
325- var eyeR = er * 0.165 ;
326- var eyeCx = cx + rd . X * er * 0.38 ;
327- var eyeCy = dy + rd . Y * eh * 0.38 ;
325+ var eyeR = _eggEr * 0.165 ;
326+ var eyeCx = cx + rd . X * _eggEr * 0.38 ;
327+ var eyeCy = dy + rd . Y * _eggEh * 0.38 ;
328328 var perpX = - rd . Y ;
329329 var perpY = rd . X ;
330330
331331 for ( var side = - 1 ; side <= 1 ; side += 2 ) {
332- var ex = eyeCx + perpX * er * 0.28 * side ;
333- var ey = eyeCy + perpY * eh * 0.28 * side ;
332+ var ex = eyeCx + perpX * _eggEr * 0.28 * side ;
333+ var ey = eyeCy + perpY * _eggEh * 0.28 * side ;
334334 await ctx . FillStyleAsync ( "rgba(248,252,255,0.95)" ) ;
335335 await ctx . BeginPathAsync ( ) ;
336- await ctx . ArcAsync ( ex , ey , eyeR , 0 , Math . PI * 2 ) ;
336+ await ctx . ArcAsync ( ex , ey , eyeR , 0 , DoublePI ) ;
337337 await ctx . FillAsync ( FillRule . NonZero ) ;
338338
339339 await ctx . FillStyleAsync ( "#18103a" ) ;
340340 await ctx . BeginPathAsync ( ) ;
341- await ctx . ArcAsync ( ex + rd . X * eyeR * 0.22 , ey + rd . Y * eyeR * 0.22 , eyeR * 0.55 , 0 , Math . PI * 2 ) ;
341+ await ctx . ArcAsync ( ex + rd . X * eyeR * 0.22 , ey + rd . Y * eyeR * 0.22 , eyeR * 0.55 , 0 , DoublePI ) ;
342342 await ctx . FillAsync ( FillRule . NonZero ) ;
343343
344344 await ctx . FillStyleAsync ( "rgba(255,255,255,0.88)" ) ;
345345 await ctx . BeginPathAsync ( ) ;
346- await ctx . ArcAsync ( ex - eyeR * 0.2 , ey - eyeR * 0.2 , eyeR * 0.24 , 0 , Math . PI * 2 ) ;
346+ await ctx . ArcAsync ( ex - eyeR * 0.2 , ey - eyeR * 0.2 , eyeR * 0.24 , 0 , DoublePI ) ;
347347 await ctx . FillAsync ( FillRule . NonZero ) ;
348348 }
349349 }
350350 }
351351
352- ( double X , double Y ) ? GetNearestFoodPos ( ) => _snake . GetNearestFoodPos ( ) ;
353-
354352 async ValueTask DrawSnakeBodyAsync ( Batch2D ctx ) {
355- var baseR = _cellSize * 0.44 ;
356- var tailR = baseR * 0.35 ;
353+
357354 var bodyPoints = _bodyPoints ;
358355 bodyPoints . Clear ( ) ;
359356 for ( var i = _snake . Parts . Count - 1 ; i >= 0 ; i -- ) {
@@ -386,7 +383,7 @@ async ValueTask TraceBodyPathAsync() {
386383
387384 await ctx . SaveAsync ( ) ;
388385 await ctx . StrokeStyleAsync ( "rgba(0,0,0,0.25)" ) ;
389- await ctx . LineWidthAsync ( baseR * 2.2 ) ;
386+ await ctx . LineWidthAsync ( _baseR * 2.2 ) ;
390387 await ctx . TranslateAsync ( 1.5 , 2 ) ;
391388 await TraceBodyPathAsync ( ) ;
392389 await ctx . StrokeAsync ( ) ;
@@ -399,30 +396,30 @@ await ctx.StrokeStyleAsync(tail.X, tail.Y, _snake.Head.CurrentScreenPos.X, _snak
399396 ( 0d , Neon . SnakeSecondary ) ,
400397 ( 0.55 , "#4fb9ff" ) ,
401398 ( 1d , Neon . SnakePrimary ) ) ;
402- await ctx . LineWidthAsync ( baseR * 2.05 ) ;
399+ await ctx . LineWidthAsync ( _baseR * 2.05 ) ;
403400 await TraceBodyPathAsync ( ) ;
404401 await ctx . StrokeAsync ( ) ;
405402 await ctx . RestoreAsync ( ) ;
406403
407404 await ctx . StrokeStyleAsync ( "rgba(170, 238, 255, 0.7)" ) ;
408- await ctx . LineWidthAsync ( baseR * 1.12 ) ;
405+ await ctx . LineWidthAsync ( _baseR * 1.12 ) ;
409406 await TraceBodyPathAsync ( ) ;
410407 await ctx . StrokeAsync ( ) ;
411408
412409 await ctx . StrokeStyleAsync ( "rgba(255,255,255,0.24)" ) ;
413- await ctx . LineWidthAsync ( baseR * 0.48 ) ;
410+ await ctx . LineWidthAsync ( _baseR * 0.48 ) ;
414411 await ctx . SaveAsync ( ) ;
415- await ctx . TranslateAsync ( 0 , - baseR * 0.14 ) ;
412+ await ctx . TranslateAsync ( 0 , - _baseR * 0.14 ) ;
416413 await TraceBodyPathAsync ( ) ;
417414 await ctx . StrokeAsync ( ) ;
418415 await ctx . RestoreAsync ( ) ;
419416
420417 await ctx . SaveAsync ( ) ;
421418 await ctx . TranslateAsync ( tail . X , tail . Y ) ;
422419 await ctx . RotateAsync ( tailAngle ) ;
423- await ctx . FillStyleAsync ( - tailR * 0.5 , - tailR * 0.2 , tailR * 0.2 , 0 , 0 , tailR * 1.4 , TailGradientStops ) ;
420+ await ctx . FillStyleAsync ( - _tailR * 0.5 , - _tailR * 0.2 , _tailR * 0.2 , 0 , 0 , _tailR * 1.4 , TailGradientStops ) ;
424421 await ctx . BeginPathAsync ( ) ;
425- await ctx . EllipseAsync ( 0 , 0 , tailR * 1.2 , tailR * 0.9 , 0 , 0 , Math . PI * 2 ) ;
422+ await ctx . EllipseAsync ( 0 , 0 , _tailR * 1.2 , _tailR * 0.9 , 0 , 0 , DoublePI ) ;
426423 await ctx . FillAsync ( FillRule . NonZero ) ;
427424 await ctx . RestoreAsync ( ) ;
428425 }
@@ -477,18 +474,18 @@ await ctx.FillStyleAsync(-hr * 0.5, -hr * 0.55, hr * 0.6, hr * 0.4,
477474
478475 await ctx . FillStyleAsync ( "rgba(255,255,255,0.3)" ) ;
479476 await ctx . BeginPathAsync ( ) ;
480- await ctx . EllipseAsync ( - hr * 0.14 , - hr * 0.36 , hr * 0.4 , hr * 0.17 , - 0.35 , 0 , Math . PI * 2 ) ;
477+ await ctx . EllipseAsync ( - hr * 0.14 , - hr * 0.36 , hr * 0.4 , hr * 0.17 , - 0.35 , 0 , DoublePI ) ;
481478 await ctx . FillAsync ( FillRule . NonZero ) ;
482479
483480 await ctx . FillStyleAsync ( "rgba(255, 145, 215, 0.28)" ) ;
484481 await ctx . BeginPathAsync ( ) ;
485- await ctx . EllipseAsync ( hr * 0.14 , - hr * 0.54 , hr * 0.14 , hr * 0.09 , 0 , 0 , Math . PI * 2 ) ;
482+ await ctx . EllipseAsync ( hr * 0.14 , - hr * 0.54 , hr * 0.14 , hr * 0.09 , 0 , 0 , DoublePI ) ;
486483 await ctx . FillAsync ( FillRule . NonZero ) ;
487484 await ctx . BeginPathAsync ( ) ;
488- await ctx . EllipseAsync ( hr * 0.14 , hr * 0.54 , hr * 0.14 , hr * 0.09 , 0 , 0 , Math . PI * 2 ) ;
485+ await ctx . EllipseAsync ( hr * 0.14 , hr * 0.54 , hr * 0.14 , hr * 0.09 , 0 , 0 , DoublePI ) ;
489486 await ctx . FillAsync ( FillRule . NonZero ) ;
490487
491- var foodPos = GetNearestFoodPos ( ) ;
488+ var foodPos = _snake . GetNearestFoodPos ( ) ;
492489 var eyeR = hr * 0.21 ;
493490 var eyeX = hr * 0.06 ;
494491 var eyeY = hr * 0.5 ;
@@ -499,13 +496,13 @@ await ctx.FillStyleAsync(-hr * 0.5, -hr * 0.55, hr * 0.6, hr * 0.4,
499496
500497 await ctx . FillStyleAsync ( "rgba(238,255,255,0.98)" ) ;
501498 await ctx . BeginPathAsync ( ) ;
502- await ctx . ArcAsync ( ex , ey , eyeR , 0 , Math . PI * 2 ) ;
499+ await ctx . ArcAsync ( ex , ey , eyeR , 0 , DoublePI ) ;
503500 await ctx . FillAsync ( FillRule . NonZero ) ;
504501
505502 await ctx . StrokeStyleAsync ( "rgba(130, 195, 255, 0.8)" ) ;
506503 await ctx . LineWidthAsync ( 1.2 ) ;
507504 await ctx . BeginPathAsync ( ) ;
508- await ctx . ArcAsync ( ex , ey , eyeR , 0 , Math . PI * 2 ) ;
505+ await ctx . ArcAsync ( ex , ey , eyeR , 0 , DoublePI ) ;
509506 await ctx . StrokeAsync ( ) ;
510507
511508 var lookX = 1d ;
@@ -527,36 +524,36 @@ await ctx.FillStyleAsync(-hr * 0.5, -hr * 0.55, hr * 0.6, hr * 0.4,
527524
528525 await ctx . FillStyleAsync ( "#2a2060" ) ;
529526 await ctx . BeginPathAsync ( ) ;
530- await ctx . ArcAsync ( pupilX , pupilY , eyeR * 0.48 , 0 , Math . PI * 2 ) ;
527+ await ctx . ArcAsync ( pupilX , pupilY , eyeR * 0.48 , 0 , DoublePI ) ;
531528 await ctx . FillAsync ( FillRule . NonZero ) ;
532529
533530 await ctx . FillStyleAsync ( "rgba(255,255,255,0.92)" ) ;
534531 await ctx . BeginPathAsync ( ) ;
535- await ctx . ArcAsync ( pupilX - eyeR * 0.16 , pupilY - eyeR * 0.14 , eyeR * 0.18 , 0 , Math . PI * 2 ) ;
532+ await ctx . ArcAsync ( pupilX - eyeR * 0.16 , pupilY - eyeR * 0.14 , eyeR * 0.18 , 0 , DoublePI ) ;
536533 await ctx . FillAsync ( FillRule . NonZero ) ;
537534
538535 await ctx . FillStyleAsync ( "rgba(255,255,255,0.5)" ) ;
539536 await ctx . BeginPathAsync ( ) ;
540- await ctx . ArcAsync ( pupilX + eyeR * 0.1 , pupilY + eyeR * 0.14 , eyeR * 0.08 , 0 , Math . PI * 2 ) ;
537+ await ctx . ArcAsync ( pupilX + eyeR * 0.1 , pupilY + eyeR * 0.14 , eyeR * 0.08 , 0 , DoublePI ) ;
541538 await ctx . FillAsync ( FillRule . NonZero ) ;
542539 }
543540
544541 await ctx . FillStyleAsync ( "rgba(25, 45, 105, 0.5)" ) ;
545542 await ctx . BeginPathAsync ( ) ;
546- await ctx . ArcAsync ( hr * 0.46 , - hr * 0.1 , hr * 0.042 , 0 , Math . PI * 2 ) ;
543+ await ctx . ArcAsync ( hr * 0.46 , - hr * 0.1 , hr * 0.042 , 0 , DoublePI ) ;
547544 await ctx . FillAsync ( FillRule . NonZero ) ;
548545 await ctx . BeginPathAsync ( ) ;
549- await ctx . ArcAsync ( hr * 0.46 , hr * 0.1 , hr * 0.042 , 0 , Math . PI * 2 ) ;
546+ await ctx . ArcAsync ( hr * 0.46 , hr * 0.1 , hr * 0.042 , 0 , DoublePI ) ;
550547 await ctx . FillAsync ( FillRule . NonZero ) ;
551548
552549 if ( _snake . EatBounce > 0.3 ) {
553550 await ctx . FillStyleAsync ( "#ff60bc" ) ;
554551 await ctx . BeginPathAsync ( ) ;
555- await ctx . EllipseAsync ( hr * 0.76 , 0 , hr * 0.32 , hr * 0.60 , 0 , 0 , Math . PI * 2 ) ;
552+ await ctx . EllipseAsync ( hr * 0.76 , 0 , hr * 0.32 , hr * 0.60 , 0 , 0 , DoublePI ) ;
556553 await ctx . FillAsync ( FillRule . NonZero ) ;
557554 await ctx . FillStyleAsync ( "#ffd8f4" ) ;
558555 await ctx . BeginPathAsync ( ) ;
559- await ctx . ArcAsync ( hr * 0.76 , 0 , hr * 0.152 , 0 , Math . PI * 2 ) ;
556+ await ctx . ArcAsync ( hr * 0.76 , 0 , hr * 0.152 , 0 , DoublePI ) ;
560557 await ctx . FillAsync ( FillRule . NonZero ) ;
561558 }
562559
@@ -582,6 +579,8 @@ await ctx.FillStyleAsync(-hr * 0.5, -hr * 0.55, hr * 0.6, hr * 0.4,
582579 }
583580
584581 async ValueTask DrawParticlesAsync ( Batch2D ctx ) {
582+ if ( _snake . EatParticles . Count == 0 ) return ;
583+
585584 foreach ( var p in _snake . EatParticles ) {
586585 var size = 4 * p . Life ;
587586 await ctx . GlobalAlphaAsync ( p . Life ) ;
@@ -591,7 +590,7 @@ async ValueTask DrawParticlesAsync(Batch2D ctx) {
591590
592591 await ctx . BeginPathAsync ( ) ;
593592 for ( var s = 0 ; s < 5 ; s ++ ) {
594- var a = ( s / 5d ) * Math . PI * 2 - Math . PI / 2 ;
593+ var a = ( s / 5d ) * DoublePI - Math . PI / 2 ;
595594 var ox = Math . Cos ( a ) * size ;
596595 var oy = Math . Sin ( a ) * size ;
597596 if ( s == 0 ) {
@@ -614,6 +613,8 @@ async ValueTask DrawParticlesAsync(Batch2D ctx) {
614613 }
615614
616615 async ValueTask DrawHitParticlesAsync ( Batch2D ctx ) {
616+ if ( _snake . HitParticles . Count == 0 ) return ;
617+
617618 foreach ( var p in _snake . HitParticles ) {
618619 await ctx . GlobalAlphaAsync ( p . Life ) ;
619620 await ctx . FillStyleAsync ( p . Color ) ;
@@ -658,21 +659,21 @@ async ValueTask DrawDeathSegmentsAsync(Batch2D ctx) {
658659 var r = seg . R * ( 1 - progress * 0.4 ) ;
659660 await ctx . FillStyleAsync ( "rgba(0,0,0,0.22)" ) ;
660661 await ctx . BeginPathAsync ( ) ;
661- await ctx . ArcAsync ( 1.5 , 2 , r , 0 , Math . PI * 2 ) ;
662+ await ctx . ArcAsync ( 1.5 , 2 , r , 0 , DoublePI ) ;
662663 await ctx . FillAsync ( FillRule . NonZero ) ;
663664
664665 var baseColor = i % 2 == 0 ? Neon . SnakePrimary : Neon . SnakeSecondary ;
665666 await ctx . FillStyleAsync ( flashOn ? Neon . Danger : baseColor ) ;
666667 await ctx . ShadowColorAsync ( flashOn ? Neon . DangerGlow : Neon . SnakeGlow ) ;
667668 await ctx . ShadowBlurAsync ( 14 ) ;
668669 await ctx . BeginPathAsync ( ) ;
669- await ctx . ArcAsync ( 0 , 0 , r , 0 , Math . PI * 2 ) ;
670+ await ctx . ArcAsync ( 0 , 0 , r , 0 , DoublePI ) ;
670671 await ctx . FillAsync ( FillRule . NonZero ) ;
671672 await ctx . ShadowBlurAsync ( 0 ) ;
672673
673674 await ctx . FillStyleAsync ( "rgba(255,255,255,0.35)" ) ;
674675 await ctx . BeginPathAsync ( ) ;
675- await ctx . ArcAsync ( - r * 0.25 , - r * 0.25 , r * 0.35 , 0 , Math . PI * 2 ) ;
676+ await ctx . ArcAsync ( - r * 0.25 , - r * 0.25 , r * 0.35 , 0 , DoublePI ) ;
676677 await ctx . FillAsync ( FillRule . NonZero ) ;
677678
678679 if ( seg . IsHead && progress < 0.6 ) {
@@ -758,7 +759,7 @@ async ValueTask DrawHeartAsync(Batch2D ctx, double cx, double cy, double size, s
758759 if ( ! isOff ) {
759760 await ctx . FillStyleAsync ( "rgba(255,255,255,0.45)" ) ;
760761 await ctx . BeginPathAsync ( ) ;
761- await ctx . ArcAsync ( cx - size * 0.35 , cy + size * 0.05 , size * 0.25 , 0 , Math . PI * 2 ) ;
762+ await ctx . ArcAsync ( cx - size * 0.35 , cy + size * 0.05 , size * 0.25 , 0 , DoublePI ) ;
762763 await ctx . FillAsync ( FillRule . NonZero ) ;
763764 }
764765 }
0 commit comments