Добавить snake.html
This commit is contained in:
+136
@@ -0,0 +1,136 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Змейка</title>
|
||||||
|
<style>
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
body {
|
||||||
|
background: #1a1a2e;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
font-family: 'Segoe UI', sans-serif;
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 2.2em;
|
||||||
|
color: #0f0;
|
||||||
|
text-shadow: 0 0 20px #0f0;
|
||||||
|
}
|
||||||
|
#score { font-size: 1.3em; margin-bottom: 10px; }
|
||||||
|
canvas {
|
||||||
|
border: 2px solid #0f0;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 30px rgba(0, 255, 0, 0.3);
|
||||||
|
}
|
||||||
|
#message {
|
||||||
|
margin-top: 15px;
|
||||||
|
font-size: 1.1em;
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>🐍 Змейка</h1>
|
||||||
|
<div id="score">Счёт: 0</div>
|
||||||
|
<canvas id="game" width="400" height="400"></canvas>
|
||||||
|
<div id="message">Стрелки для управления | Пробел — рестарт</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const canvas = document.getElementById('game');
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
const scoreEl = document.getElementById('score');
|
||||||
|
const size = 20;
|
||||||
|
const cols = canvas.width / size;
|
||||||
|
const rows = canvas.height / size;
|
||||||
|
let snake, food, dir, nextDir, score, gameOver, interval;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
snake = [{ x: 10, y: 10 }];
|
||||||
|
dir = { x: 1, y: 0 };
|
||||||
|
nextDir = { x: 1, y: 0 };
|
||||||
|
score = 0;
|
||||||
|
gameOver = false;
|
||||||
|
scoreEl.textContent = 'Счёт: 0';
|
||||||
|
placeFood();
|
||||||
|
clearInterval(interval);
|
||||||
|
interval = setInterval(update, 120);
|
||||||
|
}
|
||||||
|
|
||||||
|
function placeFood() {
|
||||||
|
while (true) {
|
||||||
|
food = { x: Math.floor(Math.random() * cols), y: Math.floor(Math.random() * rows) };
|
||||||
|
if (!snake.some(s => s.x === food.x && s.y === food.y)) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
if (gameOver) return;
|
||||||
|
dir = { ...nextDir };
|
||||||
|
const head = { x: snake[0].x + dir.x, y: snake[0].y + dir.y };
|
||||||
|
if (head.x < 0 || head.x >= cols || head.y < 0 || head.y >= rows ||
|
||||||
|
snake.some(s => s.x === head.x && s.y === head.y)) {
|
||||||
|
gameOver = true;
|
||||||
|
draw();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
snake.unshift(head);
|
||||||
|
if (head.x === food.x && head.y === food.y) {
|
||||||
|
score += 10;
|
||||||
|
scoreEl.textContent = 'Счёт: ' + score;
|
||||||
|
placeFood();
|
||||||
|
} else {
|
||||||
|
snake.pop();
|
||||||
|
}
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
ctx.fillStyle = '#16213e';
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
snake.forEach((s, i) => {
|
||||||
|
const g = ctx.createRadialGradient(s.x * size + size/2, s.y * size + size/2, 0, 0, 0, size);
|
||||||
|
g.addColorStop(0, i === 0 ? '#0f0' : '#0a0');
|
||||||
|
g.addColorStop(1, i === 0 ? '#0a0' : '#050');
|
||||||
|
ctx.fillStyle = g;
|
||||||
|
ctx.fillRect(s.x * size + 1, s.y * size + 1, size - 2, size - 2);
|
||||||
|
});
|
||||||
|
ctx.fillStyle = '#ff0040';
|
||||||
|
ctx.shadowColor = '#ff0040';
|
||||||
|
ctx.shadowBlur = 15;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(food.x * size + size/2, food.y * size + size/2, size/2 - 2, 0, Math.PI * 2);
|
||||||
|
ctx.fill();
|
||||||
|
ctx.shadowBlur = 0;
|
||||||
|
if (gameOver) {
|
||||||
|
ctx.fillStyle = 'rgba(0,0,0,0.7)';
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
ctx.fillStyle = '#ff0040';
|
||||||
|
ctx.font = 'bold 36px Segoe UI';
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
ctx.fillText('GAME OVER', canvas.width/2, canvas.height/2 - 10);
|
||||||
|
ctx.fillStyle = '#fff';
|
||||||
|
ctx.font = '20px Segoe UI';
|
||||||
|
ctx.fillText('Счёт: ' + score, canvas.width/2, canvas.height/2 + 25);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('keydown', e => {
|
||||||
|
const key = e.key;
|
||||||
|
if (key === 'ArrowUp' && dir.y !== 1) nextDir = { x: 0, y: -1 };
|
||||||
|
if (key === 'ArrowDown' && dir.y !== -1) nextDir = { x: 0, y: 1 };
|
||||||
|
if (key === 'ArrowLeft' && dir.x !== 1) nextDir = { x: -1, y: 0 };
|
||||||
|
if (key === 'ArrowRight' && dir.x !== -1) nextDir = { x: 1, y: 0 };
|
||||||
|
if (key === ' ') init();
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
init();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user