ScrumbleShip is the most accurate space combat simulation devised to date. Gather resources, construct a capital ship out of individual blocks, then pilot it with AI or human help against other players.
In which Dirkson discovers that space is, well, Big.
Posted by dirkson on Dec 7th, 2012
As I start to program multiple objects on screen at once, it turns out we need a more robust movement system than merely relative to the ship.. Specifically, I need a way to pinpoint an object's location within the solar system, whether it be a planet, ship, or player. And, after some testing to determine the smallest change in location visible to the naked eye, I worked out that we need to do it to within a tenth of a millimeter.
To quote Douglas Adams' HitchHiker's Guide to the Galaxy, "Space is big. You just won't believe how vastly, hugely, mind- bogglingly big it is. I mean, you may think it's a long way down the road to the chemist's, but that's just peanuts to space."
For example, it's about 5,000 AU (747,989,353,500 or about 748 Billion kilometers) to the start of the oort cloud, and it finally peters out around 100,000 AU. If we do the math, that means the diameter of our solar system is roughly 600 quitillion tenths of a millimeter. 600,000,000,000,000,000,000. That's a lot of zeros.
This presents us with two big problems.
Accelerating at 3 G's (~30m/s/s, which may actually be too high to sustain ), covering that distance would take almost exactly one year of constant acceleration. We need travel times on the order of minutes, not years.
There are several solutions to this problem:
We could scale up our accelerations - But allowing humans to withstand 100's of G's of acceleration would wildly affect combat. We could make time go by faster or slower - But a multiplayer game demands all players be on the same time scale. We could introduce system-internal warp jumps - But this would make for a less fun game, where players had a difficult time interacting with one another, and the high speeds attainable would make combat much less realistic.
My favorite solution is simply to scale down the size of the solar system - Scaling it down by a factor of 100,000 turns a 120 AU Pluto-to-Pluto transit into a 40 minute epic quest, and places the close-in planets and asteroids mere minutes from each other. Keeping the ratios the same allows more accuracy than the other solutions, while ensuring that fun doesn't take a hit for it. It's worth noting that this solution is nearly the same thing as merely scaling everyone's time by a similar factor.
At the same time, let's chop off the oort cloud and restrict ourselves to the Kuiper belt - At 5,000-100,000 AU, there's no method of scaling that will allow the Oort cloud to be easily reachable without making the rest of the solar system absurdly close together, and we can still access Oort cloud objects through comets. So instead of 100,000 AU, we merely need around 60 AU to reach to the far edges of the Kuiper belt.
So from our original starting point of needing 100,000 AU (600 Quintillion tenths of a millimeter), we now only need about (60*2 AU)/100,000, or 1.8 Trillion tenths of a millimeter.
That's a significant reduction!
The largest number I can easily represent in C is somewhere along the lines of 4.3 Billion (4,294,967,295). That's a far cry from 600 Quintillion OR 1.8 Trillion - We're not out of the woods yet!
The naive solution to this problem is to use a larger variable in a slightly different language - C99, for example, gives us access to a 64 bit number instead of a 32 bit number, expanding our range to
over 18 quintillion! (18,446,744,073,709,551,615) That's more than big enough.
However, this method has a problem - Namely, hit detection. If I were to lump all objects in the solar system together, I would need to check to see how close each one was to each other one. Since I need to do this about 30 times per second and there may be thousands or tens of thousands of objects, this solution is likely to eat up a ton of CPU time.
However, there's a better solution - Chop the system up into Sector, SuperSectors, and MegaSectors.
Each Sector is 10,000 kilometers (1 billion tenths of a millimeter) per side - For scale, Earth is 12,756 kilometers wide. This means that a straight line drawn through our shrunken solar system would cross about 1.8 million different sectors. I told you space was big.
By adding sectors to large structures (SuperSectors and MegaSectors) I can construct an easy method of having enough sectors to do the job. Now, instead of needing to check for collisions against all other objects, I merely need to check in the nearest sector or two!
I've already got this system partially implemented, and have had some success making the ship fly around independently of the human character. The next steps are bug fixing and implementation of multiple objects. (Such as the sun and planets)
P.S. This article contains a lot of math and sometimes I miss things. So let's have a contest: Whoever spots the first major math error (Anything besides a typo or rounding error.) in this article gets a free copy of ScrumbleShip!