Introduction

A little over three years ago, I had an idea - wouldn’t it be fun to have a whole procedurally generated universe on my phone, and have an open game where I can explore parts of it with no combat? This post describes some of the design decisions that I went through to start turning this idea into reality, and some of the consequences of those decisions.

I’m writing this post three years after the design process, and while it is easy to find out what the available options would be now, it is sometimes a little difficult to determine what the state of a particular software package or license was at the time, particularly as most web content is undated. If I had thought I was going to write this, having some documentation three years ago would have been useful. Also, this post is going to make the process sound more linear than it really was.

In particular, I chose not to use one of the standard game engines, and went with C++ for the language, Vulkan for the Graphics API, and Dear ImGui for the user interface. I think these decisions were largely correct for this application at the time, but this example is somewhat exceptional, in that an engine would usually be the right choice.

There have been changes in the last three years - in particular, Rust has matured to the point where it might be a better choice of implementation language, and I’m seriously considering porting the 34K lines of C++ code that I have to Rust.

Recent builds of the Galaxy Generator for Android, Linux and Windows can be downloaded here. This screenshot is from a development version a little ahead of the last release (open in new tab to enlarge).

Screenshot inside a galaxy showing star details!

Contents

What Already Exists

When writing software, it is good to have a look around and see what already exists. If something similar exists to what I am planning to do, that’s something I want to be using, or maybe contributing to if there is a possibility of that. It doesn’t mean I won’t write my own, but I wouldn’t want to be blindsided thinking that I’ve produced something unique when I haven’t. This is a quick survey of what I found:

Space Engine

Space Engine is a mature, visually stunning Universe simulator for PC. I have not tested this (the graphics card on my computer is inadequate), but there doesn’t appear to be any game play - it is an exploration sandbox. Also, they specifically rule out developing for Android and iOS as theoretically impossible (which at their level of detail probably is).

Elite Dangerous

Elite Dangerous is an open space flight simulation game set in a 400 billion star system galaxy. It however has a large combat component, and is also online only (there was going to be an offline mode, but they abandoned that). I like games that I can have around for a long time and play years later, so I avoid games that can’t be played offline. It is available on several platforms, none of them mobile.

No Man’s Sky

No Man’s Sky is an action-adventure exploration and survival game set in what they describe as an “infinite procedurally generated galaxy”. It has had some very good reviews, particularly as they keep adding more content. It has a larger combat component than I’d like, and is available on several platforms, none of them mobile.

Kerbal Space Program

I can’t recommend Kerbal Space Program highly enough - I’ve played it a lot, and it would be hard to surpass as a fun solar system (or Kerbol System in this case) exploration game. It’s not quite as visually detailed as the other games, but it has a lot of depth, plays offline on pretty low-end hardware and doesn’t have combat. It doesn’t allow interstellar travel (although there are mods for this), and doesn’t have the huge scope that I’m after. Unlike many other games, it works well on Linux. It doesn’t have a mobile version. I was looking forward to Kerbal Space Progam 2, but it seems that their development team has been laid off with the game really incomplete and resource hungry. This looks like an example of Second System Effect as described by Fred Brooks in the Mythical Man-Month (which everyone involved in any capacity with software engineering should read).

What is on Android

All the above options are desktop and/or console only. I do occasionally perform some searches in the Android Play Store to see if there is anything like what I’m trying to do, and while I have found some visually very nice space games, they are combat focused and don’t have anything like scope that I’m looking for.

The Task

