Full disclosure: I won a year of CodePen Pro as part of the prizes from js13k.
A couple of months back I was approached by Ania Kubów, who has a YouTube channel dedicated to JavaScript tutorials. She wanted me to contribute to a video for FreeCodeCamp showing of the top 20 entries of this years JS13K, by having their devs show and explain some cool bits of code. As Edge Not Found managed to get 2nd place, I figured I should actually record and voice this video myself (something I don’t often do online). My code example is about how I render the same level seemingly infinitely across the screen, which you can find on CodePen here.
My part start at 9:12 in the video, but I’ve also provided a transcript with images of my part in the video below. I hope it is useful to someone!
Hello! I’m Tom Hermans, I’m a Dutch developer who also makes video games sometimes, and for this year’s 13K jam I made “Edge Not Found”. It’s a puzzle game in an infinitely repeating world. I really like tile-based box pushing games like Sokoban, and I’ve already made several of them, but this one is probably my most complex one yet. I’ve been sitting on the idea for this game for a while, and the jam was a good opportunity to develop it and design some cool puzzles for it.
So let’s talk about the rendering for a bit. Each frame in the game is drawn using three steps. In the first step I create multiple canvasses that serve as sprites for the various puzzle elements, like walls and boxes. These are drawn using the rough library, which generates nice, hand-drawn looking shapes.
The second step renders the current puzzle state using these sprites, like this, then finally, it’ll draw this level repeatedly to fill up the entire game canvas. I really like the bit of code that handles this, so today, I’ll explain how this infinitely wrapping world works.
For demonstration purposes, I’ve pre-generated a level image from the game instead of generating one from scratch, to keep it simple. Now then, I have isolated the code in this sample. I’ll go over the most important bits, but if you want to toy around with the full thing, you can access this example with this link. So let’s go through it!
The core of the tiling magic happens here, with the x and y offsets:
These essentially affect how the levels are tiled. For example, if you’ve played the game you know this level can’t be solved, since the crate can’t get to the goal:
But if we change the y offset to 2, the level becomes a straight line, and the puzzle becomes solvable. It’s kinda complicated, but it is used in lots of tricky puzzles!
Next, we calculate how much levels we can fit onto the screen. The clipoffset here adds a small margin to the level border. But it also shows that the code works by putting it to a negative value*, then if I resize the screen you can see that levels are no longer drawn near the border of the screen. This makes sure that nothing will be drawn if it nearly or completely invisible:
Finally, a nested FOR loop actually draws the levels. Note that levels further away from the center will get more transparent. So if I zoom out all the way, you can see it will go on for a while, but eventually the wrapping will no longer be visible!
When drawing the image with an offset defined, we shift the image on the grid. So, if I enable the coordinates display, you can see that the image also shifts two tiles down for each step on the x axis, and that’s due to the levelOffsetY I set earlier:
And that is it! Once again, you can view this code snippet here. Do consider playing Edge Not Found first if you haven’t, so you can learn how this level wrapping is used for tricky puzzles.
So, I hope this inspired you to make your own infinite worlds! If you liked this, then you can find me as Auroriax on Twitter for more of my things, and if you look that name up on GitHub you should also be able to find the full source code of the game. Bye, and thanks for watching!