// get elements from page const info = document.getElementById("info"); const highscore = document.getElementById("highscore"); const canvas = document.getElementById("canvas"); const ctx = canvas.getContext("2d"); const game = { size: 15, speed: 1000 / 15, // 15 frames per second snek: { body: [ [3, 7], [4, 7], [5, 7], [6, 7], [7, 7], ], dir: null, newdir: null, }, apple: [12, 7], highscore: 0, }; // reset the game board (but not the highscore) function reset() { game.apple = [12, 7]; game.snek.body = [ [3, 7], [4, 7], [5, 7], [6, 7], [7, 7], ]; game.snek.dir = null; game.snek.newdir = null; } // check if the x and y coordinate is part of the snek function inSnek(x, y) { for (let part of game.snek.body) { if (part[0] === x && part[1] === y) return true; } return false; } // draw the game board function draw() { const size = 25; ctx.clearRect(0, 0, 500, 500); for (let i = 0; i < game.size; i++) { for (let j = 0; j < game.size; j++) { ctx.fillStyle = inSnek(i, j) ? "#38e070" : i === game.apple[0] && j === game.apple[1] ? "#eb4034" : "#333333"; ctx.fillRect(i * size, j * size, size, size); } } } // update the game board function update() { game.snek.dir = game.snek.newdir; const b = game.snek.body; const l = b[b.length - 1]; const next = move(); // check if the snek ate the apple if (game.apple[0] === next[0] && game.apple[1] === next[1]) { // the apple shouldnt be on top of the snek // try 30 times to place the apple for (let i = 0; i < 30; i++) { const x = Math.floor(Math.random() * game.size); const y = Math.floor(Math.random() * game.size); game.apple = [x, y]; if (!inSnek(game.apple[0], game.apple[1])) break; } } else { b.shift(); } // check if the snek crashed into itself if (inSnek(next[0], next[1])) { reset(); } // check if the snek fell out of the world if (l[0] < 0 || l[0] >= game.size || l[1] < 0 || l[1] >= game.size) { reset(); } // uncomment to wrap // if (next[0] < 0) next[0] = game.size - 1; // if (next[0] >= game.size) next[0] = 0; // if (next[1] < 0 ) next[1] = game.size - 1; // if (next[1] >= game.size) next[1] = 0; b.push(next); // move the snek // update score display if (game.snek.dir !== null) { const score = b.length - 5; if (score > game.highscore) game.highscore = score; // update high score if necessary info.innerText = `${score < 15 ? "length" : "longth"}: ${score}`; highscore.innerText = `highscore: ${game.highscore}\n`; } // calculate where the snek will move to function move() { const [x, y] = l; switch (game.snek.dir) { case "left": return [x - 1, y]; case "right": return [x + 1, y]; case "up": return [x, y - 1]; case "down": return [x, y + 1]; default: return [x, y]; } } } // change direction on keypress document.addEventListener("keydown", (e) => { if (e.ctrlKey || e.shiftKey) return; const s = game.snek; if (s.dir !== s.newdir) update(); // avoid snek from crashing into itself e.preventDefault(); switch (e.key) { case "ArrowLeft": return s.dir !== "right" ? (s.newdir = "left") : 0; case "ArrowRight": return s.dir !== "left" ? (s.newdir = "right") : 0; case "ArrowUp": return s.dir !== "down" ? (s.newdir = "up") : 0; case "ArrowDown": return s.dir !== "up" ? (s.newdir = "down") : 0; } }); // the main game loop setInterval(() => { update(); draw(); }, game.speed);