None of the above options really offered what I wanted, so the next step was to write my own. This will be a solo project and doesn’t have any commercial aspect or backing (I seriously doubt that my first game attempt is going to be something I can successfully sell), so there are a few things I am looking for in the tools I use:

  • I want them to allow writing performant code. Part of what I enjoy is optimizing code, and I’ll always find problems (or in this case turn it into a problem) where that is necessary. In this case, I decided that I wanted to be able to dynamically move through a star field, displaying an ever changing million or so stars at a time.

  • I want to learn new tools and techniques. I don’t have a deadline, so I can take the time to learn things.

  • I want something reasonably mature and stable. Nothing kills a personal project like stumbling into some showstopper bug in the tools I am using, and any help is going to be from strangers online, either by finding what they have written or asking in forums, as I have no collaborators on this project. If I get too esoteric (as a hypothetical: “so, this thing with Haskell and Vulkan isn’t working on older Androids …”), that help just might not be there.

  • Conciseness of code is important for maintainability - there is only so much that a solo developer can keep track of, a notable exception being Dwarf Fortress.

  • I want the application to run on relatively low end hardware. This includes graphics cards with single precision floating point. It also must not be very memory hungry - no more than 1-2 GB for total running memory.

  • I will probably end up wanting to use the processor vector intrinsics, as I frequently find that they help with real performance boosts in critical areas – it turned out these are useful for fast star generation. This is not a must-have, but it is strongly preferred.

Licensing - to Open Source or not to Open Source

For a library, tool, or productivity app where there is general agreement on the goal, the advantages of open sourcing are clear - other people have the opportunity to make improvements, pick up the project if it gets abandoned by the author, and even a fork can help the goal of having the functionality available.

My first impulse was to open source this - it is a personal project, not something I’m ever likely to try and make money off, and I like sharing ideas. However, the advantages of open sourcing a game that is going to evolve as it is developed are not so clear. This was a decision that I had to make early, as it affected other decisions.

When code is open sourced, there are several possibilities:

  • There is so much open source software out there (of varying quality) that the most likely case is that unless the application is a real success, the code sits there unnoticed and unused, except for being used to train such things as GitHub Copilot where there is a chance that a portion of the code gets used elsewhere and is unattributed.

  • It attracts one or more interested people who want to make contributions. This is great for generating interest and bug fixes, but runs the risk of someone trying to take it in a direction that I don’t want - for instance, I really don’t want combat, and wouldn’t want someone to put a lot of effort into developing a combat system, then have me spend energy arguing with them about it. There is a risk that the direction goes somewhere I don’t want if a contributor has more time to put in than I do. It it worth noting that many of the open source games are either small in scope, or strongly based on existing games. Freeciv is an example of this.

  • Someone forks the project, either being an originally benign contributor who doesn’t like their pull requests being not being merged, or some bad actor that wants to use my work and not give back. This second case can theoretically be prevented by using something like the GNU Public License, but then I’ve got to find out about it, and be prepared to sue to enforce the license, which is an expensive and time consuming business. There are plenty of stories in the gaming industry (and elsewhere) of rapacious behavior, sometimes from companies with deep pockets.

Overall, there appears little to be gained by open sourcing a game in its early stages, I have open sourced some libraries that I wrote that I think may be useful: Pseudo Double and Random Variate Poisson. If for whatever reason I decide to abandon this project I intend to open source everything, probably under the latest version of the GPL (GNU General Public License). For now it stays closed source.

Platforms

Before picking what engine to use (or not), I needed to decide what platforms to support as I didn’t want an engine, language or library choice to lock me out of a platform I want to support. I ended up choosing Android, Linux and Microsoft Windows for the reasons given below.

Android

This one is easy - my original vision was “universe on a phone” and my phone happens to be an Android. Android Studio is a real resource hog though, which makes it nearly unusable on lower end machines, so I want to spend as little time there as possible. It may be possible to develop for Android using entirely command line tools that would avoid Android Studio, but I don’t yet know how to do that (update: I have discovered how to do that in Rust), and I suspect that some of the command line tools are culprits in the resource hog problem. I need another platform with better tools to do most of the development and testing on.

Linux

I run Debian Linux on my main machine. I am familiar with developing on it, and am very experienced with such tools as gdb and valgrind. I want to use this for development, so I might as well generate a release from it. This is the version that has had the most testing and is going to be the most stable.

Microsoft Windows

