This post aims to introduce my ambitious, long-term gamedev project, along with my vision and long term goals for it. In essence, it could be described as a deep simulation, not unlike and very much inspired by Dwarf Fortress and Rimworld. The goal would be to build a society from the ground up in a survival scenario, while managing the needs of the population and overcoming obstacles such as natural disasters.
In absence of a real name and a fully formed idea of its final form, I've been lovingly referring to it as Name Needed.
Motivation
The main motivation for this project is to fulfil my dream of creating a dense simulation of interconnecting systems and emergent complexity. It is absolutely a hobby project, worked on only in my spare time around a full time job, without any set deadlines or release dates. I'm writing the game engine from scratch in Rust, a formidable task but one that is incredibly satisfying1.
Goals
Although the end product is still very fuzzy, there are a few major goals that form the foundation of the game.
Deep simulation
The core principle; as much as practicality allows for, all events, behaviours and actions of the universe's occupants should occur solely as a result of one or more systems. Predominantly this means avoiding the use of clever tricks to give the impression of depth and intelligence. These are commonly used in commercial games that typically don't revolve around intelligent agents and realistic simulation, instead giving the illusion of intelligence through smoke and mirrors.
I intend for virtually all aspects of the universe to be procedurally simulated, arising from the interactions between complex systems. Of course, not everything will be fully accurate and true to life, but I aim for very little to be explained by a shrug and "the RNG said so".
Clearly this is a very ambitious goal, and I acknowledge that full commercial success is very unlikely as a result. Many professional game studios have aspired to include deep and complex systems in their games, and ended up stripping them out completely when players didn't even notice them. However, with no fixed deadline or final goal, I have plenty of freedom to attempt to achieve my Simulation Dream with little pressure.
Intuitive introspection
There's no point in simulating the entire universe if everything the player sees is indistinguishable from random noise. Therefore I intend for a core part of the game to be based upon accessible complexity.
It should be clear to all what is taking place in the world, what caused it, and the possibly cascading effects those events will have. Most detailed information should be hidden or summarised by default, with very obvious UI controls to expand more detail.
This in itself is a massive task - good UI design is terribly hard even for professional studios, so a puny solo dev like me is going to have a whopper of a time getting this right. I particularly want to avoid information overload - dumping all internal game data in huge, indecipherable dashboards would definitely count as a cop out.
High performance
Care has been taken from the start to produce a well-designed, performant and scalable game engine. For example, using an entity-component-system (ECS) based architecture, cache coherent data structures, and targeted use of concurrency2. As with the other goals, this scratches a personal itch and something I find very satisfying to get right.
Rust makes the arduous challenge of concurrency hilariously easy in comparison to my experiences with other languages. I can be way more daring with my memory and thread usage, haggling with the compiler until one of us decides we're wrong3.
Open source
I want the project to be fully open source and free to play. The codebase can be found on GitHub.
In addition, I intend to release various components of the engine as separate engine-agnostic crates, such as the voxel world implementation and AI system. In future posts I'll go into depth about their implementations and interesting technical details and challenges around them.
Undecided goals
There's still a lot that's unclear about the project, much of which will be pretty critical. I'm still undecided on how to approach these, so for the time being I'm going to dump them here as questions and pretend it's a discussion.
Extent of player control
How much control does the player have over the world?
- Full direct control - clicking an entity and commanding go to this location, do this action
- Full manual control - using WASD to control the selected entity, otherwise they go around their own business
- Declarative control - much like other games in this genre; entities are fully autonomous, and juggle a personal task list that includes personal needs and orders from the player
- No control - spectate only, what a bore
Target of player control
Who does the player control?
- Everything and everyone - players can interfere with the world with godlike powers, spawning animals, starting fires and breaking kneecaps on a whim4
- Only humans in the player's society - other entities like animals can be introspected but not controlled
- A handful of humans in the player's society - the player controls a small gang out of a larger population
- A single human - the player only controls one person
- A handful of animals - e.g. the player directs a pack of wolves to achieve some nefarious goal amongst a human society
Camera view
How does the player view the world?
- Top down 2D - seeing a limited number of vertical slices of the world at a time, with the ability to move the camera up and down
- Fake 3D side-on and others - e.g. isometric or oblique projection
- Full 3D with AAA graphics, a campaign and FPS minigame - sorry, just teasing
Modding support
How should modding be supported?
- Native shared objects - powerful but very fragile, and not portable between operating systems and (likely) versions
- High level scripting API - if game logic was written in a scripting language like Lua/Mun, this could be very powerful and portable
- Data files - tweaking data files as the only modding "support", the easiest
- Not at all - just kidding, this would be the easiest option
Non goals
There are a few avenues I intend to avoid completely:
- Multiplayer - it will remain purely single player
- Using a commercial engine - most of the fun is writing it all myself from the ground up, so a port to Unity or Unreal is out of the question
Progress so far
I've been working on the project on-and-off since September 2019, and have made reasonable progress on the core engine so far. I will write about many of these topics in the future:
- SDL2 backend with top-down OpenGL rendering
- Massive voxel-based game world
- Hierarchical path finding with primitive steering behaviours
- Ambient occlusion
- A fixed number of vertical slices are visible at once, with the ability to scroll up and down in world space
- Infinite axis utility system (IAUS) AI
- Live browser dashboards for introspection during dev
- Inventory and hand-based item holding system
- Circular little cuties chasing food and wandering about aimlessly
In the video below, the circles are humans, wandering (path finding to random locations slowly) while their hunger slowly increases. Once they're hungry enough, they eat any food they are holding on their person, or sprint to the nearest food item on the floor to pick up (the green squares). The terrain is pretty boring, with a few nondescript solid colour block types. Near the end of the video, I move the camera view up and down a few vertical slices, hiding the terrain and entities out of view. Beautiful programmer art, don't you think?
-
The majority of my side projects for the last 5 years have been game engines, made with a variety of technologies. Many are the same ideas churned over and over again, but all in all they cover several distinct aspects of game development. These include procedural road generation, 3D voxels, and path-following agents. They all fizzled out eventually, but not without teaching me a great deal. ↩
-
By this I mean moving specific tasks (e.g. I/O, terrain generation, path finding) to background worker threads to avoid lagging the main thread, as opposed to blindly throwing threads at the core loop and likely causing data contention issues/overhead. ↩
-
If it's me who's wrong; thank you compiler, that's hours of debugging saved. But if it's the compiler who's wrong, it takes just a lick of
unsafe
and a few minutes to show that it was in fact me who was wrong all along. ↩ -
I don't know why, but the first situation I envisage here is watching a helpless villager carrying food between buildings, and deciding everything's going too well. Click the
Break kneecaps
button. They fall in pain, dropping the bundle. A fellow villager abandons their task of fighting off a feral dog with a stick to run over and starts dragging them home. The dog takes his chances and steals the food, carrying it off in his mouth. Imagine that. ↩