Dear reader,

In this post I am going to talk about a game I made for the Coding Blocks Game Jam, called Hidden Snek.

TLDR: It’s a game you play in the developer tools. Link to it here.

The Inspiration

I got the idea to do this from Stewart Smith’s website stewartsmith.io. If you haven’t checked out any of his stuff I highly recommend it. My first exposure to him was his Browser Pong game. I’ve since drawn a lot of inspiration from his merger of art and programming.

I was snooping around through the HTML of his website as I often do on websites I admire and I found a hidden little gem!

Stewart Smith Comments Animation

“What! Flip, I didn’t know that was possible!” - Me

After a while I got to thinking, I could make a simple game using this type of animation.

Let’s Go

In January Coding Blocks a podcast I listen to hosted a game jam and I thought it would be the perfect time to try this out. It also turned out to be a pretty great crowd to show it to since the audience of the show is programmers.

One of my first ground rules is that I wanted to take as little from Stewart’s original animation as possible (link to his code here). And might I just say, I seriously admire this little bit of code. So concise. It practically tells a story.

My regret

I had a professor in university who was a serious advocate of constantly committing your code. His logic was you can always roll back to a previous state if you get stuck. Great advice! I however rarely do this, especially when I’m working on a, one file, <500 lines project. I didn’t ever get stuck, but I do wish now that I had the history of how I worked. But alas, I’m stuck with an “initial commit” of a completed project.

The Build

I started with what I saw as the foundation, keyboard event handling, and an animation loop. First the animation loop.

To animate in the DOM you need a node to wiggle:

let commentNode = document.createComment('')
document.insertBefore(commentNode, document.firstChild)

And an event listener to get our key-presses:

let input = ''

window.onkeydown = function (e) {
  input = e.key
}

Then tie it all together once the DOM is loaded, and start a loop.

document.addEventListener('DOMContentLoaded', function () {
  let width = 30,
    height = 30,
    commentNode = document.createComment('')
  document.insertBefore(commentNode, document.firstChild)

  const events = eventHandler()
  const can = drawer(width, height, commentNode)

  let state = resetState(width, height)
  setInterval(() => {
    state = gameLoop(can, events, state, width, height)
  }, 150)
})

In this project, I was trying to force myself to use javascript closures. I doubt I did it the best way, but I sure did it.

const eventHandler = () => {
  let input = ''

  window.onkeydown = function (e) {
    input = e.key
  }

  return {
    input: () => input,
    clear: () => {
      input = ''
    },
  }
}

Side note here. I never know how much code to put in an article like this. Right now I’m going to opt for less code. See the source if you want to see it all.

I tried to have a closure function set up for each big part of handling the game events, the game logic, rendering. Overall I’ll give myself a B-.

Rendering Emojis in the Comments

Snake is a square game. Each cell is the same size. Rendering in the comments you have no control over font. The default font is not a monospace font which would have been incredibly convenient. Instead, I ended up using emoji shapes to fill the space. There happens to be a square shape (⬛⬜🟫) in a variety of colors which I used to fill the width of a cell. Next was finding other emojis that also filled the width of a cell that I could use for the rest of the game.

Firefox also has opinions about newlines in devtool comments.

Firefox devtool comment

Chrome:

Chrome devtool comment

The game

screenshot of the game in action

I’ve gone ahead and added this game to the source code of this website. Go ahead and give it a try. If you find any issues go ahead and add them to the github. I’d love feedback!

Cheers,

Jacob Strong

P.S. - Writing is not my jam, thanks for making it this far!