This came later in the development process, and didn’t affect my choice of language and tools (I’d already decided to use Vulkan and C++), but after the first build I wanted to share, nearly everyone that I asked to playtest this said “Windows” when I asked whether they wanted the Linux or the Android version. Given that I already supported Android and Linux, a few more #ifdefs didn’t seem like a disaster.

There are two obvious ways of porting C++ software from Linux software to Microsoft Windows:

  • Use Mingw-w64 to cross compile for Microsoft Windows on Linux, That is very easy to do, but does require that a couple of libraries be shipped with the game.

  • Use Visual Studio natively on Microsoft Windows. I had add some #ifdefs and do some code cleanup, but code that compiles without warnings on multiple compilers is going to be more robust. The port took me a few days, with the biggest headaches being an internal compiler error, and Visual C++ not supporting 128 bit integers that I use quite a bit.

I did both, but I think the Visual Studio build is cleaner (fewer extra libraries), so that’s the one that I’m releasing.

macOS and iOS

I’m not targeting macOS and iOS for now. This is not hardware I have easy access too. Also, you have to pay a subscription for development tools, and they tend to be a “walled garden” for software development, in that Apple makes you follow a lot of rules and jump through a lot of hoops to release anything. The problem with a wall is that you get to only be on one side of it. Three platforms is enough for now.

Frameworks/Engines

Conventional wisdom in gaming circles is to always use an existing game engine. There are two reasons not to do this:

  • if you are doing something extraordinary that isn’t best managed inside an engine,

  • you want to write an engine more than you want to write a game.

I think that this project qualifies on both of those. I love writing engines (that has so far been the focus of my career) as that involves solving performance and constraint issues that I enjoy, so I get more joy out of this by writing stuff for myself, even if it takes longer. If this was a project with a budget and timelines, an engine would make a lot more sense, but I don’t have those.

As for the extraordinary, there are two levels to this - what I need and what I don’t.

What I need: For procedural generation and rendering, I’m trying to deal with a lot of stars (millions at a time out of 400 billion total) in a limited amount of memory, so I need to keep tight control over the management of this, as I describe in Memory Management.

I don’t need a lot of the infrastructure that engines provide - I’m not going to need any physics models apart from the one that I write, don’t need collision detection (space is so large that I’m going to treat spacecraft as points, so the only collision effects I’m going to bother with are with astronomical objects, which are all close enough to spheres), lighting or gravity effects.

Having said all that, it is more useful to have a tool available than not have it (even if I don’t use all of it), so it was important to investigate what the main options were, knowing in advance that I didn’t need to use one. Here is a survey of what I considered:

Unity

Unity is very popular amongst game developers. The license is good - Unity Personal can be used for projects with revenue of less than $200,000 ($100,000 when I looked three years ago). It supports a lot of platforms, certainly all those that I’d be interested in. However, the main supported language with Unity is C# (other languages like C++ are supported, I’m just not sure how well, and tools can be very frustrating to learn and get help with if you are not using the preferred language binding), and I had a concern that C# might not be performant enough. I would have no trouble learning C#, but learning a new language and a new platform with unknown performance characteristics seemed like a large investment with uncertain return - I might not find it was a blind alley until a few months in. Also, I was already leaning towards Vulkan over OpenGL, and some (as it turns out, way out of date) documentation suggested that only OpenGL was supported.

This came later and didn’t affect my choices, but in September of 2023 they made some large changes to their licensing terms. There was an outcry and this was quickly reversed, but that does highlight the dangers of relying on a commercial closed source provider for infrastructure that you can’t easily replace.

Unreal Engine

Unreal Engine is a very powerful engine, with C++ as the language used, has available source code, and very good licensing terms for free games - the royalty is 5% of gross, with the first $1,000,000 of gross revenue exempt. However, Unreal is huge and known to not be particularly well documented, is historically set up for first person shooter games (although that emphasis has become less with later versions), and requires a lot of memory to use. My computer was too underpowered to run the Unreal Engine, and I would have needed a new machine. My reading also suggests that Unreal produces bloated binaries, and I want my software to be lightweight.

