
Graffiti Gecko
This is a simple game I built with a few friends for the Gameplay First game jam. You play as a gecko, running away from cops and spray painting walls. The app is built with a combination of React and WebGL. React is used to make all of the UI elements, and the actual game/rendering engine is built in WebGL.
The most complex part of this project was connecting the UI to the game. I opted into leveraging React so that I could build the UI elements quickly and could focus more on the game engine later on, but it turned out to be quite annoying to get the data transfer to work between the two because the game engine is built outside of a React context.


I decided to implement a global Redux store so that I could dispatch data changes from outside of a React context and have it reflected in the UI. The problem with this though is that reading from the Redux store wasn't a cheap enough operation to do within the main game loop. Because of this, things like the settings menu needed to go through some marshaling to get it out of Redux and into the game engine.
This turned out to be a pretty efficient solution though and while maybe not the most maintainable it worked in a pinch.
The next challenge was the world generation. We wanted to go with a procedural generation system that could make interesting levels that somewhat resembled a city landscape.
The first thing I tried was to use a simplex noise algorithm to generate grass (green), roads (black), and building (white) tiles. This however was ugly and I hated it π


For my second attempt, I tried implemented the wavefunction collapse algorithm. This just uses a set of rules about what tiles can be connected and can generate pretty organic layouts.
The downside was that this was ugly too. Too organic to be a city landscape, and pretty often it would generate areas that were completely unreachable (blocked by a wall or something).
Next I smartened up and decided to build an algorithm from scratch that would grow similarly to how slime mold grows in the wild. First, I used a Poisson distribution to generate a set of stereocenters, and then I connected all the stereocenters together using a minimum spanning tree (via Kruskal's algorithm).
This finally started looking like something that made sense, but it also generated a ton of dead ends. We got a lot of feedback from testers that they would pretty often die in these dead ends because they would get blocked in by a cop and it would just be a run ender.


Finally, to mitigate the dead ends, after the MST I attempted to connected each stereocenter to at least 1 nearest neighbor. I was finally happy with it and also it was like 2 am the night before the game jam submission was due so I called it there.
Unfortunately it still generated these super long runs which you could get cornered in but we had earlier added some mitigation tactics so that you wouldn't get stuck. Overall I'm mostly happy with it but there are definitely some things to be desired with this Frankenstein algorithm.
Finally now that the world generation was done I could work on spawning entities. There are two different types of entities in this game: spray can POIs and cops. Both of these need to spawn at locations that can be accessed by the player (or that can access the player for cops π). To do this, I just used a DFS to find every reachable tile for the cops, and every reachable intersection between road and wall for the spray can POIs.
This image shows some debug tooling I built to make sure this system was working correctly and as you can see it totally was. Also ignore the pink circle made around the player, we got some feedback that it was tough to find the POIs like one hour before the submission was due so I just drew some arrows pointing from the player to every POI.

The next part of this project was the actual gimmick we wanted to build which was basically spray painting a template and then getting points for how well you did.
This was way easier to do than I thought it would be β all I had to do was load the template into a canvas, then have the player paint on a different canvas, then compare every pixel's alpha to see how much it overlapped. Kinda sucks checking every pixel but frankly it worked at 60 fps even on 4k monitors with large templates so I'm calling that a W.
You first half to find a spray can POI and press the huge CTA (you can see it in the image above in the lower right corner). The template is randomized (from a set) and the player attempts to trace it. There's a 10 second time limit and you have to get an 85 or 90% overlap to be successful. If you fail then you can't tag that one again and a new one spawns somewhere else randomly on the map.




Last is the cop AI. Every time you complete a level more cops spawn and these cops need to chase the player. Super quick feature, just an easy A* algorithm and call it a day. The harder part was making sure the cops wouldn't group up together so I gave them a bit of a buffer range where they would try to run away from each other to maintain a minimum distance, and then they would chase after the player.
The path updates every second so that the player has a chance to escape. Also the player has a dodge button to mitigate the problem with getting cornered that I mentioned earlier. Lastly, every time a cop hits a player, the player's lives decrement (obviously) and then the cops all sprint away from the player at their top speed for 1 second and the player gets invincibility frames for 1 second. This is to prevent the player from insta-dying and giving them a chance to escape.

Overall this was a fun project, it took about a week to build and the code is sloppy but functional. Try it out if you want below π¦π¨