Making a Space Game
Space is a captivating setting for a video game. If you want to make a “no-limits” game, you can’t go any bigger than space. Many classic video game activities like exploration, combat, trading, strategy and player customization can be realized in a space setting. Cool, let’s do it.
Biting Off More Than You Can Chew
It can be tempting to start by imagining all the cool features your game could have, like procedural galaxies, solar systems and planets. Maybe it could be 3D, but not bloated like all those modern games! Let’s make it run on that old laptop you still have lying around! And make it look as good as the latest AAA titles from the best minds in the industry.
This is all not advisable. Those games are hard to make, taking years of work by many very smart and talented people. We have no hope of meeting the bar they’ve set, talk less of doing so on hopelessly outdated hardware. Don’t bite off more than you can chew.
- Procedural everything
- Fun (!!!)
Ignoring the previous advice, let’s make it happen. We just have to avoid getting caught in the trap of making our own game engine, as well. We could waste years with no progress, when there are plenty of free game engines we could use instead. Don’t make your own game engine, it’s a waste of time.
Making Our Own Game Engine
A game engine is conceptually pretty simple. You have a bunch of data about where everything is and how fast it’s going, plus things like health and ammo, what color things are, and AI objectives. That’s collectively your “game state”, and you basically just want to lay it out in a way that’s really fast to access. Then we have stuff like what files are loaded, what’s on the GPU, what our control inputs are, are we in full screen, etc. It doesn’t really pertain to our game itself, but our game still needs it to take our inputs and draw a pretty picture. Let’s call it “engine state”.
Every 1/60th of a second (or less), we take our game state and our player input, smush them together, and get a new game state, representing what happens 1/60th of a second later. Then we take our new game state, and try to render it, possibly updating the engine state along the way.
Okay But I Really Just Want To Fly Around In Space
Besides black emptiness, space is full of stars (my god). Usually there’s like a trillion of them, but there’s also stuff like space dust in the way, so we only really care about the ones that are nearby. We’ll keep a bunch of them in a flat array that’s fast to access and easy to make.
Create a bunch of random points. These are your stars. Render them. Cool.
We’ll make them fade to black at a certain radius so it’s not as obvious that everything interesting in the universe is shaped like a giant cube.
Everything Interesting in the Universe is Shaped Like 27 Giant Cubes
So now we have a small clump of stars to play in! To preserve the illusion of a vast universe, all we need to do is put up big glowing space-walls, and a bright red countown in the middle of the screen telling you how long it is until you explode if you don’t get back where you belong.
Actually (no) we won’t do that. We just make sure that, no matter what direction you fly in, there will be another cube filled with stars for you to fly into.
A nice way to do this is to keep track of everything in a 3x3x3 array of cubes, each filled with stars (picture a rubik’s cube). You stay in the center cube, with 26 cubes surrounding you on all sides. This array is a 3D sliding window, similar to a 1D circular buffer, with more dimensions (you can call this a hypertoroidal buffer if you want to impress people). You can make the stars fade out just shy of one cube-edge-width, and make sure update the array to keep you in the center cube.
In this diagram, the circle represents the distance at which stars fade out, the squares represent boxes filled with stars, and the arrow represents us, moving through space (the red box is just there to look pretty). Notice that the circle is always contained within our grid of boxes!
If we use the position of the cube to determine the pseudo-random positions of the stars inside it (seeding the RNG with a hash of the position), we can fly far away from our starting position, and when we return, the same stars will “be there”, in the same positions.
To bring back our earlier terminology, our position in space is definitely game state. I would argue that the positions of the stars are engine state, since they are derived procedurally from game state. As long as the generation is deterministic, this is not much different from loading in a texture for a 3D model. If we wanted to save the game to a save file, we could throw out everything we know about the stars we’ve created, and the engine could, given the player position, rederive them when a save file is loaded.
This is Simultaneously Too Much Information and Not Enough Information
You can expect more details, code snippets, and diagrams in future posts. For now I just wanted to get a feel for writing on this kind of topic. There are plenty of topics to cover, and plenty of problems to address for each. Thanks for reading my first post!