Asteroids!

Oct 27, 2021

Having just made the crazy leap from my full-time job to full-time freelancing, I've been scrambling to sharpen as many skills as I can. Since I already knew that it was going to be a grind, I wanted my projects to bring me joy, even ones I could finish in a week.

One of my favorite projects in college was to implement the classic game of Asteroids using a SoC which had a built-in FPGA HDMA driver. You can actually still find the code on my github.

We were supposed to hook in a gyroscope so users could control the ship by tilting the board. Then, they could use the buttons on the PCB to shoot/thrust. Well, we never got the gyroscope working, but it still turned out OK.

I decided to relive my college years, but this time create the game in Javascript so it could be played in the browser instead of needing the SoC. And of course, I was going to hook in the gyroscope...

The completed game can be found at asteroids.chrishughesdev.com.

Asteroids Logo

The directions to play are on the top of the home screen. If you're on desktop, W, A, and D control the ship movements (or arrow keys if you prefer), and the space bar shoots.

The fun part is playing on mobile. In that case, the game uses the gyroscope on the mobile phone to steer the craft. Tapping on the right side of the screen shoots and tapping on the left controls the thruster.

Technologies

The app is created with Python's Flask framework managing the backend and plain-old Javascript in the frontend. The HTML is actually really simple. It just ended up being a huge HTML5 canvas element that takes the entire screen. Then I used Javascript to render the required graphics directly on the canvas. One of the reasons that I went with the game of Asteroids is because the graphics are really simple, yet it still makes a game which is satisfying to code and play. For this exercise, I just wanted to sharpen my skills in responsive apps, not spend all my time making beautiful graphics. I knew once I went down that rabbit hole, I would never come out.

Anyways, even though the game was "plain-old Javascript," I still needed a unit testing package, a somewhat more advanced math package, and a package to calculate collisions for me. Instead of implementing these myself, I used Yarn to handle the package management for me. I used Webpack to bundle this stuff together and deliver it to the client.

For those curious, the packages I relied on most were:

The site (both front and backend) is hosted on Heroku. If you noticed that the initial load is a little long, it's because I'm on the free tier. To save money and push users to use their paid tiers, Heroku actually puts their free tier servers to sleep if they have not received a request in a certain period of time. On the first request after a period of inactivity, it can take several seconds for the server to re-activate. Not ideal, but the fact that they provide a platform where I can just push to Github and they handle all the setup and load balancing for free is already too good to be true, so I can't complain.

Features and Gameplay

The game starts at the main menu, where the only choice the user has is to proceed. If you're on mobile, the first tap will prompt if you wish to allow the website to access motion and orientation. Once you get past the prompt, you'll get to access the rest of the game unimpeded.

After the main menu, you'll be dropped into the classic game of asteroids.

Asteroids gameplay

I tried to follow the classic gameplay as much as I could, including adding alien saucers which try to shoot at the player. I ignored some of the later-stage dynamics since I would have never seen them live. I haven't been able to get past the first few stages...

After losing all of your lives to asteroids or saucers, the game switches to the High Score screen.

High score screen displayed after losing

Here, you are free to enter all of your highest scores along with any memorable names you can think of. The entries persist until the Heroku free tier runs out of database storage.

One thing to note is that everyone gets their own set of high scores, so the entries are there for your own enjoyment.

If you enter a high score, the new high score will be displayed if the server successfully processed it. Then within a few moments, you will be brought back to the home screen. If you don't want to enter a score, you can press Enter (or Done if you're on mobile) without entering anything into the form, and you'll also be redirected.

The game should have the same feel whether you are on your laptop or on mobile. I made sure to scale everything depending on the screen size and device pixel ratio. Even if you change the orientation of your phone mid-game (portrait to landscape or vice-versa), the game should be re-rendered in a way that's expected and doesn't harm gameplay.

Summary

Like all my other recent work, the Asteroids project can be found on Github.

Though Asteroids feels like a silly project, it was a blast to implement and I learned a ton while doing so. Games have a way of exposing any weakness in a design and gotchas with languages you might not be that familiar with. Plus, getting this to work well on mobile took quite a bit of fiddling... Well, on to my next project where I can continue to sharpen my Javascript skills!

My best score is only about 1080. See if you can beat it!