Unreal Engine might be worth another look once I get a more powerful machine.

Godot

At the time I was looking into this, Godot didn’t support Android. Android support was around the corner, but I didn’t know that and wasn’t going to wait.

My brief perusal of Godot indicates that it’s not really designed for the heavy lifting that I wanted to do anyway.

Languages

I’m a believer in picking the right tool for the job, rather than just using a tool because I happen to know it (although that is a consideration when time constraints are a factor). This is the list of programming languages that I considered.

Java

Java seemed the natural choice for this - Java and Kotlin are by far the best supported languages on Android, and Java will also run on Linux and Microsoft Windows, as cross-platform functionality is part of the Java design.

I was however concerned about performance, so I took a number crunchy algorithm (to do with planet generation) that I intend to use in the project, implemented it in Java, and it was way too slow. I implemented the same algorithm in C++ and it was much faster.

At the time, Java also didn’t support vector intrinsics support. Java later added a vector intrinsics API in Java 19 (for x86-64 anyway, not sure if that includes ARM Neon), which was released in September 2022.

Java would have been the easiest for Android development, but didn’t look like it was going to have the performance that I was going to want.

C++

C++ is a large, powerful language, well-supported across-platforms. The biggest disadvantages are that it make it really easy to shoot yourself in the foot, requires jumping through extra hoops to use it for Android development (just about all the online help for Android development is for Java or Kotlin), and I was already using it extensively for my day job. Why is this last one a disadvantage? Part of the freedom of a personal project is the opportunity to learn something new, and it also makes a good change of pace to have any coding in my spare time done in a different language to what I’m using during the day.

I couldn’t find any other language that had the support and performance that I needed, so C++ was the choice that I went with.

C

C is mostly a subset of C++. The only reasons to use C rather than C++ are if the compiler support is not there for C++ (not applicable in this case - C++ is well supported) or as a way of enforcing not to use C++ idioms, which only matters if there is a team of developers. C++ is a better choice than C in my case.

C#

The main reason to use C# would be if I was using the Unity framework. I didn’t run any benchmarks myself, but what I’ve seen online suggests that it is generally a little faster than Java, but significantly slower than Rust, C or C++, so as I described in the Unity section, I decided not to go this direction.

C# does support vector intrinsics for both x86-64 (in .NET Core 3.0, released 2019) and ARM Neon (in .NET 5.0, released in November 2020).

Rust

I really, really wanted to use Rust, as I find Rust a very appealing language. I like speed and safety and Rust is one of the few languages that realistically offers both, so it is a top contender for any new projects. However, at the time that I was considering it, Rust Android development didn’t look baked enough to use. Also, vector intrinsics were supported for x86-64, but were not stable for ARM Neon. It just didn’t seem ready.

This has now changed, and I’m considering porting the project to Rust, using vulkano for the graphics driver and egui for the UI. There are some issues that suggest that the Rust ecosystem is still maturing, but I’ll learn more as I investigate.

Haskell

Haskell wasn’t something that I really considered, but I’m listing it here as pure functional programming is a safe, powerful paradigm that often gets overlooked. It is very high level, which makes it generally the fastest paradigm for development (it is for me anyway), but it has never really become mainstream for most applications. I suspect it has a chicken and egg problem with not being as popular and not have as good library support as other languages creating a negative feedback loop. Functional language programming is also perceived as hard to learn for people with an imperative background.

This application was going to require high performance and carefully managed memory, and I don’t know how to do those in Haskell (or even if they are possible). There are people developing for Android using Haskell, and Haskell does have a Vulkan binding, but this does seem a little too off-piste - the chances of running into a showstopper and not being able to find help is way too high.

Graphics Libraries

To use a GPU, it is necessary to use a graphics library. I came into this not being familiar with any of the libraries, so I was going to have to learn whichever library I chose. I wanted something that supports Android and Linux, so DirectX (Microsoft Windows) and Metal (macOS) aren’t options. That leaves OpenGL and Vulkan as the cross-platform libraries.

