@jonelhatwell/arcade-games 1.2.18 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +362 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +82 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +361 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -392,8 +392,369 @@ var MemoryGame = () => {
|
|
|
392
392
|
] });
|
|
393
393
|
};
|
|
394
394
|
var memorygame_default = MemoryGame;
|
|
395
|
+
|
|
396
|
+
// src/components/games/snake/index.tsx
|
|
397
|
+
import { useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
|
|
398
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
399
|
+
var config3 = {
|
|
400
|
+
gridSize: 20,
|
|
401
|
+
cellSize: 20,
|
|
402
|
+
initialSpeed: 150,
|
|
403
|
+
speedIncrement: 5
|
|
404
|
+
};
|
|
405
|
+
var SnakeGame = () => {
|
|
406
|
+
const canvasRef = useRef3(null);
|
|
407
|
+
const [message, setMessage] = useState3("Use arrow keys or WASD to play!");
|
|
408
|
+
const [showOverlay, setShowOverlay] = useState3({
|
|
409
|
+
visible: false,
|
|
410
|
+
text: ""
|
|
411
|
+
});
|
|
412
|
+
const gameStateRef = useRef3({
|
|
413
|
+
snake: [{ x: 10, y: 10 }],
|
|
414
|
+
food: { x: 15, y: 15 },
|
|
415
|
+
bonusFood: [],
|
|
416
|
+
direction: "RIGHT",
|
|
417
|
+
nextDirection: "RIGHT",
|
|
418
|
+
score: 0,
|
|
419
|
+
speed: config3.initialSpeed,
|
|
420
|
+
phase: "playing"
|
|
421
|
+
});
|
|
422
|
+
const generateFood = (snake) => {
|
|
423
|
+
let food;
|
|
424
|
+
do {
|
|
425
|
+
food = {
|
|
426
|
+
x: Math.floor(Math.random() * config3.gridSize),
|
|
427
|
+
y: Math.floor(Math.random() * config3.gridSize)
|
|
428
|
+
};
|
|
429
|
+
} while (snake.some((seg) => seg.x === food.x && seg.y === food.y));
|
|
430
|
+
return food;
|
|
431
|
+
};
|
|
432
|
+
const generateBonusFood = (snake, regularFood, count = 3) => {
|
|
433
|
+
const bonusFood = [];
|
|
434
|
+
for (let i = 0; i < count; i++) {
|
|
435
|
+
let food;
|
|
436
|
+
do {
|
|
437
|
+
food = {
|
|
438
|
+
x: Math.floor(Math.random() * config3.gridSize),
|
|
439
|
+
y: Math.floor(Math.random() * config3.gridSize)
|
|
440
|
+
};
|
|
441
|
+
} while (snake.some((seg) => seg.x === food.x && seg.y === food.y) || food.x === regularFood.x && food.y === regularFood.y || bonusFood.some((bf) => bf.x === food.x && bf.y === food.y));
|
|
442
|
+
bonusFood.push(food);
|
|
443
|
+
}
|
|
444
|
+
return bonusFood;
|
|
445
|
+
};
|
|
446
|
+
const initGame = () => {
|
|
447
|
+
const initialSnake = [{ x: 10, y: 10 }];
|
|
448
|
+
gameStateRef.current = {
|
|
449
|
+
snake: initialSnake,
|
|
450
|
+
food: generateFood(initialSnake),
|
|
451
|
+
bonusFood: [],
|
|
452
|
+
direction: "RIGHT",
|
|
453
|
+
nextDirection: "RIGHT",
|
|
454
|
+
score: 0,
|
|
455
|
+
speed: config3.initialSpeed,
|
|
456
|
+
phase: "playing"
|
|
457
|
+
};
|
|
458
|
+
setMessage("Use arrow keys or WASD to play!");
|
|
459
|
+
};
|
|
460
|
+
const checkCollision = (head, snake) => {
|
|
461
|
+
return snake.some((seg) => seg.x === head.x && seg.y === head.y);
|
|
462
|
+
};
|
|
463
|
+
const moveSnake = () => {
|
|
464
|
+
const state2 = gameStateRef.current;
|
|
465
|
+
if (state2.phase !== "playing") return;
|
|
466
|
+
state2.direction = state2.nextDirection;
|
|
467
|
+
const head = { ...state2.snake[0] };
|
|
468
|
+
switch (state2.direction) {
|
|
469
|
+
case "UP":
|
|
470
|
+
head.y -= 1;
|
|
471
|
+
break;
|
|
472
|
+
case "DOWN":
|
|
473
|
+
head.y += 1;
|
|
474
|
+
break;
|
|
475
|
+
case "LEFT":
|
|
476
|
+
head.x -= 1;
|
|
477
|
+
break;
|
|
478
|
+
case "RIGHT":
|
|
479
|
+
head.x += 1;
|
|
480
|
+
break;
|
|
481
|
+
}
|
|
482
|
+
if (head.x < 0) head.x = config3.gridSize - 1;
|
|
483
|
+
if (head.x >= config3.gridSize) head.x = 0;
|
|
484
|
+
if (head.y < 0) head.y = config3.gridSize - 1;
|
|
485
|
+
if (head.y >= config3.gridSize) head.y = 0;
|
|
486
|
+
if (checkCollision(head, state2.snake)) {
|
|
487
|
+
state2.phase = "gameover";
|
|
488
|
+
setShowOverlay({ visible: true, text: "Game Over! \u{1F480}" });
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
const newSnake = [head, ...state2.snake];
|
|
492
|
+
let ateFood = false;
|
|
493
|
+
if (head.x === state2.food.x && head.y === state2.food.y) {
|
|
494
|
+
state2.score += 10;
|
|
495
|
+
state2.speed = Math.max(50, state2.speed - config3.speedIncrement);
|
|
496
|
+
state2.food = generateFood(newSnake);
|
|
497
|
+
ateFood = true;
|
|
498
|
+
setMessage(`Score: ${state2.score} \u{1F34E}`);
|
|
499
|
+
if (state2.score % 50 === 0 && state2.score > 0) {
|
|
500
|
+
state2.bonusFood = generateBonusFood(newSnake, state2.food);
|
|
501
|
+
setMessage(`Score: ${state2.score} \u{1F34E} BONUS FOOD! \u2B50`);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
const bonusFoodIndex = state2.bonusFood.findIndex(
|
|
505
|
+
(bf) => bf.x === head.x && bf.y === head.y
|
|
506
|
+
);
|
|
507
|
+
if (bonusFoodIndex !== -1) {
|
|
508
|
+
state2.score += 10;
|
|
509
|
+
state2.bonusFood.splice(bonusFoodIndex, 1);
|
|
510
|
+
ateFood = true;
|
|
511
|
+
setMessage(`Score: ${state2.score} \u2B50 Bonus!`);
|
|
512
|
+
}
|
|
513
|
+
if (!ateFood) {
|
|
514
|
+
newSnake.pop();
|
|
515
|
+
}
|
|
516
|
+
state2.snake = newSnake;
|
|
517
|
+
};
|
|
518
|
+
const handleDirectionChange = (newDirection) => {
|
|
519
|
+
const state2 = gameStateRef.current;
|
|
520
|
+
const opposites = {
|
|
521
|
+
UP: "DOWN",
|
|
522
|
+
DOWN: "UP",
|
|
523
|
+
LEFT: "RIGHT",
|
|
524
|
+
RIGHT: "LEFT"
|
|
525
|
+
};
|
|
526
|
+
if (opposites[state2.direction] !== newDirection) {
|
|
527
|
+
state2.nextDirection = newDirection;
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
const togglePause = () => {
|
|
531
|
+
const state2 = gameStateRef.current;
|
|
532
|
+
if (state2.phase === "playing") {
|
|
533
|
+
state2.phase = "paused";
|
|
534
|
+
setMessage("Game Paused");
|
|
535
|
+
} else if (state2.phase === "paused") {
|
|
536
|
+
state2.phase = "playing";
|
|
537
|
+
setMessage("Use arrow keys or WASD to play!");
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
const resetGame = () => {
|
|
541
|
+
setShowOverlay({ visible: false, text: "" });
|
|
542
|
+
initGame();
|
|
543
|
+
};
|
|
544
|
+
useEffect3(() => {
|
|
545
|
+
initGame();
|
|
546
|
+
const onKeyDown = (e) => {
|
|
547
|
+
const key = e.key.toLowerCase();
|
|
548
|
+
if (key === " ") {
|
|
549
|
+
e.preventDefault();
|
|
550
|
+
togglePause();
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
if (gameStateRef.current.phase !== "playing") return;
|
|
554
|
+
switch (key) {
|
|
555
|
+
case "arrowup":
|
|
556
|
+
case "w":
|
|
557
|
+
e.preventDefault();
|
|
558
|
+
handleDirectionChange("UP");
|
|
559
|
+
break;
|
|
560
|
+
case "arrowdown":
|
|
561
|
+
case "s":
|
|
562
|
+
e.preventDefault();
|
|
563
|
+
handleDirectionChange("DOWN");
|
|
564
|
+
break;
|
|
565
|
+
case "arrowleft":
|
|
566
|
+
case "a":
|
|
567
|
+
e.preventDefault();
|
|
568
|
+
handleDirectionChange("LEFT");
|
|
569
|
+
break;
|
|
570
|
+
case "arrowright":
|
|
571
|
+
case "d":
|
|
572
|
+
e.preventDefault();
|
|
573
|
+
handleDirectionChange("RIGHT");
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
window.addEventListener("keydown", onKeyDown);
|
|
578
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
579
|
+
}, []);
|
|
580
|
+
useEffect3(() => {
|
|
581
|
+
const interval = setInterval(() => {
|
|
582
|
+
moveSnake();
|
|
583
|
+
}, gameStateRef.current.speed);
|
|
584
|
+
return () => clearInterval(interval);
|
|
585
|
+
}, []);
|
|
586
|
+
useEffect3(() => {
|
|
587
|
+
const canvas = canvasRef.current;
|
|
588
|
+
if (!canvas) return;
|
|
589
|
+
const ctx = canvas.getContext("2d");
|
|
590
|
+
if (!ctx) return;
|
|
591
|
+
let animationId;
|
|
592
|
+
const draw = () => {
|
|
593
|
+
const state2 = gameStateRef.current;
|
|
594
|
+
const width = config3.gridSize * config3.cellSize;
|
|
595
|
+
const height = config3.gridSize * config3.cellSize;
|
|
596
|
+
ctx.fillStyle = "#1a1a2e";
|
|
597
|
+
ctx.fillRect(0, 0, width, height);
|
|
598
|
+
ctx.strokeStyle = "#16213e";
|
|
599
|
+
ctx.lineWidth = 1;
|
|
600
|
+
for (let i = 0; i <= config3.gridSize; i++) {
|
|
601
|
+
ctx.beginPath();
|
|
602
|
+
ctx.moveTo(i * config3.cellSize, 0);
|
|
603
|
+
ctx.lineTo(i * config3.cellSize, height);
|
|
604
|
+
ctx.stroke();
|
|
605
|
+
ctx.beginPath();
|
|
606
|
+
ctx.moveTo(0, i * config3.cellSize);
|
|
607
|
+
ctx.lineTo(width, i * config3.cellSize);
|
|
608
|
+
ctx.stroke();
|
|
609
|
+
}
|
|
610
|
+
ctx.fillStyle = "#ef4444";
|
|
611
|
+
ctx.beginPath();
|
|
612
|
+
ctx.arc(
|
|
613
|
+
state2.food.x * config3.cellSize + config3.cellSize / 2,
|
|
614
|
+
state2.food.y * config3.cellSize + config3.cellSize / 2,
|
|
615
|
+
config3.cellSize / 2 - 2,
|
|
616
|
+
0,
|
|
617
|
+
Math.PI * 2
|
|
618
|
+
);
|
|
619
|
+
ctx.fill();
|
|
620
|
+
state2.bonusFood.forEach((bf) => {
|
|
621
|
+
ctx.fillStyle = "#fbbf24";
|
|
622
|
+
ctx.strokeStyle = "#f59e0b";
|
|
623
|
+
ctx.lineWidth = 2;
|
|
624
|
+
const centerX = bf.x * config3.cellSize + config3.cellSize / 2;
|
|
625
|
+
const centerY = bf.y * config3.cellSize + config3.cellSize / 2;
|
|
626
|
+
const outerRadius = config3.cellSize / 2 - 2;
|
|
627
|
+
const innerRadius = outerRadius / 2;
|
|
628
|
+
const points = 5;
|
|
629
|
+
ctx.beginPath();
|
|
630
|
+
for (let i = 0; i < points * 2; i++) {
|
|
631
|
+
const radius = i % 2 === 0 ? outerRadius : innerRadius;
|
|
632
|
+
const angle = Math.PI * i / points - Math.PI / 2;
|
|
633
|
+
const x = centerX + Math.cos(angle) * radius;
|
|
634
|
+
const y = centerY + Math.sin(angle) * radius;
|
|
635
|
+
if (i === 0) {
|
|
636
|
+
ctx.moveTo(x, y);
|
|
637
|
+
} else {
|
|
638
|
+
ctx.lineTo(x, y);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
ctx.closePath();
|
|
642
|
+
ctx.fill();
|
|
643
|
+
ctx.stroke();
|
|
644
|
+
});
|
|
645
|
+
state2.snake.forEach((seg, idx) => {
|
|
646
|
+
if (idx === 0) {
|
|
647
|
+
ctx.fillStyle = "#22c55e";
|
|
648
|
+
} else {
|
|
649
|
+
ctx.fillStyle = "#16a34a";
|
|
650
|
+
}
|
|
651
|
+
ctx.fillRect(
|
|
652
|
+
seg.x * config3.cellSize + 1,
|
|
653
|
+
seg.y * config3.cellSize + 1,
|
|
654
|
+
config3.cellSize - 2,
|
|
655
|
+
config3.cellSize - 2
|
|
656
|
+
);
|
|
657
|
+
});
|
|
658
|
+
animationId = requestAnimationFrame(draw);
|
|
659
|
+
};
|
|
660
|
+
draw();
|
|
661
|
+
return () => cancelAnimationFrame(animationId);
|
|
662
|
+
}, []);
|
|
663
|
+
const state = gameStateRef.current;
|
|
664
|
+
const canvasSize = config3.gridSize * config3.cellSize;
|
|
665
|
+
return /* @__PURE__ */ jsxs3("div", { className: "relative flex flex-col items-center gap-4 p-4 max-w-xl mx-auto", children: [
|
|
666
|
+
/* @__PURE__ */ jsx4("div", { className: "text-3xl font-bold text-green-500", children: "\u{1F40D} Snake Game" }),
|
|
667
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex gap-8 text-lg", children: [
|
|
668
|
+
/* @__PURE__ */ jsxs3("div", { className: "text-yellow-400", children: [
|
|
669
|
+
"Score: ",
|
|
670
|
+
/* @__PURE__ */ jsx4("span", { className: "font-bold", children: state.score })
|
|
671
|
+
] }),
|
|
672
|
+
/* @__PURE__ */ jsxs3("div", { className: "text-blue-400", children: [
|
|
673
|
+
"Length: ",
|
|
674
|
+
/* @__PURE__ */ jsx4("span", { className: "font-bold", children: state.snake.length })
|
|
675
|
+
] })
|
|
676
|
+
] }),
|
|
677
|
+
/* @__PURE__ */ jsx4(
|
|
678
|
+
"canvas",
|
|
679
|
+
{
|
|
680
|
+
ref: canvasRef,
|
|
681
|
+
width: canvasSize,
|
|
682
|
+
height: canvasSize,
|
|
683
|
+
className: "border-4 border-green-600 rounded-lg shadow-xl"
|
|
684
|
+
}
|
|
685
|
+
),
|
|
686
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex gap-2", children: [
|
|
687
|
+
/* @__PURE__ */ jsx4(Button, { onClick: togglePause, variant: "outline", disabled: state.phase === "gameover", children: state.phase === "paused" ? "Resume" : "Pause" }),
|
|
688
|
+
/* @__PURE__ */ jsx4(Button, { onClick: resetGame, variant: "outline", children: "Restart" })
|
|
689
|
+
] }),
|
|
690
|
+
/* @__PURE__ */ jsx4("div", { className: "text-sm text-center text-blue-400 h-5", children: message }),
|
|
691
|
+
/* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-3 gap-2 w-48", children: [
|
|
692
|
+
/* @__PURE__ */ jsx4("div", {}),
|
|
693
|
+
/* @__PURE__ */ jsx4(
|
|
694
|
+
Button,
|
|
695
|
+
{
|
|
696
|
+
size: "lg",
|
|
697
|
+
variant: "outline",
|
|
698
|
+
onClick: () => handleDirectionChange("UP"),
|
|
699
|
+
disabled: state.phase !== "playing",
|
|
700
|
+
className: "text-2xl",
|
|
701
|
+
children: "\u2191"
|
|
702
|
+
}
|
|
703
|
+
),
|
|
704
|
+
/* @__PURE__ */ jsx4("div", {}),
|
|
705
|
+
/* @__PURE__ */ jsx4(
|
|
706
|
+
Button,
|
|
707
|
+
{
|
|
708
|
+
size: "lg",
|
|
709
|
+
variant: "outline",
|
|
710
|
+
onClick: () => handleDirectionChange("LEFT"),
|
|
711
|
+
disabled: state.phase !== "playing",
|
|
712
|
+
className: "text-2xl",
|
|
713
|
+
children: "\u2190"
|
|
714
|
+
}
|
|
715
|
+
),
|
|
716
|
+
/* @__PURE__ */ jsx4(
|
|
717
|
+
Button,
|
|
718
|
+
{
|
|
719
|
+
size: "lg",
|
|
720
|
+
variant: "outline",
|
|
721
|
+
onClick: () => handleDirectionChange("DOWN"),
|
|
722
|
+
disabled: state.phase !== "playing",
|
|
723
|
+
className: "text-2xl",
|
|
724
|
+
children: "\u2193"
|
|
725
|
+
}
|
|
726
|
+
),
|
|
727
|
+
/* @__PURE__ */ jsx4(
|
|
728
|
+
Button,
|
|
729
|
+
{
|
|
730
|
+
size: "lg",
|
|
731
|
+
variant: "outline",
|
|
732
|
+
onClick: () => handleDirectionChange("RIGHT"),
|
|
733
|
+
disabled: state.phase !== "playing",
|
|
734
|
+
className: "text-2xl",
|
|
735
|
+
children: "\u2192"
|
|
736
|
+
}
|
|
737
|
+
)
|
|
738
|
+
] }),
|
|
739
|
+
showOverlay.visible && /* @__PURE__ */ jsxs3("div", { className: "absolute inset-0 flex flex-col items-center justify-center bg-black/80 rounded-lg", children: [
|
|
740
|
+
/* @__PURE__ */ jsx4("p", { className: "text-4xl font-bold mb-4 text-red-500", children: showOverlay.text }),
|
|
741
|
+
/* @__PURE__ */ jsxs3("p", { className: "mb-2 text-xl text-gray-300", children: [
|
|
742
|
+
"Final Score: ",
|
|
743
|
+
/* @__PURE__ */ jsx4("strong", { className: "text-yellow-400", children: state.score })
|
|
744
|
+
] }),
|
|
745
|
+
/* @__PURE__ */ jsxs3("p", { className: "mb-6 text-lg text-gray-300", children: [
|
|
746
|
+
"Length: ",
|
|
747
|
+
/* @__PURE__ */ jsx4("strong", { className: "text-green-400", children: state.snake.length })
|
|
748
|
+
] }),
|
|
749
|
+
/* @__PURE__ */ jsx4(Button, { onClick: resetGame, size: "lg", className: "bg-green-600 hover:bg-green-700", children: "Play Again" })
|
|
750
|
+
] }),
|
|
751
|
+
/* @__PURE__ */ jsx4("div", { className: "text-xs text-center text-gray-400 max-w-md", children: "Arrow keys or WASD to move \u2022 Space to pause \u2022 Red apple = +10 pts \u2022 Golden star = +10 pts (every 50 pts)" })
|
|
752
|
+
] });
|
|
753
|
+
};
|
|
754
|
+
var snake_default = SnakeGame;
|
|
395
755
|
export {
|
|
396
756
|
memorygame_default as MemoryGame,
|
|
757
|
+
snake_default as Snake,
|
|
397
758
|
spacedodger_default as SpaceDodger
|
|
398
759
|
};
|
|
399
760
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/games/spacedodger/index.tsx","../src/components/ui/button.tsx","../src/lib/utils.ts","../src/components/games/memorygame/index.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport { Button } from '@/components/ui/button';\n\ninterface Position {\n x: number;\n y: number;\n}\n\ninterface Enemy extends Position {\n radius: number;\n}\n\ninterface Player extends Position {\n width: number;\n height: number;\n}\n\ninterface SpaceDodgerState {\n player: Player;\n enemies: Enemy[];\n frame: number;\n keys: Record<string, boolean>;\n}\n\n\nconst config = {\n canvasSize : { \n width: 450, \n height: 450 \n },\n player: { x: 200, y: 350, width: 25, height: 50 }\n}\n\nconst SpaceDodger: React.FC = () => {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const scoreRef = useRef(0);\n const lastBatchScoreRef = useRef(0);\n\n const [score, setScore] = useState(0);\n const [gameOver, setGameOver] = useState(false);\n\n const gameStateRef = useRef<SpaceDodgerState>({\n player: config.player,\n enemies: [],\n frame: 0,\n keys: {}\n });\n\n const resetGame = () => {\n gameStateRef.current = {\n player: config.player,\n enemies: [],\n frame: 0,\n keys: {}\n };\n scoreRef.current = 0;\n lastBatchScoreRef.current = 0;\n setScore(0);\n setGameOver(false);\n };\n\n\n \n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n const state = gameStateRef.current;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n state.keys[e.key] = true;\n };\n const handleKeyUp = (e: KeyboardEvent) => {\n state.keys[e.key] = false;\n };\n\n window.addEventListener('keydown', handleKeyDown);\n window.addEventListener('keyup', handleKeyUp);\n\n const randomRadius = () => 10 + Math.random() * 15;\n\n const getEnemySpeed = () => {\n const base = 3;\n const increase = Math.floor(scoreRef.current / 20) * 0.5;\n return base + increase;\n };\n\n let animationId: number;\n\n const gameLoop = () => {\n if (gameOver) return;\n\n state.frame++;\n\n ctx.fillStyle = '#000';\n ctx.fillRect(0, 0, config.canvasSize.width, config.canvasSize.height);\n\n // Player movement\n if (state.keys['ArrowLeft'] && state.player.x > 0) state.player.x -= 5;\n if (state.keys['ArrowRight'] && state.player.x < config.canvasSize.width - state.player.width) state.player.x += 5;\n if (state.keys['ArrowUp'] && state.player.y > 0) state.player.y -= 5;\n if (state.keys['ArrowDown'] && state.player.y < config.canvasSize.height - state.player.height) state.player.y += 5;\n\n // Draw player\n ctx.fillStyle = '#0ea5e9';\n ctx.fillRect(\n state.player.x,\n state.player.y,\n state.player.width,\n state.player.height\n );\n\n // Normal enemy spawn\n if (state.frame % 40 === 0) {\n const radius = randomRadius();\n state.enemies.push({\n x: radius + Math.random() * (config.canvasSize.width - radius * 2),\n y: -radius,\n radius,\n });\n }\n\n // Extra batch every 20 score\n if (\n scoreRef.current > 0 &&\n scoreRef.current % 20 === 0 &&\n lastBatchScoreRef.current !== scoreRef.current\n ) {\n lastBatchScoreRef.current = scoreRef.current;\n const batchCount = 2 + Math.floor(Math.random() * 3);\n\n for (let i = 0; i < batchCount; i++) {\n const radius = randomRadius();\n state.enemies.push({\n x: radius + Math.random() * (config.canvasSize.width - radius * 2),\n y: -Math.random() * 100,\n radius\n });\n }\n }\n\n // Enemies update\n state.enemies = state.enemies.filter(enemy => {\n enemy.y += getEnemySpeed();\n\n // Draw enemy (circle)\n ctx.fillStyle = '#ef4444';\n ctx.beginPath();\n ctx.arc(enemy.x, enemy.y, enemy.radius, 0, Math.PI * 2);\n ctx.fill();\n\n // Circle vs rectangle collision\n const closestX = Math.max(\n state.player.x,\n Math.min(enemy.x, state.player.x + state.player.width)\n );\n const closestY = Math.max(\n state.player.y,\n Math.min(enemy.y, state.player.y + state.player.height)\n );\n\n const dx = enemy.x - closestX;\n const dy = enemy.y - closestY;\n\n if (dx * dx + dy * dy < enemy.radius * enemy.radius) {\n setGameOver(true);\n return false;\n }\n\n // Passed screen\n if (enemy.y - enemy.radius > config.canvasSize.height) {\n setScore(s => {\n scoreRef.current = s + 1;\n return s + 1;\n });\n return false;\n }\n\n return true;\n });\n\n animationId = requestAnimationFrame(gameLoop);\n };\n\n gameLoop();\n\n return () => {\n cancelAnimationFrame(animationId);\n window.removeEventListener('keydown', handleKeyDown);\n window.removeEventListener('keyup', handleKeyUp);\n };\n }, [gameOver]);\n\n return (\n <div className=\"relative flex flex-col items-center gap-4 p-4\">\n <div className=\"text-xl font-bold\">Score: {score}</div>\n <canvas\n ref={canvasRef}\n width={config.canvasSize.width}\n height={config.canvasSize.height}\n className=\"border-2 border-gray-300\"\n />\n\n {gameOver && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center bg-black/60\">\n <p className=\"text-xl font-bold text-red-500 mb-3\">Game Over</p>\n <Button onClick={resetGame}>Play Again</Button>\n </div>\n )}\n\n <div className=\"text-sm text-foreground\">Use arrow keys to move</div>\n </div>\n );\n};\n\nexport default SpaceDodger;","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}","import React, { useEffect, useRef, useState } from 'react';\nimport { Button } from '@/components/ui/button';\n\ninterface NumberItem {\n x: number;\n y: number;\n value: number;\n radius: number;\n}\n\ntype GamePhase = 'memorize' | 'recall' | 'transition';\n\ninterface GameState {\n numbers: NumberItem[];\n sequence: number[];\n currentIndex: number;\n level: number;\n showNumbers: boolean;\n phase: GamePhase;\n revealed: Set<number>;\n}\n\nconst config = {\n canvasSize: { width: 450, height: 450 },\n baseHideTime: 3000,\n numberRadius: 30,\n};\n\nconst MemoryGame: React.FC = () => {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const [level, setLevel] = useState(1);\n const [gameOver, setGameOver] = useState(false);\n const [message, setMessage] = useState('');\n const [showOverlay, setShowOverlay] = useState<{ visible: boolean; text: string }>({\n visible: false,\n text: '',\n });\n const gameStateRef = useRef<GameState>({\n numbers: [],\n sequence: [],\n currentIndex: 0,\n level: 1,\n showNumbers: true,\n phase: 'memorize',\n revealed: new Set(),\n });\n\n // Max numbers = 9\n const getNumberCount = (lvl: number) => Math.min(4 + lvl, 9);\n\n // Hide time decreases as level increases, min 500ms\n const getHideTime = (lvl: number) =>\n Math.max(500, config.baseHideTime - Math.floor((lvl - 1) / 1) * 500);\n\n const generateNumbers = (lvl: number) => {\n const count = getNumberCount(lvl);\n const numbers: NumberItem[] = [];\n const sequence: number[] = [];\n const padding = config.numberRadius * 2.5;\n\n for (let i = 0; i < count; i++) {\n let x: number, y: number, overlap: boolean;\n let attempts = 0;\n\n do {\n overlap = false;\n x = padding + Math.random() * (config.canvasSize.width - padding * 2);\n y = padding + Math.random() * (config.canvasSize.height - padding * 2);\n\n for (const num of numbers) {\n const dx = x - num.x;\n const dy = y - num.y;\n if (Math.sqrt(dx * dx + dy * dy) < config.numberRadius * 2.5) {\n overlap = true;\n break;\n }\n }\n attempts++;\n } while (overlap && attempts < 100);\n\n numbers.push({ x, y, value: i + 1, radius: config.numberRadius });\n sequence.push(i + 1);\n }\n\n return { numbers, sequence };\n };\n\n const startLevel = (lvl: number) => {\n const { numbers, sequence } = generateNumbers(lvl);\n gameStateRef.current = {\n numbers,\n sequence,\n currentIndex: 0,\n level: lvl,\n showNumbers: true,\n phase: 'memorize',\n revealed: new Set(),\n };\n setMessage('Memorize the sequence!');\n\n setTimeout(() => {\n gameStateRef.current.showNumbers = false;\n gameStateRef.current.phase = 'recall';\n setMessage('Click the numbers in order!');\n }, getHideTime(lvl));\n };\n\n const resetGame = () => {\n setLevel(1);\n setGameOver(false);\n setShowOverlay({ visible: false, text: '' });\n startLevel(1);\n };\n\n const handleCanvasClick = (e: React.MouseEvent<HTMLCanvasElement>) => {\n if (gameOver || gameStateRef.current.phase !== 'recall') return;\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const rect = canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n const state = gameStateRef.current;\n\n for (const num of state.numbers) {\n const distance = Math.hypot(x - num.x, y - num.y);\n if (distance <= num.radius) {\n const expected = state.sequence[state.currentIndex];\n if (num.value === expected) {\n state.revealed.add(num.value);\n state.currentIndex++;\n\n if (state.currentIndex === state.sequence.length) {\n const nextLevel = level + 1;\n setLevel(nextLevel);\n state.phase = 'transition';\n setShowOverlay({ visible: true, text: `Get Ready! Level ${nextLevel}` });\n\n setTimeout(() => {\n setShowOverlay({ visible: false, text: '' });\n startLevel(nextLevel);\n }, 1500);\n }\n } else {\n setGameOver(true);\n setMessage(`Wrong! Clicked ${num.value}, expected ${expected}`);\n }\n break;\n }\n }\n };\n\n useEffect(() => startLevel(1), []);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n let animationId: number;\n\n const draw = () => {\n const state = gameStateRef.current;\n ctx.fillStyle = '#000';\n ctx.fillRect(0, 0, config.canvasSize.width, config.canvasSize.height);\n\n state.numbers.forEach((num, idx) => {\n // Show green hint only in level 1\n const isNext = state.phase === 'recall' && level === 1 && idx === state.currentIndex;\n ctx.fillStyle = isNext ? '#22c55e' : '#3b82f6';\n ctx.beginPath();\n ctx.arc(num.x, num.y, num.radius, 0, Math.PI * 2);\n ctx.fill();\n\n // Reveal numbers if memorizing, transitioning, or already correctly guessed\n if (state.showNumbers || state.phase === 'transition' || state.revealed.has(num.value)) {\n ctx.fillStyle = '#fff';\n ctx.font = 'bold 24px sans-serif';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(num.value.toString(), num.x, num.y);\n }\n });\n\n if (!gameOver) animationId = requestAnimationFrame(draw);\n };\n\n draw();\n return () => cancelAnimationFrame(animationId);\n }, [gameOver, level]);\n\n return (\n <div className=\"relative flex flex-col items-center gap-4 p-4\">\n <div className=\"flex gap-8 text-xl font-bold\">\n <div>Level: {level}</div>\n <div>Numbers: {getNumberCount(level)}</div>\n </div>\n <div className=\"text-lg font-semibold text-blue-400 h-6\">{message}</div>\n <canvas\n ref={canvasRef}\n width={config.canvasSize.width}\n height={config.canvasSize.height}\n className=\"border-2 border-gray-300 cursor-pointer\"\n onClick={handleCanvasClick}\n />\n {gameOver && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center bg-black/60\">\n <p className=\"text-xl font-bold text-red-500 mb-2\">Game Over</p>\n <p className=\"text-lg text-white mb-4\">Reached Level {level}</p>\n <Button onClick={resetGame}>Play Again</Button>\n </div>\n )}\n\n {showOverlay.visible && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center bg-black/60\">\n <p className=\"text-2xl font-bold text-yellow-400\">{showOverlay.text}</p>\n </div>\n )}\n\n <div className=\"text-sm text-center text-foreground max-w-md\">\n <div>Memorize the numbers, then click them in sequence (1, 2, 3...)</div>\n <div className=\"mt-1 text-xs text-gray-400\">Green circle = next number to click (level 1 only)</div>\n </div>\n </div>\n );\n};\n\nexport default MemoryGame;\n"],"mappings":"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","names":["jsx","useEffect","useRef","useState","jsx","jsxs","config","useRef","useState","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/games/spacedodger/index.tsx","../src/components/ui/button.tsx","../src/lib/utils.ts","../src/components/games/memorygame/index.tsx","../src/components/games/snake/index.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport { Button } from '@/components/ui/button';\n\ninterface Position {\n x: number;\n y: number;\n}\n\ninterface Enemy extends Position {\n radius: number;\n}\n\ninterface Player extends Position {\n width: number;\n height: number;\n}\n\ninterface SpaceDodgerState {\n player: Player;\n enemies: Enemy[];\n frame: number;\n keys: Record<string, boolean>;\n}\n\n\nconst config = {\n canvasSize : { \n width: 450, \n height: 450 \n },\n player: { x: 200, y: 350, width: 25, height: 50 }\n}\n\nconst SpaceDodger: React.FC = () => {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const scoreRef = useRef(0);\n const lastBatchScoreRef = useRef(0);\n\n const [score, setScore] = useState(0);\n const [gameOver, setGameOver] = useState(false);\n\n const gameStateRef = useRef<SpaceDodgerState>({\n player: config.player,\n enemies: [],\n frame: 0,\n keys: {}\n });\n\n const resetGame = () => {\n gameStateRef.current = {\n player: config.player,\n enemies: [],\n frame: 0,\n keys: {}\n };\n scoreRef.current = 0;\n lastBatchScoreRef.current = 0;\n setScore(0);\n setGameOver(false);\n };\n\n\n \n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n const state = gameStateRef.current;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n state.keys[e.key] = true;\n };\n const handleKeyUp = (e: KeyboardEvent) => {\n state.keys[e.key] = false;\n };\n\n window.addEventListener('keydown', handleKeyDown);\n window.addEventListener('keyup', handleKeyUp);\n\n const randomRadius = () => 10 + Math.random() * 15;\n\n const getEnemySpeed = () => {\n const base = 3;\n const increase = Math.floor(scoreRef.current / 20) * 0.5;\n return base + increase;\n };\n\n let animationId: number;\n\n const gameLoop = () => {\n if (gameOver) return;\n\n state.frame++;\n\n ctx.fillStyle = '#000';\n ctx.fillRect(0, 0, config.canvasSize.width, config.canvasSize.height);\n\n // Player movement\n if (state.keys['ArrowLeft'] && state.player.x > 0) state.player.x -= 5;\n if (state.keys['ArrowRight'] && state.player.x < config.canvasSize.width - state.player.width) state.player.x += 5;\n if (state.keys['ArrowUp'] && state.player.y > 0) state.player.y -= 5;\n if (state.keys['ArrowDown'] && state.player.y < config.canvasSize.height - state.player.height) state.player.y += 5;\n\n // Draw player\n ctx.fillStyle = '#0ea5e9';\n ctx.fillRect(\n state.player.x,\n state.player.y,\n state.player.width,\n state.player.height\n );\n\n // Normal enemy spawn\n if (state.frame % 40 === 0) {\n const radius = randomRadius();\n state.enemies.push({\n x: radius + Math.random() * (config.canvasSize.width - radius * 2),\n y: -radius,\n radius,\n });\n }\n\n // Extra batch every 20 score\n if (\n scoreRef.current > 0 &&\n scoreRef.current % 20 === 0 &&\n lastBatchScoreRef.current !== scoreRef.current\n ) {\n lastBatchScoreRef.current = scoreRef.current;\n const batchCount = 2 + Math.floor(Math.random() * 3);\n\n for (let i = 0; i < batchCount; i++) {\n const radius = randomRadius();\n state.enemies.push({\n x: radius + Math.random() * (config.canvasSize.width - radius * 2),\n y: -Math.random() * 100,\n radius\n });\n }\n }\n\n // Enemies update\n state.enemies = state.enemies.filter(enemy => {\n enemy.y += getEnemySpeed();\n\n // Draw enemy (circle)\n ctx.fillStyle = '#ef4444';\n ctx.beginPath();\n ctx.arc(enemy.x, enemy.y, enemy.radius, 0, Math.PI * 2);\n ctx.fill();\n\n // Circle vs rectangle collision\n const closestX = Math.max(\n state.player.x,\n Math.min(enemy.x, state.player.x + state.player.width)\n );\n const closestY = Math.max(\n state.player.y,\n Math.min(enemy.y, state.player.y + state.player.height)\n );\n\n const dx = enemy.x - closestX;\n const dy = enemy.y - closestY;\n\n if (dx * dx + dy * dy < enemy.radius * enemy.radius) {\n setGameOver(true);\n return false;\n }\n\n // Passed screen\n if (enemy.y - enemy.radius > config.canvasSize.height) {\n setScore(s => {\n scoreRef.current = s + 1;\n return s + 1;\n });\n return false;\n }\n\n return true;\n });\n\n animationId = requestAnimationFrame(gameLoop);\n };\n\n gameLoop();\n\n return () => {\n cancelAnimationFrame(animationId);\n window.removeEventListener('keydown', handleKeyDown);\n window.removeEventListener('keyup', handleKeyUp);\n };\n }, [gameOver]);\n\n return (\n <div className=\"relative flex flex-col items-center gap-4 p-4\">\n <div className=\"text-xl font-bold\">Score: {score}</div>\n <canvas\n ref={canvasRef}\n width={config.canvasSize.width}\n height={config.canvasSize.height}\n className=\"border-2 border-gray-300\"\n />\n\n {gameOver && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center bg-black/60\">\n <p className=\"text-xl font-bold text-red-500 mb-3\">Game Over</p>\n <Button onClick={resetGame}>Play Again</Button>\n </div>\n )}\n\n <div className=\"text-sm text-foreground\">Use arrow keys to move</div>\n </div>\n );\n};\n\nexport default SpaceDodger;","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}","import React, { useEffect, useRef, useState } from 'react';\nimport { Button } from '@/components/ui/button';\n\ninterface NumberItem {\n x: number;\n y: number;\n value: number;\n radius: number;\n}\n\ntype GamePhase = 'memorize' | 'recall' | 'transition';\n\ninterface GameState {\n numbers: NumberItem[];\n sequence: number[];\n currentIndex: number;\n level: number;\n showNumbers: boolean;\n phase: GamePhase;\n revealed: Set<number>;\n}\n\nconst config = {\n canvasSize: { width: 450, height: 450 },\n baseHideTime: 3000,\n numberRadius: 30,\n};\n\nconst MemoryGame: React.FC = () => {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const [level, setLevel] = useState(1);\n const [gameOver, setGameOver] = useState(false);\n const [message, setMessage] = useState('');\n const [showOverlay, setShowOverlay] = useState<{ visible: boolean; text: string }>({\n visible: false,\n text: '',\n });\n const gameStateRef = useRef<GameState>({\n numbers: [],\n sequence: [],\n currentIndex: 0,\n level: 1,\n showNumbers: true,\n phase: 'memorize',\n revealed: new Set(),\n });\n\n // Max numbers = 9\n const getNumberCount = (lvl: number) => Math.min(4 + lvl, 9);\n\n // Hide time decreases as level increases, min 500ms\n const getHideTime = (lvl: number) =>\n Math.max(500, config.baseHideTime - Math.floor((lvl - 1) / 1) * 500);\n\n const generateNumbers = (lvl: number) => {\n const count = getNumberCount(lvl);\n const numbers: NumberItem[] = [];\n const sequence: number[] = [];\n const padding = config.numberRadius * 2.5;\n\n for (let i = 0; i < count; i++) {\n let x: number, y: number, overlap: boolean;\n let attempts = 0;\n\n do {\n overlap = false;\n x = padding + Math.random() * (config.canvasSize.width - padding * 2);\n y = padding + Math.random() * (config.canvasSize.height - padding * 2);\n\n for (const num of numbers) {\n const dx = x - num.x;\n const dy = y - num.y;\n if (Math.sqrt(dx * dx + dy * dy) < config.numberRadius * 2.5) {\n overlap = true;\n break;\n }\n }\n attempts++;\n } while (overlap && attempts < 100);\n\n numbers.push({ x, y, value: i + 1, radius: config.numberRadius });\n sequence.push(i + 1);\n }\n\n return { numbers, sequence };\n };\n\n const startLevel = (lvl: number) => {\n const { numbers, sequence } = generateNumbers(lvl);\n gameStateRef.current = {\n numbers,\n sequence,\n currentIndex: 0,\n level: lvl,\n showNumbers: true,\n phase: 'memorize',\n revealed: new Set(),\n };\n setMessage('Memorize the sequence!');\n\n setTimeout(() => {\n gameStateRef.current.showNumbers = false;\n gameStateRef.current.phase = 'recall';\n setMessage('Click the numbers in order!');\n }, getHideTime(lvl));\n };\n\n const resetGame = () => {\n setLevel(1);\n setGameOver(false);\n setShowOverlay({ visible: false, text: '' });\n startLevel(1);\n };\n\n const handleCanvasClick = (e: React.MouseEvent<HTMLCanvasElement>) => {\n if (gameOver || gameStateRef.current.phase !== 'recall') return;\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const rect = canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n const state = gameStateRef.current;\n\n for (const num of state.numbers) {\n const distance = Math.hypot(x - num.x, y - num.y);\n if (distance <= num.radius) {\n const expected = state.sequence[state.currentIndex];\n if (num.value === expected) {\n state.revealed.add(num.value);\n state.currentIndex++;\n\n if (state.currentIndex === state.sequence.length) {\n const nextLevel = level + 1;\n setLevel(nextLevel);\n state.phase = 'transition';\n setShowOverlay({ visible: true, text: `Get Ready! Level ${nextLevel}` });\n\n setTimeout(() => {\n setShowOverlay({ visible: false, text: '' });\n startLevel(nextLevel);\n }, 1500);\n }\n } else {\n setGameOver(true);\n setMessage(`Wrong! Clicked ${num.value}, expected ${expected}`);\n }\n break;\n }\n }\n };\n\n useEffect(() => startLevel(1), []);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n let animationId: number;\n\n const draw = () => {\n const state = gameStateRef.current;\n ctx.fillStyle = '#000';\n ctx.fillRect(0, 0, config.canvasSize.width, config.canvasSize.height);\n\n state.numbers.forEach((num, idx) => {\n // Show green hint only in level 1\n const isNext = state.phase === 'recall' && level === 1 && idx === state.currentIndex;\n ctx.fillStyle = isNext ? '#22c55e' : '#3b82f6';\n ctx.beginPath();\n ctx.arc(num.x, num.y, num.radius, 0, Math.PI * 2);\n ctx.fill();\n\n // Reveal numbers if memorizing, transitioning, or already correctly guessed\n if (state.showNumbers || state.phase === 'transition' || state.revealed.has(num.value)) {\n ctx.fillStyle = '#fff';\n ctx.font = 'bold 24px sans-serif';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(num.value.toString(), num.x, num.y);\n }\n });\n\n if (!gameOver) animationId = requestAnimationFrame(draw);\n };\n\n draw();\n return () => cancelAnimationFrame(animationId);\n }, [gameOver, level]);\n\n return (\n <div className=\"relative flex flex-col items-center gap-4 p-4\">\n <div className=\"flex gap-8 text-xl font-bold\">\n <div>Level: {level}</div>\n <div>Numbers: {getNumberCount(level)}</div>\n </div>\n <div className=\"text-lg font-semibold text-blue-400 h-6\">{message}</div>\n <canvas\n ref={canvasRef}\n width={config.canvasSize.width}\n height={config.canvasSize.height}\n className=\"border-2 border-gray-300 cursor-pointer\"\n onClick={handleCanvasClick}\n />\n {gameOver && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center bg-black/60\">\n <p className=\"text-xl font-bold text-red-500 mb-2\">Game Over</p>\n <p className=\"text-lg text-white mb-4\">Reached Level {level}</p>\n <Button onClick={resetGame}>Play Again</Button>\n </div>\n )}\n\n {showOverlay.visible && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center bg-black/60\">\n <p className=\"text-2xl font-bold text-yellow-400\">{showOverlay.text}</p>\n </div>\n )}\n\n <div className=\"text-sm text-center text-foreground max-w-md\">\n <div>Memorize the numbers, then click them in sequence (1, 2, 3...)</div>\n <div className=\"mt-1 text-xs text-gray-400\">Green circle = next number to click (level 1 only)</div>\n </div>\n </div>\n );\n};\n\nexport default MemoryGame;\n","import React, { useEffect, useRef, useState } from 'react';\nimport { Button } from '@/components/ui/button';\n\ntype GamePhase = 'playing' | 'paused' | 'gameover';\ntype Direction = 'UP' | 'DOWN' | 'LEFT' | 'RIGHT';\n\ninterface Position {\n x: number;\n y: number;\n}\n\ninterface GameState {\n snake: Position[];\n food: Position;\n bonusFood: Position[];\n direction: Direction;\n nextDirection: Direction;\n score: number;\n speed: number;\n phase: GamePhase;\n}\n\nconst config = {\n gridSize: 20,\n cellSize: 20,\n initialSpeed: 150,\n speedIncrement: 5,\n};\n\nconst SnakeGame: React.FC = () => {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const [message, setMessage] = useState('Use arrow keys or WASD to play!');\n const [showOverlay, setShowOverlay] = useState<{ visible: boolean; text: string }>({\n visible: false,\n text: '',\n });\n\n const gameStateRef = useRef<GameState>({\n snake: [{ x: 10, y: 10 }],\n food: { x: 15, y: 15 },\n bonusFood: [],\n direction: 'RIGHT',\n nextDirection: 'RIGHT',\n score: 0,\n speed: config.initialSpeed,\n phase: 'playing',\n });\n\n const generateFood = (snake: Position[]): Position => {\n let food: Position;\n do {\n food = {\n x: Math.floor(Math.random() * config.gridSize),\n y: Math.floor(Math.random() * config.gridSize),\n };\n } while (snake.some((seg) => seg.x === food.x && seg.y === food.y));\n return food;\n };\n\n const generateBonusFood = (snake: Position[], regularFood: Position, count: number = 3): Position[] => {\n const bonusFood: Position[] = [];\n for (let i = 0; i < count; i++) {\n let food: Position;\n do {\n food = {\n x: Math.floor(Math.random() * config.gridSize),\n y: Math.floor(Math.random() * config.gridSize),\n };\n } while (\n snake.some((seg) => seg.x === food.x && seg.y === food.y) ||\n (food.x === regularFood.x && food.y === regularFood.y) ||\n bonusFood.some((bf) => bf.x === food.x && bf.y === food.y)\n );\n bonusFood.push(food);\n }\n return bonusFood;\n };\n\n const initGame = () => {\n const initialSnake = [{ x: 10, y: 10 }];\n gameStateRef.current = {\n snake: initialSnake,\n food: generateFood(initialSnake),\n bonusFood: [],\n direction: 'RIGHT',\n nextDirection: 'RIGHT',\n score: 0,\n speed: config.initialSpeed,\n phase: 'playing',\n };\n setMessage('Use arrow keys or WASD to play!');\n };\n\n const checkCollision = (head: Position, snake: Position[]): boolean => {\n // Only self collision (no wall collision - wrap around instead)\n return snake.some((seg) => seg.x === head.x && seg.y === head.y);\n };\n\n const moveSnake = () => {\n const state = gameStateRef.current;\n if (state.phase !== 'playing') return;\n\n state.direction = state.nextDirection;\n\n const head = { ...state.snake[0] };\n\n switch (state.direction) {\n case 'UP':\n head.y -= 1;\n break;\n case 'DOWN':\n head.y += 1;\n break;\n case 'LEFT':\n head.x -= 1;\n break;\n case 'RIGHT':\n head.x += 1;\n break;\n }\n\n // Wrap around edges\n if (head.x < 0) head.x = config.gridSize - 1;\n if (head.x >= config.gridSize) head.x = 0;\n if (head.y < 0) head.y = config.gridSize - 1;\n if (head.y >= config.gridSize) head.y = 0;\n\n if (checkCollision(head, state.snake)) {\n state.phase = 'gameover';\n setShowOverlay({ visible: true, text: 'Game Over! 💀' });\n return;\n }\n\n const newSnake = [head, ...state.snake];\n let ateFood = false;\n\n // Check if regular food eaten\n if (head.x === state.food.x && head.y === state.food.y) {\n state.score += 10;\n state.speed = Math.max(50, state.speed - config.speedIncrement);\n state.food = generateFood(newSnake);\n ateFood = true;\n setMessage(`Score: ${state.score} 🍎`);\n\n // Generate bonus food every 50 points\n if (state.score % 50 === 0 && state.score > 0) {\n state.bonusFood = generateBonusFood(newSnake, state.food);\n setMessage(`Score: ${state.score} 🍎 BONUS FOOD! ⭐`);\n }\n }\n\n // Check if bonus food eaten\n const bonusFoodIndex = state.bonusFood.findIndex(\n (bf) => bf.x === head.x && bf.y === head.y\n );\n if (bonusFoodIndex !== -1) {\n state.score += 10;\n state.bonusFood.splice(bonusFoodIndex, 1);\n ateFood = true;\n setMessage(`Score: ${state.score} ⭐ Bonus!`);\n }\n\n if (!ateFood) {\n newSnake.pop();\n }\n\n state.snake = newSnake;\n };\n\n const handleDirectionChange = (newDirection: Direction) => {\n const state = gameStateRef.current;\n const opposites: Record<Direction, Direction> = {\n UP: 'DOWN',\n DOWN: 'UP',\n LEFT: 'RIGHT',\n RIGHT: 'LEFT',\n };\n\n if (opposites[state.direction] !== newDirection) {\n state.nextDirection = newDirection;\n }\n };\n\n const togglePause = () => {\n const state = gameStateRef.current;\n if (state.phase === 'playing') {\n state.phase = 'paused';\n setMessage('Game Paused');\n } else if (state.phase === 'paused') {\n state.phase = 'playing';\n setMessage('Use arrow keys or WASD to play!');\n }\n };\n\n const resetGame = () => {\n setShowOverlay({ visible: false, text: '' });\n initGame();\n };\n\n useEffect(() => {\n initGame();\n\n const onKeyDown = (e: KeyboardEvent) => {\n const key = e.key.toLowerCase();\n \n if (key === ' ') {\n e.preventDefault();\n togglePause();\n return;\n }\n\n if (gameStateRef.current.phase !== 'playing') return;\n\n switch (key) {\n case 'arrowup':\n case 'w':\n e.preventDefault();\n handleDirectionChange('UP');\n break;\n case 'arrowdown':\n case 's':\n e.preventDefault();\n handleDirectionChange('DOWN');\n break;\n case 'arrowleft':\n case 'a':\n e.preventDefault();\n handleDirectionChange('LEFT');\n break;\n case 'arrowright':\n case 'd':\n e.preventDefault();\n handleDirectionChange('RIGHT');\n break;\n }\n };\n\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, []);\n\n // Game loop\n useEffect(() => {\n const interval = setInterval(() => {\n moveSnake();\n }, gameStateRef.current.speed);\n\n return () => clearInterval(interval);\n }, []);\n\n // Drawing\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n let animationId: number;\n\n const draw = () => {\n const state = gameStateRef.current;\n const width = config.gridSize * config.cellSize;\n const height = config.gridSize * config.cellSize;\n\n // Background\n ctx.fillStyle = '#1a1a2e';\n ctx.fillRect(0, 0, width, height);\n\n // Grid\n ctx.strokeStyle = '#16213e';\n ctx.lineWidth = 1;\n for (let i = 0; i <= config.gridSize; i++) {\n ctx.beginPath();\n ctx.moveTo(i * config.cellSize, 0);\n ctx.lineTo(i * config.cellSize, height);\n ctx.stroke();\n ctx.beginPath();\n ctx.moveTo(0, i * config.cellSize);\n ctx.lineTo(width, i * config.cellSize);\n ctx.stroke();\n }\n\n // Food\n ctx.fillStyle = '#ef4444';\n ctx.beginPath();\n ctx.arc(\n state.food.x * config.cellSize + config.cellSize / 2,\n state.food.y * config.cellSize + config.cellSize / 2,\n config.cellSize / 2 - 2,\n 0,\n Math.PI * 2\n );\n ctx.fill();\n\n // Bonus Food (star-shaped)\n state.bonusFood.forEach((bf) => {\n ctx.fillStyle = '#fbbf24';\n ctx.strokeStyle = '#f59e0b';\n ctx.lineWidth = 2;\n \n const centerX = bf.x * config.cellSize + config.cellSize / 2;\n const centerY = bf.y * config.cellSize + config.cellSize / 2;\n const outerRadius = config.cellSize / 2 - 2;\n const innerRadius = outerRadius / 2;\n const points = 5;\n \n ctx.beginPath();\n for (let i = 0; i < points * 2; i++) {\n const radius = i % 2 === 0 ? outerRadius : innerRadius;\n const angle = (Math.PI * i) / points - Math.PI / 2;\n const x = centerX + Math.cos(angle) * radius;\n const y = centerY + Math.sin(angle) * radius;\n if (i === 0) {\n ctx.moveTo(x, y);\n } else {\n ctx.lineTo(x, y);\n }\n }\n ctx.closePath();\n ctx.fill();\n ctx.stroke();\n });\n\n // Snake\n state.snake.forEach((seg, idx) => {\n if (idx === 0) {\n // Head\n ctx.fillStyle = '#22c55e';\n } else {\n // Body\n ctx.fillStyle = '#16a34a';\n }\n ctx.fillRect(\n seg.x * config.cellSize + 1,\n seg.y * config.cellSize + 1,\n config.cellSize - 2,\n config.cellSize - 2\n );\n });\n\n animationId = requestAnimationFrame(draw);\n };\n\n draw();\n return () => cancelAnimationFrame(animationId);\n }, []);\n\n const state = gameStateRef.current;\n const canvasSize = config.gridSize * config.cellSize;\n\n return (\n <div className=\"relative flex flex-col items-center gap-4 p-4 max-w-xl mx-auto\">\n <div className=\"text-3xl font-bold text-green-500\">🐍 Snake Game</div>\n\n <div className=\"flex gap-8 text-lg\">\n <div className=\"text-yellow-400\">\n Score: <span className=\"font-bold\">{state.score}</span>\n </div>\n <div className=\"text-blue-400\">\n Length: <span className=\"font-bold\">{state.snake.length}</span>\n </div>\n </div>\n\n <canvas\n ref={canvasRef}\n width={canvasSize}\n height={canvasSize}\n className=\"border-4 border-green-600 rounded-lg shadow-xl\"\n />\n\n <div className=\"flex gap-2\">\n <Button onClick={togglePause} variant=\"outline\" disabled={state.phase === 'gameover'}>\n {state.phase === 'paused' ? 'Resume' : 'Pause'}\n </Button>\n <Button onClick={resetGame} variant=\"outline\">\n Restart\n </Button>\n </div>\n\n <div className=\"text-sm text-center text-blue-400 h-5\">{message}</div>\n\n {/* Touch controls for mobile */}\n <div className=\"grid grid-cols-3 gap-2 w-48\">\n <div></div>\n <Button\n size=\"lg\"\n variant=\"outline\"\n onClick={() => handleDirectionChange('UP')}\n disabled={state.phase !== 'playing'}\n className=\"text-2xl\"\n >\n ↑\n </Button>\n <div></div>\n <Button\n size=\"lg\"\n variant=\"outline\"\n onClick={() => handleDirectionChange('LEFT')}\n disabled={state.phase !== 'playing'}\n className=\"text-2xl\"\n >\n ←\n </Button>\n <Button\n size=\"lg\"\n variant=\"outline\"\n onClick={() => handleDirectionChange('DOWN')}\n disabled={state.phase !== 'playing'}\n className=\"text-2xl\"\n >\n ↓\n </Button>\n <Button\n size=\"lg\"\n variant=\"outline\"\n onClick={() => handleDirectionChange('RIGHT')}\n disabled={state.phase !== 'playing'}\n className=\"text-2xl\"\n >\n →\n </Button>\n </div>\n\n {showOverlay.visible && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center bg-black/80 rounded-lg\">\n <p className=\"text-4xl font-bold mb-4 text-red-500\">{showOverlay.text}</p>\n <p className=\"mb-2 text-xl text-gray-300\">\n Final Score: <strong className=\"text-yellow-400\">{state.score}</strong>\n </p>\n <p className=\"mb-6 text-lg text-gray-300\">\n Length: <strong className=\"text-green-400\">{state.snake.length}</strong>\n </p>\n <Button onClick={resetGame} size=\"lg\" className=\"bg-green-600 hover:bg-green-700\">\n Play Again\n </Button>\n </div>\n )}\n\n <div className=\"text-xs text-center text-gray-400 max-w-md\">\n Arrow keys or WASD to move • Space to pause • Red apple = +10 pts • Golden star = +10 pts (every 50 pts)\n </div>\n </div>\n );\n};\n\nexport default SnakeGame;"],"mappings":"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","names":["jsx","useEffect","useRef","useState","jsx","jsxs","config","useRef","useState","useEffect","useEffect","useRef","useState","jsx","jsxs","config","useRef","useState","state","useEffect"]}
|