<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neon Snake</title>
<style>
body {
background-color: #050505;
color: #99d160;
font-family: 'Courier New', Courier, monospace;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
overflow: hidden;
}
h1 { margin: 0 0 10px 0; text-transform: uppercase; letter-spacing: 2px; }
#scoreBoard { font-size: 1.2rem; margin-bottom: 20px; font-weight: bold; }
canvas {
background-color: #111;
border: 2px solid #333;
border-radius: 8px;
box-shadow: 0 0 20px rgba(153, 209, 96, 0.2);
}
.controls { margin-top: 20px; color: #666; font-size: 0.9rem; text-align: center; line-height: 1.5; }
</style>
</head>
<body>
<h1>Neon Snake</h1>
<div id="scoreBoard">Score: 0</div>
<canvas id="gameCanvas" width="400" height="400"></canvas>
<div class="controls">Use <b>Arrow Keys</b> to Move<br>Press <b>SPACE</b> to Restart</div>
<script>
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
const scoreBoard = document.getElementById("scoreBoard");
const gridSize = 20;
const tileCount = canvas.width / gridSize;
let snake = [{x: 10, y: 10}];
let dx = 0;
let dy = -1;
let food = {x: 15, y: 15};
let score = 0;
let gameLoop;
let isGameOver = false;
function resetGame() {
snake = [{x: 10, y: 10}];
dx = 0;
dy = -1;
score = 0;
isGameOver = false;
scoreBoard.innerText = "Score: " + score;
placeFood();
clearTimeout(gameLoop);
main();
}
function main() {
if (hasGameEnded()) {
isGameOver = true;
ctx.fillStyle = "rgba(0,0,0,0.8)";
ctx.fillRect(0,0, canvas.width, canvas.height);
ctx.fillStyle = "#e74c3c";
ctx.font = "bold 30px Courier New";
ctx.textAlign = "center";
ctx.fillText("GAME OVER", canvas.width/2, canvas.height/2);
ctx.fillStyle = "#fff";
ctx.font = "15px Courier New";
ctx.fillText("Press SPACE to Restart", canvas.width/2, canvas.height/2 + 30);
return;
}
gameLoop = setTimeout(function onTick() {
clearCanvas();
drawFood();
advanceSnake();
drawSnake();
main();
}, 100);
}
function clearCanvas() {
ctx.fillStyle = '#111';
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
function drawSnake() {
snake.forEach((part, index) => {
// Head is white, body is neon green
ctx.fillStyle = index === 0 ? "#ffffff" : "#99d160";
ctx.strokeStyle = "#050505";
ctx.fillRect(part.x * gridSize, part.y * gridSize, gridSize, gridSize);
ctx.strokeRect(part.x * gridSize, part.y * gridSize, gridSize, gridSize);
});
}
function advanceSnake() {
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;
scoreBoard.innerText = "Score: " + score;
placeFood();
} else {
snake.pop();
}
}
function drawFood() {
ctx.fillStyle = "#e74c3c";
ctx.beginPath();
ctx.arc(food.x * gridSize + gridSize/2, food.y * gridSize + gridSize/2, gridSize/2 - 2, 0, 2 * Math.PI);
ctx.fill();
}
function placeFood() {
food.x = Math.floor(Math.random() * tileCount);
food.y = Math.floor(Math.random() * tileCount);
// Make sure food doesn't spawn inside the snake
snake.forEach(function isFoodOnSnake(part) {
if (part.x == food.x && part.y == food.y) placeFood();
});
}
function hasGameEnded() {
for (let i = 4; i < snake.length; i++) {
if (snake[i].x === snake[0].x && snake[i].y === snake[0].y) return true;
}
const hitLeftWall = snake[0].x < 0;
const hitRightWall = snake[0].x >= tileCount;
const hitTopWall = snake[0].y < 0;
const hitBottomWall = snake[0].y >= tileCount;
return hitLeftWall || hitRightWall || hitTopWall || hitBottomWall;
}
document.addEventListener("keydown", function(e) {
// Restart game on spacebar if dead
if (e.code === "Space" && isGameOver) {
resetGame();
return;
}
// Prevent default scrolling for arrow keys inside the iframe
if(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Space"].indexOf(e.code) > -1) {
e.preventDefault();
}
const goingUp = dy === -1;
const goingDown = dy === 1;
const goingRight = dx === 1;
const goingLeft = dx === -1;
if (e.code === "ArrowLeft" && !goingRight) { dx = -1; dy = 0; }
if (e.code === "ArrowUp" && !goingDown) { dx = 0; dy = -1; }
if (e.code === "ArrowRight" && !goingLeft) { dx = 1; dy = 0; }
if (e.code === "ArrowDown" && !goingUp) { dx = 0; dy = 1; }
});
placeFood();
main();
</script>
</body>
</html>