OpenGL

OpenGL (OpenGL ES for mobile) is well supported and in very wide use. However it as not as fast or efficient as more modern libraries such as Vulkan, and doesn’t provide as much control over the GPU pipeline. It is an aging technology, and my reading suggests that it carries a lot of baggage from earlier versions and trying to keep things simple to use.

Vulkan

Vulkan is much lower level than OpenGL, and has a much steeper learning curve because it makes you deal with all the details - even the ‘draw a triangle’ tutorial is hundreds of lines of code, setting up many many required structures. This very much suits my style of doing things - I want access to as many levers as possible to let me write performant code. There have been cases where I use a library that is higher level than I prefer, and end up fighting it when I want to do something that was kept under the hood because the library writer didn’t anticipate someone wanting direct access. For me, Vulkan was a clear choice over OpenGL.

User Interface

A game is going to require a GUI, and this is going to require either some sort of library to provide all the widgets (menus, buttons, combo boxes, etc.), or an API provided by the platform.

Qt

The first option that I looked at was Qt. It is powerful and mature tool for creating cross-platform graphics user interfaces, supports all the platforms I want, has choices for what graphics binding to use, and I’ve used it before. What is there not to like? The license options. My reading of it as there are two options:

  • Pay for a license. On the website now, it lists either 999 Euro or 499 Euro per year (I’m not quite sure which is applicable, I think 499 Euro), but when I looked at the start of this project, I don’t remember seeing an option for less than several hundred dollars a month, which is small change for an established studio, way out of budget for a solo developer. Even 499 Euro per year is more than I want to pay for a project I’m working on at my own pace.

  • Use the free Qt Community Edition. This would require me to meet LGPL (GNU Lesser General Public License) obligations. Android is a bit complicated with LGPL as you have to provide a way of swapping out the LGPL code. The easy way of dealing with this is to release my code under the GPL, but I’d already decided not to do that. Otherwise the road map for making sure that I follow the license is not completely clear. I didn’t want to start my development journey with visiting a lawyer, and certainly don’t want to end it with lawyers.

The cost or possibly onerous licensing conditions means I reluctantly had to look elsewhere.

Native

By far the best user experience is going to be to use the native GUI API provided by the platform. Windows has such an API, so does Android, whereas Linux does not have a preferred GUI API, although there are lots to choose from.

This incurs a large development overhead, as all these APIs are hugely different and they all need to be built and tested separately. Multiple GUI APIs is one of the reasons that MVC (Model-View-Controller) is a design pattern that is generally preferred for games, as the GUI code then all exists in the view. MVC helps, but still means that each version of the interface needs to be debugged.

For a solo project, having to support two separate interfaces is way too much work, particularly as on Android it would involve lots of calls from C++ to Java, so I was looking for a cross-platform GUI library.

Apple applications are way more standardized about look and feel, so if I had chosen to write macOS or iOS versions, I’d be having to use either Qt or the native versions right away.

Dear ImGui

There is only one well supported free cross-platform (including Android) GUI library for C++ that I could find - Dear ImGui. It is an immediate mode GUI, so it gets redrawn every frame, and it designed for debug tools rather than a user interface for the end user, so it is less polished than an interface would be designed for the end user would be. However, it works well, is open source, well written and easy to use and modify. I went with this as this is at least a very good placeholder.

Challenges

So far I’ve encountered some challenges. I describe some of them, and indicate whether a game engine would have been helpful in overcoming them.

Project scope

