Voidstar pt1- Generating an Entire Galaxy
For several years, I’ve wanted to build a space-opera roguelike, where players can take on interstellar adventures, meet exotic aliens, and explore uncharted systems. Think No Man’s Sky meets Dwarf Fortress. As the game grows and evolves, I’ll talk more about the actual mechanics, but in this post I’m going to introduce the galaxy generation system, which was the area I started working on.
World Generation Overview
World generation is the first stage of game play. Players generate a world file, which their characters can live in and explore. Players of Dwarf Fortress will be familiar with this pattern. Procedural generation is my preferred form of art, so I wanted to tackle this system early.
At a high level, the game world is stored in a hierarchical tree, the top level of which is the Galaxy object. For the purposes of this post, the Galaxy’s only child is a Starmap, which we will see later.
Creating Some Stars
The Galaxy object has four methods of interest:
We’ll see bake_starmap in the next post. Let’s take a look at how we lay out the galaxy.
This method lets us add a randomly distributed disc to the galaxy’s star list. Its inputs are a count of stars and the distribution parameters. In Voidstar’s actual code, this method takes additional parameters that let the worldbuilder customize what types of stars show up. That way, we can have different star type distributions on the spiral arms than in the core (and other possible configurations).
Tall and skinny disc
By combining two skinny discs, two wide discs, and one small circular disc, we get a large cross that will form the arms of our galaxy:
Giving It Some Style
The next method is swirl, which requires a couple helper methods. These are mathematically fairly simple.
where a is the configurable swirl factor. The 20th root of the distance may raise eyebrows, but in testing I found this to produce the best output. However, this changes drastically with different standard deviations in the star distributions, so it may warrant some inspection.
The swirl function took a few interations to get right. It turns out that factor needs to be closer to 100 to produce realistic looking output.
The last function we need to make a pretty galaxy is a jitter function, which quickly eases up any hard lines we may have picked up when adding and swirling the discs:
The jitter and swirl factors can be used to create more evenly distributed systems within the Galaxy. They will likely be configurable parameters at worldgen.
Tying It All Together
We need to get all of this into a harness so we can see what it does:
We’ll want a way to look at the map. For that, I’m using matplotlib:
Here, we’re pulling the data from the stars and unzipping it into two lists, using the special operator *, which tells zip to perform the inverse operation.
Then, we’re generating a scatterplot with a nicely fit window.
Now, kick the whole process off: