Skip to content

Snake Game

Open the editor and paste this code to play Snake live.

The Code

javascript
if (!state.init) {
  state.cell = 20;
  state.cols = Math.floor(w / state.cell);
  state.rows = Math.floor(h / state.cell);
  state.snake = [
    { x: 8, y: 8 },
    { x: 7, y: 8 },
    { x: 6, y: 8 }
  ];
  state.dir = { x: 1, y: 0 };
  state.nextDir = { x: 1, y: 0 };
  state.food = { x: 15, y: 10 };
  state.score = 0;
  state.timer = 0;
  state.speed = 0.12;
  state.gameOver = false;
  state.init = true;
}

if (!state.gameOver) {
  if ((keys.ArrowUp || keys.w) && state.dir.y !== 1)
    state.nextDir = { x: 0, y: -1 };
  if ((keys.ArrowDown || keys.s) && state.dir.y !== -1)
    state.nextDir = { x: 0, y: 1 };
  if ((keys.ArrowLeft || keys.a) && state.dir.x !== 1)
    state.nextDir = { x: -1, y: 0 };
  if ((keys.ArrowRight || keys.d) && state.dir.x !== -1)
    state.nextDir = { x: 1, y: 0 };
}

if (!state.gameOver) {
  state.timer += dt;
  if (state.timer >= state.speed) {
    state.timer = 0;
    state.dir = state.nextDir;
    const head = state.snake[0];
    const newHead = { x: head.x + state.dir.x, y: head.y + state.dir.y };
    if (newHead.x < 0 || newHead.x >= state.cols || newHead.y < 0 || newHead.y >= state.rows) {
      state.gameOver = true;
    }
    for (const s of state.snake) {
      if (s.x === newHead.x && s.y === newHead.y) state.gameOver = true;
    }
    if (!state.gameOver) {
      state.snake.unshift(newHead);
      if (newHead.x === state.food.x && newHead.y === state.food.y) {
        state.score++;
        state.speed = Math.max(0.05, state.speed * 0.98);
        while (true) {
          const fx = Math.floor(Math.random() * state.cols);
          const fy = Math.floor(Math.random() * state.rows);
          let occupied = false;
          for (const s of state.snake) { if (s.x === fx && s.y === fy) { occupied = true; break; } }
          if (!occupied) { state.food = { x: fx, y: fy }; break; }
        }
      } else {
        state.snake.pop();
      }
    }
  }
}

const particles = [];
for (const s of state.snake) {
  particles.push({ x: s.x * state.cell + state.cell / 2, y: s.y * state.cell + state.cell / 2, r: state.cell * 0.42, color: "#22C55E" });
}
particles.push({ x: state.food.x * state.cell + state.cell / 2, y: state.food.y * state.cell + state.cell / 2, r: state.cell * 0.42, color: "#EF4444" });
particles.push({ x: state.snake[0].x * state.cell + state.cell / 2, y: state.snake[0].y * state.cell + state.cell / 2, r: state.cell * 0.45, color: "#4ADE80" });

const text = { Score: String(state.score) };
if (state.gameOver) {
  text["GAME OVER"] = "Press R to Restart";
  if (keys.r || keys.R) state.init = false;
}

return { particles, text };

Key Concepts

ConceptHow It's Used
Grid systemCompute cols/rows from w/h divided by cell size
Direction queuenextDir buffers input between ticks; only flushed on tick
Tick timerstate.timer += dt — game only advances at fixed intervals
CollisionWall bounds check + self-intersection loop
Food spawningRandom position, rejected if on snake body
Difficulty scalingspeed *= 0.98 each food eaten (capped at 0.05s)
Restartstate.init = false on R key during game over

Building Your Own Games

The keys global opens up endless possibilities:

  • Pong / Breakout — paddle control with arrow keys, ball physics with collision
  • Platformer — gravity, jump with w/space, left/right movement
  • Top-down RPG — 4-direction movement, grid collision, item pickups
  • Rhythm game — timed key presses, scoring by accuracy
  • Puzzle game — grid manipulation with keyboard controls

See the Keyboard Input guide for more patterns and techniques.

See Also