This month has seen a host of small improvements piling up, some of which are invisible code changes. While any one may not make much of a visual splash, they add up to the game being in a better place to move forward than it was a month ago. I’ll start with the more visible ones and then get to the code digging.
Font Choices and Title Design
When it comes to the look of a game, fonts a tricky thing. Using the defaults for the engine or graphics package can subconsciously look cheap or lazy. Picking something distinctive is good, but you have to make sure it’s readable in your game without being confusing or straining. Add in the thousands of font options out there and picking a good font can be trying. Here’s just some of the fonts I looked at when trying to pick one.
You get a bit more room to be bold in titles and logos than general user interface, but I ended up using the same font family for both. Getting it all in the game has helped the look along subtly, but significantly to me.
Also visible in the above screenshots is a new edge-of-screen glow to really get that retro screen look going. The backdrop for the game isn’t a pure black anymore either, though it’s close. This will probably need to be user-tunable with options eventually, much like the general bloom, but I’m rather taken with the effect. All together the game is looking a lot different than it did a year ago or even three months ago, and rather for the better I think.
Bouncy Objective Indicators
Harder to show off but just as important, I addressed a nagging visual issue with objectives. With celestial distance scales a perfectly reasonable objective that is no trouble to hit may be so small as to be invisible when viewing the whole level. For instance, if you fly from Earth to one of Jupiter’s moons, then when you are looking at both Earth and Jupiter you won’t even be able to see the particular moon you’re after, let alone the objective zone around it. This makes objective indicators bad at helping people understand the objectives at a glance, which is most of their job. My solution is that objectives now have a minimum visual size. If you zoom out far enough that they should be smaller than that limit they will stop shrinking.
Naturally, that reduces their effectiveness at helping you refine the course, as now it can look like you’re meeting the objective, since your course appears to cross the circle, but you aren’t because the circle is being drawn larger than it should be. To help address that if the real objective is smaller than the displayed one the circle now animates. At present it bounces in and out to indicate that you need to get closer. I also tried scrolling the texture, and may turn that on for some testing builds in the future to see how players react to the different options.
This project is one I’ve been working on, to varying levels of intensity, for quite a bit longer than this blog has been up. I’ve developed a lot as a programmer in that time, and sometimes I realize that what seemed like a good enough idea years or months ago is holding things back. This month I attacked a pile of these problems that have been sitting around for a while.
If this gets too dry, there’s a few screenshots of other new things in the next section.
Object Identifier Rewrite
For something outside the simulation(like the GUI, or the drawing code) to get information about an object, one of two things is needed. Either the outsider needs far too much access to the internal structure of the simulation(see thrust IDs below), or there needs to be an identifier the outsider can ask for information with. Originally, I decided that I should just use the name of objects as the identifier. They need names anyway, so why not?
Well, two reasons. One is that passing around text chunks and comparing them to each other is not the cheapest option computationally. This hasn’t been a huge performance drain, but when ID comparisons happen thousands of times per second then it’s a problem worth addressing. The second reason hasn’t been a big issue for the simulation but has cropped up in the level editor where I repeated the mistake. If for some reason you change the name of an object, you’ve suddenly caused chaos for everything that referred to it. If I happened to make an objective involving an object in the level editor and then changed that object’s name it would cause errors that required opening the level in a text editor to fix
That’s all fixed and more resilient now. Everything is referred to by ID numbers everywhere that matters, and unless someone hand-hacks a level file to have duplicate identifiers all should be good. While I was in there I made a few other changes to the data structures and how they’re searched that resulted in measurable performance gains. There’s always room for more of that, of course!
Another one that’s been waiting a while. Translating the huge scales ranges of space into computer graphics has challenges. The way computer games typically store positions(single-precision floating point numbers) has limited accuracy. If your numbers are all close enough together this is plenty fine, but if you start to get towards the far ends of their range they lose resolution and errors develop. This is fine for most cases and the technology used for games is heavily optimized around it. Unfortunately for space you have to deal with quantities that are so tiny(such as the force of gravity on Pluto) and distances that are so huge(such as the position of Pluto) that this breaks down.
Atomic Space Race deals with this by doing all the math at a higher precision, then converting to single-precision floats only to feed into a unity scene for drawing. Previously, this meant just converting the numbers and then scaling them down to fit inside a range floating point number’s range, then moving a camera around the resultant scene. This is doing things in the wrong order. Oops.
Since we convert then scale, things at the extremes of what floats can handle are still mangled on their way to the scene. Well, not anymore. I’ve rewritten large chunks of the display code so that now the camera is entirely stationary as far as unity is concerned, and positions from the simulation are scaled and moved before being converted to single-precision floats
The result of all this is a bit slower than the old way, unfortunately. Doing any math before converting to single-floats will always be slower than doing it with them. And along the way I centralized the reference-frame logic in such a way that it broke optimizations I made to orbit-drawing code earlier, making some more work for myself in the future. But the new way is much more resilient to extreme circumstances, adapting to them perfectly rather than relying on me to tweak some magic translation constants in the vain hope that a set of values existed that would work everywhere. It also opens some doors for more advanced reference frame manipulations in the future, which are badly needed for certain puzzle types.
Above I mentioned that letting things have too much access or knowledge about the internal simulation was bad, and this is a good example. I had a few persistent bugs in thrust editing. Whenever you selected or edited a thrust in the GUI, it was essentially saying to the simulation “Give me the first thrust” or “make this change to the third thrust”.
Well, what happens if you have a burn at T=1000, one at T=3000, and one at T=4000, then you change the third one to happen at T=10? It’s not the third one anymore.
This is something that can be managed with enough effort, but it can also be managed by just giving every thrust a unique ID number and having the UI communicate to the simulation using that instead. This is now done and works much better, squashing several squirrely interface bugs at once. It’s also just plain better design in general, which may pay off in the longer term.
After all that was done I rewarded myself by taking another look at binary stars. Back in ATOMIC SPACE NEWS #006 I talked about having gotten them into the editor but not quite sorting out how to get them from that into the simulation properly. Turns out the way I was mathing the starting velocities of the stars left the pair with significant net momentum. They orbited each other properly, and the planets all orbited where their stars should be properly, but the stars were zooming off due to imbalanced momentum and as a result distorting all the planet orbits. Got that sorted yesterday and already gotten a few cool systems roughed in.
An alternate, stable version of the above system in motion.
I’ve been hunting for good music and interface sounds for the game lately, and think I’ve got a few good candidates. Integrating them into the game has some implications that I’m not sure I’ll sort out by next month, but we’ll see. The above clip includes one of the music pieces I’m considering. Let me know what you think of it!