It is conventional wisdom in game design to start with small games, because the first few games will be bad and you don’t want to invest a lot of time in things that you are going to throw away. An alternative view is to just run with your passion, and I like that view so much more. Starting small is a little tricky when the vision for what I want has so much scope, but I have scoped things down a little. I’m also an experienced software developer, so I’m not going into this blindly.

  • I’m only doing one galaxy instead of a whole universe, but making sure that the design will support expanding this later. That is plenty of room to explore to start with, and more galaxies would largely be a visual backdrop until it is possible to cross really vast distances.

  • I’m not dealing with binary stars in the first cut, as that makes star generation a lot more complicated. Part of the problem is that binary stars really need to rotate around each other, so the star generation would have to deal with moving rather than the static stars that I can get away with for something set over a small time scale.

  • There are no dust clouds yet. This would involve volume rendering, which is its own topic I will need to spend some time on when I want them, and I can make a perfectly playable (if less visually appealing) game without them.

One very good way of scoping things down would have been to start with a single solar system, which would also be more amenable to use of a game engine. That wouldn’t give the feel that I want, and would risk looking like a small subset of Kerbal Space Program, and I don’t really want there to be a too obvious a comparison between what I write and some other project that is much better resourced.

Multi-Platform

I’m currently developing for three platforms in parallel with the same code base, so there are a considerable number of #ifdefs in the code. Using a game engine would certainly have reduced but not eliminated them - desktop and Android have quite different input and output characteristics, vector intrinsics are processor family dependent, and Visual C++ does not support 128 bit integers (g++ and clang++ both do), so there is some special casing to deal with that.

Cross-Platform Floating Point

One of the properties of procedural generation is that it can very sensitive to any changes. In particular it is important that the same calculation returns exactly the same answer every time. I wanted my saved games to work cross-platform (and maybe one day a multiplayer version where the same seed generates exactly the same galaxy). This needed to work for x86-64 and ARMv8. However, floating point calculations make no cross-platform guarantees. I assumed that this was a common enough problem that there were some compilation flags that could be used, or some other industry best practice such as a particular library. The closest answer I got was to use fixed point. Unfortunately, the numbers in astronomical calculations vary so widely that fixed point would be an incredible headache, as the coding would involve carefully keeping track of what scale everything was at, and I would be forever debugging overflows. I thought there might be some sort of cross-platform soft floating point library that I could use, but everything I found was either really heavyweight and implemented all of the IEEE-754 standard, or very lightweight and only supporting single precision and only a small number of the transcendental functions. My solution was to write PseudoDouble, a relatively lightweight library that implements high precision (48 bits mantissa, 16 bits exponent, and this is configurable) using only integer instructions. I did something similar for Poisson Random Variates, which I wrote about in Poisson Random Variates for Procedural Generation.

None of the game engines would have saved me from this particular diversion.

Memory Management

The Galaxy that I’m generating contains approximately 400 billion stars. Clearly that will never fit in memory at once, so there has to be a mechanism for only generating and storing the regions that have visible stars, and purging the regions that have been left. The normal way of doing this is using an Octree and only storing certain branches. I want to have the point of view move rapidly, which means that new branches need to be added and old branches removed as I explore in Efficient Octree Storage and Traversal. It turns out that in some cases, the pruning needs to be quite aggressive. I also had to pay close attention to the CPU to GPU Pipeline.

This is all carefully written code, which could not be left to a generic engine to handle. A side note - one of the ways that they handled some of these issues in Elite Dangerous was to limit visibility and therefore rendering range by adding more space dust. I don’t do that (I don’t have dust at all yet), so a very bright star a long way away still needs to be visible.

Persistent Storage

At some point every non-trivial game needs to save its state. There are lots of formats for this - various text formats such as XML, JSON, YAML or TOML. There are also binary formats, such as BSON, something based on Google Protocol Buffers, serialization that some languages support, or something hand-rolled.

I decided I want a binary format, as it will be more compact when there is lots of state to save, such as attaching user state to lots of stars. I experimented briefly with Google Protocol Buffers, but the flexibility of that comes with some overhead that I don’t want, and I quickly realized that for me, hand-rolled was the way to go. I wouldn’t generally suggest this unless you enjoy looking at hex dumps while debugging. I’ve been dealing with custom binary file formats, including handling multiple versions, for years as part of my day job, so I have lots of experience, and I found that in this case tools that try and help were instead just getting in the way.

