Skip to content

Instantly share code, notes, and snippets.

@onEnterFrame
Created June 23, 2025 19:00
Show Gist options
  • Select an option

  • Save onEnterFrame/bd6601c0fc584429648fada80c62966d to your computer and use it in GitHub Desktop.

Select an option

Save onEnterFrame/bd6601c0fc584429648fada80c62966d to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>SNAKE</title>
<style>
body { background: #000; color: #0f0; font-family: monospace; text-align: center; }
canvas { border: 2px solid #0f0; background: #111; }
</style>
</head>
<body>
<h1>SNAKE</h1>
<div>SCORE: <span id="sc">0</span></div>
<canvas id="c"></canvas>
<script>
// --- System Globals (to save space!) ---
const C = document.getElementById('c');
const CTX = C.getContext('2d');
const G = 20; // Grid Size
let S, F, P, D, T, L, HS = 0; // Snake, Food, Score, Direction, TileCount, Loop, HighScore
// --- Initialize Memory & Load Program ---
window.onload = function() {
C.width = C.height = 400; // Fixed size like an old monitor
T = C.width / G;
document.addEventListener('keydown', key);
reset();
};
// --- Reset Program State ---
function reset() {
clearInterval(L); // Stop game loop
S = [{x:10, y:10}]; // Snake starts with one block
F = {}; // Food position
P = 0; // Player score
D = 39; // Start direction right (keycode)
document.getElementById('sc').textContent = P;
spawnFood();
draw(); // Draw initial screen
L = setInterval(gameLoop, 150);
}
// --- Main Game Loop ---
function gameLoop() {
let head = {x: S[0].x, y: S[0].y};
// Move based on keycode
if (D === 37) head.x--; // Left
if (D === 38) head.y--; // Up
if (D === 39) head.x++; // Right
if (D === 40) head.y++; // Down
// Check for collisions (walls or self)
if (head.x < 0 || head.y < 0 || head.x >= T || head.y >= T || checkHit(head)) {
// GAME OVER
clearInterval(L);
CTX.fillStyle = '#f00';
CTX.font = '40px monospace';
CTX.fillText('GAME OVER', C.width / 2 - 120, C.height / 2);
if (P > HS) { HS = P; }
setTimeout(reset, 2000); // Auto-restart
return;
}
S.unshift(head);
// Check for food
if (head.x === F.x && head.y === F.y) {
P++;
document.getElementById('sc').textContent = P;
spawnFood();
} else {
S.pop();
}
draw();
}
// --- Drawing Subroutine ---
function draw() {
// Clear screen
CTX.fillStyle = '#000';
CTX.fillRect(0, 0, C.width, C.height);
// Draw snake
CTX.fillStyle = '#0f0';
for (let i = 0; i < S.length; i++) {
CTX.fillRect(S[i].x * G, S[i].y * G, G - 2, G - 2);
}
// Draw food
CTX.fillStyle = '#f0f'; // Magenta food
CTX.fillRect(F.x * G, F.y * G, G - 2, G - 2);
}
// --- Generate Food ---
function spawnFood() {
F.x = Math.floor(Math.random() * T);
F.y = Math.floor(Math.random() * T);
// If food spawns on snake, try again
if (checkHit(F)) {
spawnFood();
}
}
// --- Collision Check Subroutine ---
function checkHit(pos) {
for (let i = 0; i < S.length; i++) {
if (pos.x === S[i].x && pos.y === S[i].y) return true;
}
return false;
}
// --- Keyboard Input Handler ---
function key(e) {
let newD = e.keyCode;
// Prevent going in the opposite direction
if (Math.abs(D - newD) !== 2) {
// Only accept arrow keys
if (newD >= 37 && newD <= 40) {
D = newD;
}
}
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment