Created
June 23, 2025 19:00
-
-
Save onEnterFrame/bd6601c0fc584429648fada80c62966d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!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