World(s) of Hex
This is a (very) late and verbose (I don’t know how to keep it brief) writeup about how one world became many.
Back in 2017 I wrote about how I came to build my game World of Hex.
In October 2018 I released version 2.0 of World of Hex, and this one came with a massive expansion to the game that for some reason I never thought was worth writing about. 🤷♂️
Further to that, in August 2020 I also added macOS support which was far more significant than I had expected it to be at the time.
Now, in 2022, as I embark on another series of enhancements to the game, I thought it might be worth writing a little about the process of adding an entire (well sort of) solar system to the game.
When I first built the game I already had the Moon (or Luna) moving around the Earth at the right time and I was quite happy with that, even if I might not have got some aspects of it right. I had had thoughts of adding a colony to Luna but that wasn’t part of the original plan, so I launched the game with just Earth as a playable colony. It seemed like enough.
But then in 2018 I got the itch to expand, and with Mars being a hot topic I thought it would be neat to not only add a colony to Luna, but one to Mars as well. After all, with everyone wanting to get to Mars (like how many Netflix series are there taking people to Mars?) first I thought it would be a good draw card for the game.
Add to that the fact that I’d been thoroughly enjoying watching The Expanse™ on Netflix, that itch grew and I began to wonder just how hard it would be to “expand” the game to encompass more of the solar system, providing colonies on much more than just Luna and Mars.
Prototyping a solar system
So it was time to start learning how to build a model of our solar system. Google was my greatest initial resource along with Wikipedia, and soon I happened upon a set of data that I could use to model the positions of each of the planets in the solar system.
I started off with a small Swift project just as a prototype to see if I could do what I wanted in SceneKit. The existing app used SceneKit to display the Earth (a sphere) surrounded by a Hexasphere, with another appropriately scaled sphere (Luna) orbiting the Earth.
A macOS playground showing an early prototype of a solar system.
This prototype adopted a set of Orbital Elements, or Keplerian Elements to place each planetoid (as I called all of the planets and Luna) in the correct position given a date & time. I was thus able to render a basic solar system using SceneKit quite easily.
I was then able to take that prototype, rewrite the key elements of it in Objective-C and integrate it into World of Hex.
That then meant I needed to craft Hexaspheres for both Luna and Mars, that would act as a representation of the colonies on those planetoids. I built these based on my own naive ideas of what the colonies on those planetoids might look like (shape wise). (In hindsight I think the Mars colony is very poorly laid out and ignores the topography of the land entirely 😬)
At this point, the core functionality supporting multiple worlds with colonies worked, and I could have these three colonies but I needed to add a way for the player to move between the colonies.
Enter the solar system view. As I mentioned above I’d been watching and thoroughly enjoying The Expanse™, and one wonderfull thing I saw in a number of episodes was this holographic, interactive rendering of the solar system, showing the trajectories of planetoids (and in this case, spacecraft). Here is one example from Season 1, episode 6:
I wanted something like this. And I wanted, when a player chose to shift focus to a colony on another planetoid (at this time, Earth, Luna or Mars), the camera to be manipulated so that it looked as if the player were in a spacecraft, and that spacecraft would complete a partial orbit, turn to face the destination and then travel there.
This video shows what I was aiming for in this. It’s rough, based on a very early attempt at the animation.
I spent what seems now, a ridiculous amount of time (months) obsessing on getting this animation working. In the end, it beat me. I could not get it to work the way I wanted it to.
What I’d wanted in my I-am-not-a-pilot-or-astronaut position, was to compute the orbit position on the current planetoid that is closest to the destination planetoid, travel in-orbit to that, turning at that point to face the destination, and then travel to the destination, keeping in mind that it is moving in space as the spacecraft moves (so in essence, travelling to where it will be when my spacecraft is due to arrive). To this day, I’m still not sure where I went wrong.
The code is still there inside the current version of World of Hex; it’s just not enabled anymore. Apart from the problems I had getting it to work (so, so many variables), it also became obvious that if the player just wants to move from, say, Earth to Mars, the transition, whilst nice, would probably end up taking too long, and the player would just find it boring.
Below is a snippet of what it looks like when I re-enable that code within the current baseline.
At this point, being heavily inspired by The Expanse™ I started to think about adding more colonies. That also meant adding moons. Then of course in The Expanse there are also colonies on some of the larger asteroids.
This presented a problem for me. The Keplerian elements are great, and the implementation was remarkably easy given some hard work by people much smarter than I am, but you can’t use the same mechanism for some of the moons or for the asteroids. I couldn’t find data for them until I arrived at the realisation, with some advice from my online friends at StackExchange, in this case the Astronomy StackExchange.
I ended up in communication with the kind people at NAIF and one particular person from the Astronomy StackExchange, who gave me some advice and guidance on what I needed to do to get the information I needed from their CSPICE library. This required that I port their library (which itself is a conversion of the original Fortran into C) to compile and be usable on iOS and macOS. macOS was easy, but I found that the library assumed that files that it reads are in the “current directory” which is not going to be the case on an iPhone or iPad. So I went through the process of adding a wrapper to the library, and adding a way to tell CSPICE where to look for any files it needs to access.
This all worked a treat, and I was also able to get their TSPICE library of unit tests running, allowing me to validate what I’d done.
I’ve since been given the OK by the people at NAIF to make the GIT repo’s for both public:
With CSPICE in place and working, my next problem was that the data required to feed into CSPICE to provide the paths of all of the planets, moons and asteroids was bigger than I could reasonably load into memory.
As mentioned in my stack exchange query, I then used the SPKMERGE tool to generate ephemeris files that contained just the data I needed for my app. The app then loads those files via CSPICE and generates the positional data it needs. The data currently built into the app should be good till 2050. If World of Hex is still running by then, then I’m afraid it will probably be someone else updating the data files.
At this point, the solar system managed by World of Hex now comprised (with colonies on those with a ⬢):
- Earth ⬢
- Luna ⬢
- Mars ⬢
- Io ⬢
- Europa ⬢
- Ganymede ⬢
- Callisto ⬢
- Titan ⬢
- Ceres ⬢
- Pallas ⬢
It’s worth mentioning here that both Phobos and Deimos, moons of Mars move so fast that it became too difficult to keep the camera focused on them, so, apart from the Sun itself, these two planetoids are the only two you can see, but not visit.
Textures and visualisations
Another thing to consider, now that I had positional data, was providing textures for each of the planetoid bodies. For this, initially, I relied heavily on a website called Solar System Scope. (Incidentally, this really is a terrific resource, and it gave me some inspiration at well). From here I was able to obtain high quality textures for most planets, and for those I could not get, I sourced from sos.noaa.gov, or from artists who contributed to the Celestia project. Credits are all provided in the game on the credits screen (if you can find it…)
For the two asteroids, Ceres and Pallas I confess to cheating and just treating them as spheres so that I could use Hexaspheres to represent their colonies.
The Great Conjunction
Back on the 22nd of October, 2020 I was able to record The Great Conjunction, the lining up of Saturn, Jupiter and Earth from within World of Hex, showing that my use and implementation of the SPICE libraries had worked. Here is a short recording I shared with the folk at NAIF:
Scale; the art of fitting an entire solar system onto a screen.
One of the things I had to wrestle with was how to deal with the vast distances that the planets, and especially, the asteroids and Dwarf Planet Pluto travel, and still be able to show more than just a dot for the inner planets.
If you look at most implementations, and Solar System Scope is no exception, it’s impossible to fit it all on a single screen, whether it’s an iPhone or a 42″ TV.
So whilst World of Hex correctly computes everything, the representation is all scaled in post processing of the computed positional data so that:
- You can see everything within reason; and
- It is still a reasonable representation of the distances.
In addition to scaling the distances, I also took the step to scale the size of the planetoids, and this scaling changes between when you’re in normal play mode, focused on one planetoid, and when you’re in the solar system view mode. When in solar system view mode, the scale of both the distances, and the sizes is dynamically recomputed so as to make the solar system easily navigable.
This gave me an approximation of what I’d seen on The Expanse™ that I was happy with.
Now, if our iPhones or iPads had a 3D holographic projector that could place the solar system all around us as seen in The Expanse™ I’d be looking at how to make that happen…
So what’s going on now?
I’ve written this (rather long and rambling) post because I’ve been working on some changes to the game as part of a push to improve it’s presentation, perhaps open it up to more players, etc. I’ve just finished a 2 month effort to create the first large update since bringing the game to macOS back in August 2020. The update notes for v4.2 are longer than I ever intended them to be.
I initially intended “simply” to add portrait mode to the iPhone. As part of doing that, one thing I’d needed to fix was how I put text on the screen.
When I originally developed World of Hex, the SKLabelNode, part of SpriteKit, did not support Attributed text (text that can change style) so I’d built a way to do this that worked, but not well.
Apple have kindly added native support for Attributed text in the meantime, so I’ve moved to using that, and an entirely different method of creating that Attributed text for display via a wonderful library of code called SwiftRichString. My expectation now is that I will be able to add support for more languages, thus widening the audience of the game.
The full update notes for version 4.2 are listed below:
- World of Hex is starting a new phase of enhancement, and to kick this off, the way text is displayed on the screen has been improved, so if you’ve seen a partial message, or been confused about something, perhaps this will help.
- On iPhone and iPad, support for Portrait mode has been added, at last! Yes, you can now play World of Hex one-handed on your iPhone or iPad whilst standing on the train commute to work. With this rather large change a number of related bugs have been fixed that have been plaguing players for a while now.
- New users are now introduced to their AI module right from the get go, so that they know there is more to the game to build towards. Did you know that you can program your own AI with commands to defend the world tiles you win? No? Well all you need to do is reach level 2, and access will be granted!
- The leader board now displays a more information about how well those players at the top have been doing.
- For those of you that have noticed that the Earth seemed to get confused about just where the Sun actually is, and turned the wrong face to the Sun, I believe I have finally fixed this. It won’t affect play at all, but it affects my sanity. So this way I get some peace of mind too.
- Finally, finally, World of Hex no longer stops your favourite music from playing when you launch the game! I’m sorry this one has taken so long.
- Panning a world on macOS now works as nicely as it does on iOS, iPadOS and tvOS. And it’s even nicer on those too!
- The player information panel now shows a small meter to indicate to you how much more you need to play before reaching the next level.
- Experience points (XP) can be earned faster now with the addition of a “win multiplier” for each world tile. If you, or someone from the same faction keeps winning consecutive games in a given world tile, then XP are earned much faster.
- On macOS, panning to rotate the selected planet or moon using two fingers now works as smooth as silk (finally).
- Fixed a number of nasty memory leaks and buggos.
- Fixed a problem where the colour of a tile was not changing after you win a game. This bug was introduced back when I added the Game Center Achievements. My apologies; it’s fixed again.
- A note for the wary. Apparently, if you force kill World of Hex, iCloud can get it’s knickers in a knot and stop sending the app the background notifications that allows it to keep the state of the world tiles up to date. If you’ve done this, and think the tiles are not accurate, then the only way to fix it (apparently) is to reboot the phone. Not my preferred advice to anyone but it’s all I got. I spent quite some time trying to work out if I’d done something wrong, but no…
- On the Apple TV, something special, well I think so. You can now zoom in and out in little bits.
And where to next?
Now that v4.2 is out there, the current roadmap of things I want to do are:
- Allow it to be played offline (which is needed for an Arcade title I understand).
Add portrait mode on iPhone.
- Add localisations to the game to make it more accessible to non-English speaking players.
- Add accessibility to the game.
- Add controller support, especially for tvOS.
- Add more visual polish and eye-candy.
- Add more moons and asteroids.
- For fans of The Expanse™ add a pocket universe and allow the Ring Gate to be activated.
- Add an Easter egg or two. There is already one (the credits scene) if you can find it.
I call this a roadmap which implies some sort of order. As you can see, the order means little. Some items are easy enough to do, though cost money (and believe me, this game does NOT pay it’s way) because I need to pay others for things like translations.
If you’ve made it this far, thanks for reading. I hope it wasn’t too hard to follow.