Skip to content

Instantly share code, notes, and snippets.

@abdelfattahradwan
Last active April 30, 2021 23:37
Show Gist options
  • Save abdelfattahradwan/6774dc33a5797ba896a3389e0c0a1444 to your computer and use it in GitHub Desktop.
Save abdelfattahradwan/6774dc33a5797ba896a3389e0c0a1444 to your computer and use it in GitHub Desktop.
A simple Snake game made using HTML and JavaScript.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<style>
#game-canvas {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
</style>
<title>Snake</title>
</head>
<body>
<canvas id="game-canvas" width="512" height="512">
</canvas>
<script>
/** @type {HTMLCanvasElement} */
const CANVAS = document.getElementById("game-canvas");
const CONTEXT = CANVAS.getContext("2d");
const SEGMENT_WIDTH = 32.0;
const SEGMENT_HEIGHT = 32.0;
const COLUMNS = CANVAS.width / SEGMENT_WIDTH;
const ROWS = CANVAS.height / SEGMENT_HEIGHT;
class Segment {
/**
* @param x {number}
* @param y {number}
* @param direction {number}
*/
constructor(x, y, direction) {
this.x = x;
this.y = y;
this.direction = direction;
this.oldDirection = this.direction;
/** @type {Segment} */
this.next = null;
}
setDirection(direction) {
this.oldDirection = this.direction;
this.direction = direction;
}
move() {
if (this.direction === 0) this.y--;
else if (this.direction === 1) this.y++;
else if (this.direction === 2) this.x--;
else if (this.direction === 3) this.x++;
if (this.x < 0) this.x = COLUMNS - 1; else if (this.x > COLUMNS - 1) this.x = 0;
if (this.y < 0) this.y = ROWS - 1; else if (this.y > ROWS - 1) this.y = 0;
this.oldDirection = this.direction;
if (this.next !== null) {
this.next.move();
this.next.setDirection(this.oldDirection);
}
}
}
const ROOT = new Segment(COLUMNS / 2, ROWS / 2, 0);
window.addEventListener("keydown", event => {
if (event.code === "KeyW") {
if (ROOT.direction !== 1) ROOT.direction = 0;
} else if (event.code === "KeyS") {
if (ROOT.direction !== 0) ROOT.direction = 1;
} else if (event.code === "KeyA") {
if (ROOT.direction !== 3) ROOT.direction = 2;
} else if (event.code === "KeyD") {
if (ROOT.direction !== 2) ROOT.direction = 3;
}
});
function addSegment() {
let lastSegment = ROOT;
while (lastSegment.next !== null) lastSegment = lastSegment.next;
let xOffset = lastSegment.direction === 2 ? 1 : lastSegment.direction === 3 ? -1 : 0;
let yOffset = lastSegment.direction === 0 ? 1 : lastSegment.direction === 1 ? -1 : 0;
lastSegment.next = new Segment(lastSegment.x + xOffset, lastSegment.y + yOffset, lastSegment.direction);
}
let foodX = 0;
let foodY = 0;
function randomizeFoodPosition() {
foodX = Math.floor(Math.random() * (COLUMNS - 1));
foodY = Math.floor(Math.random() * (ROWS - 1));
}
randomizeFoodPosition();
let gameOver = false;
let elapsedFrames = 0;
function update() {
if (elapsedFrames > 14) {
ROOT.move();
if (ROOT.x === foodX && ROOT.y === foodY) {
addSegment();
randomizeFoodPosition();
}
let currentSegment = ROOT.next;
while (currentSegment !== null) {
if (ROOT.x === currentSegment.x && ROOT.y === currentSegment.y) {
gameOver = true;
break;
}
currentSegment = currentSegment.next;
}
elapsedFrames = 0;
} else elapsedFrames++;
}
function render() {
CONTEXT.fillStyle = "black";
CONTEXT.fillRect(0.0, 0.0, CANVAS.width, CANVAS.height);
let currentSegment = ROOT;
while (currentSegment !== null) {
CONTEXT.fillStyle = "rgb(155, 55, 55)";
CONTEXT.fillRect(currentSegment.x * SEGMENT_WIDTH, currentSegment.y * SEGMENT_HEIGHT, SEGMENT_WIDTH, SEGMENT_HEIGHT);
currentSegment = currentSegment.next;
}
CONTEXT.fillStyle = "rgb(55, 55, 155)";
CONTEXT.fillRect(foodX * SEGMENT_WIDTH, foodY * SEGMENT_HEIGHT, SEGMENT_WIDTH, SEGMENT_HEIGHT);
}
function tick() {
update();
render();
if (!gameOver) window.requestAnimationFrame(tick);
}
tick();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment