A 2D space engine that has all things the real 3D universe has to offer (but displayed in 2D). This is an idea that started a few years ago. I started programming with Unity3D and quickly discovered the possibilities of procedural generation. I had the pretty radical idea that it should be possible to generate everything there is in the universe and build a game around it. While it is theoretically possible to generate such an universe, the current computer technology would not be able to deal with this amount of data. But there are games that work around these kinds of problems. Think about Kerbal Space Program and the Elite games. How do they solve these problems? Let’s first take a look at the problems that we’ll be facing.
Problems of scale
There are two main problems that I will be dealing with in this project. The first is the ridiculously huge amount of data that needs to be generated. The second problem are the huge distances between objects. In short, space is big and there’s a lot in it.
Problem of data
The huge amount of data is probably the easiest to work around. When the player is approaching the spaceport that orbits around a planet, we don’t need to generate all the stars in it’s galaxy. We don’t need to generate the other planets in the system. We don’t need to generate all the people that live in the cities on the surface of the planet. We only need to generate what the player can see: a model for the spacecraft, a model for the spaceport, and a planet. So that is three things versus something on the order of 10^24 (a 1 with 24 zeros, rough estimation for the amount of planets in the universe). It won’t be too difficult to create a system that generates things based on the current situation of the player.
Solving the problem of data
So we need a system that generates only what we need at a certain situation. This is done by making a list of rules for every possible situation. The game will then detect the situation of the player, and generate the objects based on the rules in that list. It will probably look something like this:
This would work pretty well as an initial setup. There is still a problem when viewing a map of the universe, but we’ll think about that sometime later. We will off course limit the size of the game to 2D, so that makes things easier.
Problem of distance
The problem of distance is a bit more difficult. This is more of a technical problem. And the problem houses within Unity3D (ok, I’m not hating on Unity, pretty much all game engines have this problem). Distances in unity are given in units. A unit is pretty much what you say it is. For example, I can say that 1 unit is 1 meter. This would mean that a spaceship of 100 meters long is 100 units. Ok that seems reasonable, but what if our spaceship is orbiting the planet at a height of 400 km (roughly the height that the ISS orbits). If we say that the player is at coördinates (0,0,0), the surface of the planet would be at (0,400 000, 0). Ok, 400 000 is a number that I can understand, no problem. Let’s punch that number into unity.
A warning. Unity recommends us to bring the range of coördinates within 100 000 units. Why? Let’s take a look.
Solving the problem of distance
So what is going on here. Unity is complaining about large numbers. Let’s take a look at how numbers are stored in computer memory.
Unity uses floats to store coordinates. Floats are numbers that can have a decimal point (1.75 or -9872.22). But there is a limit to how large floating point number can be. I don’t know fundamentally how floating point numbers work, but I’ll give an example of what I think is going on. Let’s say that our number can occupy 10 ‘memory slots’. If we add a decimal at the 9th slot, we can make numbers like 826572918.5
Ok neat. But 1 decimal is not really precise. When our spaceship is moving, it will not travel in steps of 0.1 meters. That would create very shakey and imprecise movement. Let’s say that we need an accuracy of at least 4 decimal points to calculate our movement more precise. That means that we will have only 6 more ‘slots’ for the rest of the number.
So what we see here is that accuracy drops with larger numbers. This is a huge problem, because we want to use large numbers, but also accurate position calculation. So what is the solution?
It is called a ‘layered coordinate system’. This is the same concept that Kerbal Space Program (also made in Unity) used to display their solar system. The idea of a layered coordinate system is that you use different units of measurement in different layers. For example: when we are rendering the scene of a city, we need our meter units to accurately place buildings, npc’s, trees, etc. But we also want to see that moon that is orbiting the planet. That moon might be 384 million meters away.
But what if we say that the coordinate layer of the moon is different than the coordinate layer of the city? Then we could say that 1 unit is not 1 meter, but 1 000 000 meters. Now the moon is 384 units away. Ok, great, but the moon is now physically closer to the planet than it should be. Unity still thinks that it is 384 units away, but we can solve that by changing the scale of the moon. We increased the scale of units by a factor of one million, now we need to say that the moon’s size is decreased by a factor of one million. The diameter of the moon is 3 474 000 meters. But when we apply our scale factor, it will be 3.5 units wide. That is easy for unity to calculate.
So we use many layers of different scales. For each object in a layer, we apply the scale factor to the position, size and other properties that are influenced by this (orbital speed for example).
Again this is the solution for a 3D game, so we will only deal with a small amount of these problems.
The scales in our game
Some of you might have noticed that we can resolve both out problems with the same solution. We use the different layers to deal with distances, and we use layers that the player is currently in as our situation. Great! So what layers do we need? Let’s start at our smallest layer: 1 unit = 1 meter.
Let’s take a look at the Wikipedia page on orders of magnitude.
In the first table we see increments of 4 orders of magnitude with each step. So that means that the next layer would be at 1000 meters. That is a little bit low as we have more room in out limits, but it will be easy to work with. As we can see in the table on Wikipedia, the maximum value is a ridiculously huge number: ten to the power of 10 to the power of 10 to the power of 122. That’s a bit much, so I’ll set my maximum distance to 10^24 meters. That is roughly the size of the Virgo supercluster or about 100 million light years. There are about 5000 interesting galaxies in that area and roughly 200 trillion stars. I think that is enough content for our game. We might add an extra 3 orders of magnitude when I’m bored and want to add the rest of the universe.
So our layer table looks like this:
So we’ll end up with 8 layers. That seems manageable.
How will these layers work in our 2D game. My game will be viewed top down for most situations, so we don’t need to be able to ‘look’ very far like you need to in a 3D game. However I want to be able to zoom out and transition from small scale to larger scale.
This sums up the main structure of our space engine. I’ll take a look at the generation of the objects that will populate my engine in the next log.