That's why I thought it was about time that I should dust it off, upgrade it, and give it a new place to call home. You can play it now by clicking the button below, or continue reading to learn more about the development process 😄
Table of Contents
I used HTML5 / Canvas for the rendering which was pretty fun to work with. It allows you to create your own sprites as an image source to paint onto the canvas. I actually drew my own Kryptonite in Photoshop for the obstacles:
The game randomly selects the height and calculates how much it needs for the top and bottom piece. It takes into account the
constant and any
Kryptonite.PADDING that I've allowed to make the hit boxes a bit more friendly, then it takes the appropriate slice
from the source image and paints it onto the canvas. COOL, RIGHT?!
During development I had the "flying object" (which I didn't know would be Superman at the time) represented as a circle, but clearly this did not work too well once I switched to using the Superman sprite:
The white paths show the true boundaries used for determining collisions. Even with padding, you can see that the circle wasn't going to be very accurate anymore. So, I changed Superman's hit box shape to a triangle instead. After I defined the hit box boundaries I moved on to the fun part of defining how to detect collisions. The switch to a triangle hit box required some special handling.
Here I detect when the right vertical edge of Superman's triangular hit box collides with the left edge of the Kryptonite. An extra qualifying condition to check is whether the top of Superman is above the lowest edge of the upper Kryptonite or the bottom of Superman is below the top edge of the lower Kryptonite.
Here I detect when the top point or bottom edge of Superman collides with the top/bottom edges of the Kryptonite within the gap.
Finally, I detect when the rear hypotenuse edge of Superman's hit box collides with the bottom edge of the top Kryptonite. Due to the shape of Superman with his cape, a circle or quadrilateral hit box would trigger a collision where visually it did not appear that one occurred. A trianglur hit box proved to allow more accurate collision detection.
This required a slight change in how the collision would be detected as Superman rises past this particular edge. Using an Isosceles Right Triangle made this slightly easier:
Simply put, while k is between points a and b, a collision is triggered if the length of kx is less than the length of ax. A nice and easy solution after I initially thought I would need to whip out some trig functions for this one.
Updates for 2022
To bring it into the modern era, I chose maximum pain by deciding to migrate it to TypeScript as a Next.js project using the t3 stack. With it I'll be leveraging tRPC/Prisma to replace the Ruby/Rails LeaderboardAPI for a completely fullstack Next.js application. New for 2022, I'll be adding more elements to the background of the game, and I'll also be adding SMS notifications for leaderboard rank updates.
As a predominantly backend engineer, this was also an excellent exercise in both TypeScript and React. I've used a bit of both
at TravelPerk, but not with a very strong understanding of all the differences between
firing of a
useEffect side-effect would cause the game to glitch out.
For context, a lot of the decisions I made regarding which language, framework, and/or tools to use were not because it was the easiest or fastest way to do it, but because I wanted to intentionally force myself to learn new things along the way. It's been slower and more painful this way, and sometimes a complete overengineering of the project, but it's been a great way to test myself and have fun while learning new skills. I mean, who doesn't want to play with all the new shiny things anyways?
As I resurrected this game I found myself finding all sorts of improvements I wanted to work on. Overall, most of the actual game mechanics will remain unchanged. I have to give myself credit for creating an actual playable game, but there are plenty of new features, nice-to-haves, and of course refactorings that would go a long way to keep iterating on it.
- Leaderboard that is less hackable with server-side game validation
- Mute sound toggle
- Scrolling background art
- SMS notifications
- Game counter