AWS Logo
Menu
Dyson Swarm: How I built a hard science fiction game with AWS services

Dyson Swarm: How I built a hard science fiction game with AWS services

An end-to-end overview of building a serverless browser game.

Published Dec 31, 2024

The game concept

I'm a huge science fiction fan -- so much so that I started and ran a science fiction magazine for five years, and I'm still very engaged in the science fiction community.
Back in October I had the idea to start making a series of short games to explain hard science fiction concepts in a fun way. Right after I started the game, I saw that AWS was having a Game Builder Challenge, so I decided to write my first hard science fiction game as a part of the hackathon!
Dyson Swarm is an incremental (clicker) game about dismantling the solar system in order to completely envelop the sun in space habitats. You start as a simple game developer, and progress through stages, building up resources as you go along.
I originally thought that development would only take 10-20 hours, but the scope of the game ballooned, and ultimately I ended up spending closer to 70 hours developing the game (the entirety of which were spent after my wife and kids went to sleep at night, which is my excuse if you encounter a bug). Effort estimates are one of the most difficult parts of software engineering!
I've hosted the game here if you want to try it out: Dyson Swarm

The AWS Architecture

Dyson Swarm AWS architecture
The game is built using client-side Javascript, and runs entirely in the browser. Since all the game code is served through static HTML/Javascript elements, the cheapest and easiest way to host such a game is with a static site S3 bucket fronted by the CloudFront CDN -- this allows fast serving of the files all around the world, and CloudFront can do the TLS termination so that you don't need to deal with custom certificates or servers.
The game also collects some high-level metrics about how many people are playing the game (anonymized), and how far they're getting (what stage of the game they've completed). These metrics are stored in an RDS Postgres database, and get there via a serverless API built using API Gateway and Lambda. I'm using an RDS instance, since I already had one available, but you could just as easily use serverless RDS for this.
I deployed the S3 bucket and CloudFront distribution through the AWS console, and created a Python-based AWS CDK stack for the serverless metrics lambda.

The CDK stack

This is the CDK stack for the serverless metrics lambda:
It's not too complex at all! You can see that it references an existing ECR repo (with a container image for the lambda) along with an existing Route 53 hosted zone (for the custom domain). Other than that, it's creating an API Gateway backed by a Lambda that is built using the specified container in ECR.
This file is also located in the open-source game repo here: dyson_swarm_stack.py if you'd like to see it in context.

The Code

The entire source code for the game can be found here: Dyson Swarm GitHub Repo
The main game loop is a hundred millisecond interval specified at the end of the dysonswarm.html file, so if you want to dig into the code in detail I'd start there.
The game uses local browser storage to maintain state, so if you close the browser and come back later your game is automatically saved. This is actually very easy to implement in Javascript, all you have to do is take an existing json object and store it like this: localStorage.setItem('dysonSwarmGameState', JSON.stringify(gameState));
Each time the game loop runs, it calculates resource gains and losses based on the current gameState. All the other action happens when the buttons are clicked (these change the gameState). Since there are currently 56 of these buttons that get unlocked at various stages of the game, the buttons have their own file called buttonFunctions.js. The file contains metadata about what the buttons do along with functions that get invoked when the buttons are clicked. The button functions get attached to the actual button DOM elements when the game is instantiated, by looping through all the button elements and running handleButton() on them when the game is loaded. As buttons are clicked, new stages of the game are unlocked, until you've built a solar-system spanning civilization.
The most complicated part of building the game was creating and importing the animations, particularly the satellites.js animation. I initially made them with SVG, but for the orbital animation things started to break down at around two thousand satellite elements. I ported this to Canvas, since it can more efficiently render a greater number of elements, being raster-based instead of vector-based.
Another tricky thing was covering all the corner cases for the game logic. Some elements (like "sell shipyard") were only implemented after friends played through the game and got stuck at various points. There's still some balancing I could do to make the game flow better, and I have a list of small improvements in the repo that I'd like to make. Managing game state properly is difficult!

Using Q Developer

One of the elements of the AWS Game Builder Challenge was to use AWS Q Developer to help build the game. I was excited to try it out, since I've used other coding assistants to great effect in the past. I downloaded the VSCode Q Developer plugin and used it that way.
The pros:
  • The built-in chat interface is good, you can ask it questions as you go along and it will provide useful answers.
  • The /dev feature will actually create a diff and also apply it to your code if you approve it! This prevents tedious copy/paste operations and saves time.
  • Q Developer is very good at replicating repeating patterns in code. For instance, I told it things like "add 2 percent inflation to all repeatable buttons (other than the marketer button), in the same pattern as the ad purchase button inflation." and it saved a ton of time!
The cons:
  • The /dev feature takes a long time (on the order of minutes), because it does multiple LLM invocations on the back-end.
  • The /dev feature is good at generating code diffs is good for some things, but it often decides to create new files instead of adding code in-line. You have to be very careful in your prompt management to keep it from going off the rails.
I think Q Developer has room for improvement, but AWS is rapidly iterating on it and I foresee the tool being used more often in the future.

The game is open-source!

I've released the entire source code on GitHub under an MIT license, so please feel free to use any of the elements as a base for your own game.
If you end up building a game of your own, I'd love to hear about it!
 

Comments