What's on the docket?
The beginnings of something (maybe) great.
So, in short, I've got three main things going on:
- The Create Academy
- Project Ponder
- Project Flagship
The Create Academy
The Create Academy is already up an running, so not going to go into too much detail about it here. While not my project, I've been a major contributor in its now third iteration and has just been fun to work on.
Can read more about it on the Create Academy Website (which is of my design!) if you're interested. In short, it's a Minecraft (Java Edition) Modded SMP Server mainly focused around the Create Mod.
Project Ponder
Project Ponder is an unannounced project I've been invited as a founding member. It's still very much in its "throw random ideas at the wall and see what sticks" stage and things are still kinda under wraps, but I'll be sharing more details here in the not-too-distant-future as it becomes reasonable to do so.
Project Flagship
A real flagship product, isn't it?
Now, this one is interesting. This project is in-fact a solo project and will be my main focus (until Ponder kicks off and eats some of my time), and, unlike the other two, I will be sharing more details here! In fact, it is likely to become the major topic of discussion for the next little while.
So, uh, what is it?
It's a Game!
You just lost it. You're welcome.
I've been wanting to actually make my own video game for a while, so I'm gonna. Given I've got a bit of a nasty habit of starting projects then promptly abandoning them, my hope is that in documenting the process, things will be a bit more cohesive and I'll actually stick to this one. Not to say I didn't learn anything from all those little experiments, though, and that knowledge will prove valuable here.
"Flagship" is only a working title for now: the whole project is still in its infancy as a random collection of concept notes, thoughts, and experimental blobs of code. I've not even drafted a proper design document yet (I know, I know, I'll get to it), but that's mostly in-part that I haven't nailed down the finer details yet and will only be sharing them as I do.
As for the more "coarse" details, though, that much I know. The idea right now is which sits firmly in the "colony-management" genre, inspired by the likes of RimWorld, Prison Architect, and, of all things, Starbound. That last one's gonna come up a lot, too, even though it's the only non-colony-management one of the three; more on why later.
Design Goals
Design-driven design-oriented design.
Besides the obvious, there are some more particular design goals I want to hit with this. I realize these might be a bit lofty for what appears to be a "first" project, but this ain't my first rodeo and I don't want to just make anything. I have standards.
That said, these goals are, in order of importance:
Be Extensible
This is probably the top priority: in my opinion, user-generated content (i.e. mods) is by far the most effective way of creating community within a game (especially a single-player game) and increasing both playtime and longevity. For any game and its community to remain healthy, it must be extensible. So, to achieve this, I want this game to be as "extensible" as possible. What do I mean by that? In short, I want to make sure that not only are the tools for users to extend the game to create new content readily available, but that the game itself is designed such that it does not get in the way.
To achieve the prior, proper APIs are in order. Some games already do this in their own way (a la RimWorld and Starbound), while others have community made-projects which serve a similar function. To me, though, this is less important at the start as these can kinda be "grown in" as the game grows. What matters more, in my opinion, is that the game's design isn't an active deterrent to extending it.
The biggest among that is language choice: C# and Java are languages that are very easy to modify, making them fantastic for games which don't place the utmost priority on performance, as they're a bit slower than their native C/Rust/Go/etc cousins. Games like Starbound and Factorio get around this by basically introducing an entire Lua scripting engine into the game, but now the game treats user content and its own content unfairly and any performance benefits of using a native language are promptly lost on Lua or the like. Stellaris even goes so far as to write its own custom half-scripting-half-markup language, but it suffers from the same issue and just sounds like a horror to maintain.
Besides language, too, there are design considerations within the code itself. Certain elements are just much harder to manipulate than others, compilers and source generators can do some really strange and unexpected things sometimes, and sometimes systems are just built in a way that is just very hard to get into.
Be Data-Driven
"Data-driven design" gets toss around a lot in technical circles, but essentially what it means is that the data is in charge and acts as the primary source of truth, not the world. It is very common in many game engines to have the "world view" and the "data" be one in the same space; while this is fine for simple things or things for which extensibility is far less of a concern, we need the two concerns separated.
What do I mean by this? We essentially want two responsibilities: the "simulation" which takes care of actually processing and updating relevant game data, and the "view" which takes the resulting data and draws it to the screen. The simulation does not need to know about mesh data, textures, particle emitters, lights, etc. since those aren't relevant to the simulation itself: it cares far more about things like inputs and outputs, collision boxes (if relevant), connections and relationships to the objects around it. For example, think about a "building" in a colony builder or RTS game: the sim needs to know where it is, what it is doing, and resources to consume/produce; it's the view's job, on the other hand, to draw the building to the screen and put out little smoke particles or play a little animation while it's "working."
The "Entity-Component-System" (ECS) model is a solid start: while not a hard division, ECS's "components" allow for components to have separate concerns and whether or not they belong to the "view" or the "simulation", and relevant systems that only interact with one side or the other. For Flagship, I want the division to be a bit more clear, but ECS as a concept will come up again.
I have this listed below extensibility but above performance, though, since I would prefer to sacrifice a bit of data-driven-ness in favor of extensibility, but don't mind losing performance if need be.
Be Performant
Obviously, ya don't want things to be slow; that just feels awful. It may not be the primary design consideration, but that doesn't mean we should just forget about it.
I think many players have become a bit too comfortable with simulation-style games just running like garbage and developers are getting complacent as a result. Not to throw shade at anyone, though, and there is a strong argument for not doing "premature optimization", but it does feel like many shortcuts get taken for the sake of ease of development, due to a lack of knowledge, or a compromise with available tooling.
That said, I'd prefer to leverage everything I can to just build systems that run well (or can easily be optimized) from the get-go. The prior two goals, though, take priority. It's all a careful balance, I suppose.
So Let's Talk Tech
Still with me?
The first thing I have to think about is what it is I'm going to use, tool-wise.
Game Engines
At the time of writing, I believe there to be three major players in the "ready-to-use game engine" market: Unity, Unreal Engine, and Godot. There are some other smaller or more specialized ones (colony builder built in RPG Maker, anyone?), but I won't be talking about them here.
Unreal Engine is the gold standard (as far as prebuild engines go) in terms of performance-per-prettiness but it's also probably the hardest to use and the most expensive (with good reason). Plus, it's used with C++ (see above about extensibility), so I'm just going to write this one off and move on.
Next up, Unity. In terms of "easy-to-use," and "my first game engine", Unity has been a go-to for a long time. It is written in C#, albeit a bastardized and ancient version at this point, and by default ships with a component-model-like system, so it's super extensible right out of the box. In fact, there is already a large community built around doing just that (with tools like BepInEx and Harmony). At a precursory glance, then, Unity sounds like a good candidate, but... I'll be honest: I spent a lot of time with it, both personally and professionally, and it's... well it's not bad, it's just not... good. It's got good potential, but the performance is really lackluster, the ancient version of .NET Mono it uses creates a lot of friction, and the whole Runtime Fee debacle kinda left a bad taste in my mouth. There's also Unity ECS, which aims to be more performant and data-driven, but in doing so they flushed the few things that made Unity good, namely the ease-of-use and developer experience, down the toilet. So, eh, something else.
Around about the time I was getting sick of Unity I stumbled into Godot: the underdog on the block. Rather than being built by a private company, Godot is assembled by the Godot Foundation as FOSS (Free and Open-Source Software), so no licensing to pay, which is nice. Besides that, though, it comes in three flavors: GDScript (a custom scripting language), C++ (or similar), or C#. GDScript, while good for newcomers to programming, has rather poor performance, but hey the C# is actually modern .NET! And not just "relatively" modern, but the latest and greatest! Neat! Much of the extensibility work made for Unity also ports over to Godot, too, which is another huge plus. As for the engine itself, it's built on a "node" model where very simple single-purpose nodes are arranged in a tree, much like Roblox or HTML. The sad part is, though, is that this style of doing things really sucks for being data-driven, since by nature everything is tightly coupled with the tree and therefor the world. Can't have everything, huh?
So now what?
Well, here's my thinking: go custom...ish.
I don't feel confident I could write a custom render engine myself as there is so much to consider and I'm just going to pick something off-the-shelf. The simulation engine, though, I will do myself; kinda a hybrid custom/prebuilt thing, I suppose.
What I think makes the most sense, then, is this: leverage Godot for the "view" and write a custom "simulation" in .NET C#. Godot will happily execute .NET code, so that's easy, and actually has another trick up its sleeve: you don't have to use it's node-tree system. In fact, Godot exposes all of its APIs at a much lower level, too, allowing you to create much more intricate and powerful systems while still saving yourself from having to actually manifest entire rendering or physics engines from scratch. What this means for my case is that I can build my simulation to interact with Godot's API directly and avoid the pitfalls that come with the node-tree system. And best yet, all for free! Need to make a mental note to go donate to the Godot Foundation if this whole thing does well.
As for multi-platform support, Godot is probably as easy to port as it gets and comes with some native macOS and Linux stuff: will for sure be including a Linux build as well.
And Away I Go
And that's our show, folks!
Next step is to start doing some theory crafting and experimental work on this simulation engine, which will be the focus of next week's post (assuming I successfully stick to the weekly cadence I would like). Some ideas are already brewing, and while my free time to play with this is limited, I am going to try to put some ideas together.
Until next time.