|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>Beautiful Snake Game</title> |
|
<style> |
|
body { |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
min-height: 100vh; |
|
background: linear-gradient(45deg, #1a1a2e, #16213e); |
|
margin: 0; |
|
font-family: Arial, sans-serif; |
|
} |
|
|
|
.game-container { |
|
background: rgba(255, 255, 255, 0.1); |
|
padding: 20px; |
|
border-radius: 15px; |
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3); |
|
} |
|
|
|
canvas { |
|
background: #0f0f23; |
|
border-radius: 10px; |
|
border: 2px solid #4ecca3; |
|
} |
|
|
|
.score { |
|
color: #fff; |
|
text-align: center; |
|
font-size: 24px; |
|
margin-bottom: 10px; |
|
text-shadow: 0 0 5px #4ecca3; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="game-container"> |
|
<div class="score">Score: <span id="score">0</span></div> |
|
<canvas id="gameCanvas" width="400" height="400"></canvas> |
|
</div> |
|
|
|
<script> |
|
const canvas = document.getElementById('gameCanvas'); |
|
const ctx = canvas.getContext('2d'); |
|
const scoreElement = document.getElementById('score'); |
|
|
|
const gridSize = 20; |
|
const tileCount = canvas.width / gridSize; |
|
|
|
let snake = [ |
|
{ x: 10, y: 10 }, |
|
]; |
|
let food = spawnFood(); |
|
let dx = 0; |
|
let dy = 0; |
|
let score = 0; |
|
let gameSpeed = 100; |
|
let gameLoop; |
|
|
|
function drawGame() { |
|
|
|
const head = { x: snake[0].x + dx, y: snake[0].y + dy }; |
|
snake.unshift(head); |
|
|
|
|
|
if (head.x === food.x && head.y === food.y) { |
|
score += 10; |
|
scoreElement.textContent = score; |
|
food = spawnFood(); |
|
if (gameSpeed > 50) gameSpeed -= 2; |
|
} else { |
|
snake.pop(); |
|
} |
|
|
|
|
|
ctx.fillStyle = '#0f0f23'; |
|
ctx.fillRect(0, 0, canvas.width, canvas.height); |
|
|
|
|
|
snake.forEach((segment, index) => { |
|
ctx.fillStyle = `hsl(${index * 5}, 70%, 50%)`; |
|
ctx.beginPath(); |
|
ctx.arc( |
|
segment.x * gridSize + gridSize / 2, |
|
segment.y * gridSize + gridSize / 2, |
|
gridSize / 2 - 1, |
|
0, |
|
Math.PI * 2 |
|
); |
|
ctx.fill(); |
|
}); |
|
|
|
|
|
ctx.fillStyle = '#ff6b6b'; |
|
ctx.beginPath(); |
|
ctx.arc( |
|
food.x * gridSize + gridSize / 2, |
|
food.y * gridSize + gridSize / 2, |
|
gridSize / 2 - 1, |
|
0, |
|
Math.PI * 2 |
|
); |
|
ctx.fill(); |
|
|
|
|
|
if (checkCollision(head)) { |
|
gameOver(); |
|
return; |
|
} |
|
|
|
gameLoop = setTimeout(drawGame, gameSpeed); |
|
} |
|
|
|
function spawnFood() { |
|
return { |
|
x: Math.floor(Math.random() * tileCount), |
|
y: Math.floor(Math.random() * tileCount) |
|
}; |
|
} |
|
|
|
function checkCollision(head) { |
|
if (head.x < 0 || head.x >= tileCount || head.y < 0 || head.y >= tileCount) { |
|
return true; |
|
} |
|
for (let i = 1; i < snake.length; i++) { |
|
if (head.x === snake[i].x && head.y === snake[i].y) { |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
function gameOver() { |
|
clearTimeout(gameLoop); |
|
alert(`Game Over! Score: ${score}`); |
|
snake = [{ x: 10, y: 10 }]; |
|
dx = 0; |
|
dy = 0; |
|
score = 0; |
|
gameSpeed = 100; |
|
scoreElement.textContent = score; |
|
food = spawnFood(); |
|
drawGame(); |
|
} |
|
|
|
document.addEventListener('keydown', (e) => { |
|
switch (e.key) { |
|
case 'ArrowUp': |
|
if (dy === 0) { dx = 0; dy = -1; } |
|
break; |
|
case 'ArrowDown': |
|
if (dy === 0) { dx = 0; dy = 1; } |
|
break; |
|
case 'ArrowLeft': |
|
if (dx === 0) { dx = -1; dy = 0; } |
|
break; |
|
case 'ArrowRight': |
|
if (dx === 0) { dx = 1; dy = 0; } |
|
break; |
|
} |
|
}); |
|
|
|
|
|
drawGame(); |
|
</script> |
|
</body> |
|
</html> |
|
|