| <!DOCTYPE html>
|
| <html lang="en">
|
| <head>
|
| <meta charset="UTF-8">
|
| <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| <title>Snake Game</title>
|
| <script src="https://cdn.jsdelivr.net/npm/@mediapipe/hands/hands.js"></script>
|
| <script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js"></script>
|
| <script src="https://cdn.jsdelivr.net/npm/@mediapipe/drawing_utils/drawing_utils.js"></script>
|
| <style>
|
| * {
|
| margin: 0;
|
| padding: 0;
|
| box-sizing: border-box;
|
| }
|
| body {
|
| font-family: Arial, sans-serif;
|
| background-color: black;
|
| color: white;
|
| display: flex;
|
| flex-direction: column;
|
| align-items: center;
|
| justify-content: center;
|
| height: 100vh;
|
| overflow: hidden;
|
| }
|
| .game-container {
|
| position: relative;
|
| width: 90%;
|
| max-width: 600px;
|
| aspect-ratio: 3 / 2;
|
| background-color: #111;
|
| border: 2px solid #00ff00;
|
| display: flex;
|
| justify-content: center;
|
| align-items: center;
|
| }
|
| canvas {
|
| position: absolute;
|
| top: 0;
|
| left: 0;
|
| width: 100%;
|
| height: 100%;
|
| }
|
| #pointer {
|
| position: absolute;
|
| width: 15px;
|
| height: 15px;
|
| background-color: rgba(255, 0, 0, 0.8);
|
| border-radius: 50%;
|
| pointer-events: none;
|
| transform: translate(-50%, -50%);
|
| }
|
| .timer {
|
| position: fixed;
|
| top: 10px;
|
| left: 10px;
|
| font-size: 18px;
|
| color: white;
|
| z-index: 10;
|
| }
|
| .score {
|
| position: fixed;
|
| top: 10px;
|
| right: 10px;
|
| font-size: 18px;
|
| color: white;
|
| z-index: 10;
|
| }
|
| .popup {
|
| position: fixed;
|
| top: 50%;
|
| left: 50%;
|
| transform: translate(-50%, -50%);
|
| background-color: #222;
|
| color: white;
|
| padding: 20px;
|
| border: 2px solid #00ff00;
|
| border-radius: 10px;
|
| z-index: 10;
|
| text-align: center;
|
| }
|
| .popup button {
|
| margin-top: 10px;
|
| padding: 10px 20px;
|
| background-color: #00ff00;
|
| border: none;
|
| border-radius: 5px;
|
| cursor: pointer;
|
| color: black;
|
| font-size: 16px;
|
| }
|
| .popup button:hover {
|
| background-color: #00cc00;
|
| }
|
| </style>
|
| </head>
|
| <body>
|
| <div class="timer" id="timer">Time: 0:00</div>
|
| <div class="score" id="score">Score: 0</div>
|
| <div class="game-container">
|
| <canvas id="gameCanvas"></canvas>
|
| <div id="pointer"></div>
|
| </div>
|
|
|
| <script>
|
| const canvas = document.getElementById('gameCanvas');
|
| const ctx = canvas.getContext('2d');
|
| const pointer = document.getElementById('pointer');
|
| const timerDisplay = document.getElementById('timer');
|
| const scoreDisplay = document.getElementById('score');
|
|
|
| canvas.width = canvas.parentElement.clientWidth;
|
| canvas.height = canvas.parentElement.clientHeight;
|
|
|
| let snake = [{ x: 150, y: 150 }];
|
| const snakeSize = 20;
|
| let food = { x: Math.random() * (canvas.width - snakeSize), y: Math.random() * (canvas.height - snakeSize) };
|
| let score = 0;
|
| let timeLeft = 60;
|
| let gameInterval, timerInterval;
|
|
|
|
|
| const hands = new Hands({
|
| locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`,
|
| });
|
|
|
| hands.setOptions({
|
| maxNumHands: 1,
|
| modelComplexity: 1,
|
| minDetectionConfidence: 0.8,
|
| minTrackingConfidence: 0.8,
|
| });
|
|
|
| const videoElement = document.createElement('video');
|
| const camera = new Camera(videoElement, {
|
| onFrame: async () => {
|
| await hands.send({ image: videoElement });
|
| },
|
| width: 1280,
|
| height: 720,
|
| });
|
| camera.start();
|
|
|
| hands.onResults((results) => {
|
| if (results.multiHandLandmarks && results.multiHandLandmarks.length > 0) {
|
| const landmarks = results.multiHandLandmarks[0];
|
| const pointerX = landmarks[8].x * canvas.width;
|
| const pointerY = landmarks[8].y * canvas.height;
|
|
|
| pointer.style.left = `${pointerX}px`;
|
| pointer.style.top = `${pointerY}px`;
|
| }
|
| });
|
|
|
| function drawSnake() {
|
| ctx.fillStyle = 'green';
|
| snake.forEach((segment) => {
|
| ctx.fillRect(segment.x, segment.y, snakeSize, snakeSize);
|
| });
|
| }
|
|
|
| function drawFood() {
|
| ctx.fillStyle = 'red';
|
| ctx.fillRect(food.x, food.y, snakeSize, snakeSize);
|
| }
|
|
|
| function moveSnake() {
|
| const head = { x: snake[0].x, y: snake[0].y };
|
| head.x += (pointer.offsetLeft - head.x) * 0.1;
|
| head.y += (pointer.offsetTop - head.y) * 0.1;
|
|
|
| snake.unshift(head);
|
| if (
|
| Math.abs(head.x - food.x) < snakeSize &&
|
| Math.abs(head.y - food.y) < snakeSize
|
| ) {
|
| score += 10;
|
| food = { x: Math.random() * (canvas.width - snakeSize), y: Math.random() * (canvas.height - snakeSize) };
|
| } else {
|
| snake.pop();
|
| }
|
|
|
| if (
|
| head.x < 0 ||
|
| head.x > canvas.width ||
|
| head.y < 0 ||
|
| head.y > canvas.height ||
|
| snake.some((segment, index) => index !== 0 && head.x === segment.x && head.y === segment.y)
|
| ) {
|
| endGame();
|
| }
|
| }
|
|
|
| function updateTimer() {
|
| if (timeLeft <= 0) {
|
| endGame();
|
| } else {
|
| timeLeft--;
|
| const minutes = Math.floor(timeLeft / 60);
|
| const seconds = timeLeft % 60;
|
| timerDisplay.textContent = `Time: ${minutes}:${seconds.toString().padStart(2, '0')}`;
|
| }
|
| }
|
|
|
| function endGame() {
|
| clearInterval(gameInterval);
|
| clearInterval(timerInterval);
|
| const popup = document.createElement('div');
|
| popup.classList.add('popup');
|
| popup.innerHTML = `<h2>Game Over</h2><p>Your Score: ${score}</p><button onclick="restartGame()">Restart</button>`;
|
| document.body.appendChild(popup);
|
| }
|
|
|
| function restartGame() {
|
| document.location.reload();
|
| }
|
|
|
| function gameLoop() {
|
| ctx.clearRect(0, 0, canvas.width, canvas.height);
|
| drawSnake();
|
| drawFood();
|
| moveSnake();
|
| scoreDisplay.textContent = `Score: ${score}`;
|
| }
|
|
|
| gameInterval = setInterval(gameLoop, 100);
|
| timerInterval = setInterval(updateTimer, 1000);
|
| </script>
|
| </body>
|
| </html> |