My understanding is that game engines offer support for this, but it’s not a particularly big problem anyway (for me). There might come a time when there is too much state to save it in a single file. When that happens, I’ll need to break up the save file into pieces, which may be a lot more effort.

Challenges Yet to Overcome

These are some of the challenges that I’m anticipating, and haven’t really dealt with yet.

Controls

At the moment, the controls are pretty rudimentary - I have arrow buttons that work on desktop and Android, and key bindings for desktop. This will need to be built out, and will require some coding that an engine might have been considerable help with.

Artwork

Artwork at some level is something that any game needs. I’ve avoided it so far by using procedural generation, but I will eventually need some. I don’t have the budget to adequately compensate a professional, and I will not work around that by using an AI art generator, as they have been trained on the output of artists, generally without their consent. That leaves finding some free or cheap assets somewhere, or building my own. I’m intending to use a simple style with line drawings where I can.

An engine won’t offer artwork, but will help display it. Given that I’m tending towards the simple small end (there aren’t going to be any non-procedural animations or video cut-scenes for instance), the tools that I already have for display should be quite adequate.

Sound Effects and Music

I play all my games with the music turned off, and often the sound effects as well. I seem to be in a small minority here - it seems to be a nearly universal opinion that games need sound effects and music. I can work my way around most of the sound effects because there is no sound in space (the movie 2001: A Space Odyssey got this right), but I may need some, and that doesn’t get me out of providing music. As with the artwork, I will be looking for free or cheap assets for this. I listen to lots of Beethoven, Tchaikovsky and Mozart as I code.

An engine would have tools for playing sound built in. I will need to find some library (or libraries if I can’t find anything cross-platform) to deal with this.

Multiplayer

It has been pointed out to me that this setting would be great for a massively multiplayer online game. If I ever get to this, I would make it fully cooperative, as there is plenty of room for everyone. However, there are some impediments to this (in no particular order):

  • So many games are written and released that it is hard for an indie game to find an audience. A small player base is fine for a single player game, and it can maybe grow slowly over time, but games that rely on interaction will have new players trickle in one at a time, discover there is no one else there, then leave. My game would have a small advantage there - a galaxy is an enormous sparse place with one player in it, but it would also be an enormous sparse place with 10,000 players in it, so it might be OK that it takes a while to encounter others.

  • Balancing a multiplayer game is much harder than balancing a single player game. If there is an imbalance in a single player game, or exploit that speeds up progress more than expected, that only affects the people who find it and who they tell, and can be fixed in a later version. With a multiplayer game, it gives some people an advantage that you have to either leave them with or take away - a Eternal Lands’ MMORPG Postmortem includes examples of this.

  • Dealing with bad actors - griefers, people who look for exploits or try and hack the client, people who try and attack the server. It is hard to design something robust to all of that, and time would need to be spent policing it. One of my favorite mobile games, Hades’ Star, is designed to avoid griefing in its cooperative modes, but even then, the game has been modified several times to counter griefing exploits that were discovered.

  • Writing and debugging distributed code is much much harder than writing code for a single machine. The engines help with this, and there will be standalone libraries too. This is not something I’d want to design from scratch.

Conclusion

I had an idea for a game, and after investigating several options, decided not to base it on a game engine, instead using C++, Vulkan and Dear ImGui. These choices have been a success in that I have a basic engine running (somewhat scoped down from my initial idea) that I have enjoyed writing, and development is ongoing. However I’m three years in (only part time, as this is a personal project), and have only recently started on the game play. Using a game engine would have got me to game play much faster, but possibly not got me something I would be as happy with.

I am seriously considering a port to Rust, as I think it would be more scalable as I expand the project. I’m still investigating that option.

Unless you really like writing engines, if you are writing a game, base it one one of the existing engines.

Any comments, corrections or observations? Please feel free to contact me