Triverse is a pausable drone-building simulation on a triangle grid. Players scavenge parts and resources to build drones, defending against opposing drone collectives. Players can choose to fortify a base or build a fleet to explore the world.
Each part occupies a tile and affects surrounding parts and the overall dynamics of the drone. By arranging parts in a plan grid, players can design a mix of stealth, firepower, defenses, or mobility for their drones. Worker drones then construct those designs, crafting parts as needed. Drones can range in size from one part to hundreds.
Players control either individual drone movement directly like a roguelike or leave it to the AI. The AI will maneuver to avoid danger and find vantage points to attack from, but players can help it by giving RTS-style targeting or movement orders. Turrets fire automatically, choosing targets based on vulnerability or player orders.
My primary goal was to design and implement end-to-end resource and assembly systems. Originally parts were simply collected in an omnipresent inventory and warped in when building, but I wanted a more physical inventory with real costs to storing or moving parts around. This took the form of a worker system, where worker drones of varying shape and size could carry parts.
Along with assembling, I wanted the ability to bootstrap a fleet by mining or growing raw natural resources rather than always relying on scavenging. The use of raw resources also gives something for bases to protect or fleets to seek. Parts can work for this purpose too, but they are less fungible and typically used directly rather than stored. Resources come in both renewable and nonrenewable varieties.
And then we need a way to transform those resources into parts, so a crafting system emerged. This system piggybacked on the existing blueprint system and allowed players to place specific recipe blueprints, which when assembled became an output part. The end result is a simulation where players can draw plans and recipes and worker drones rush around to fulfill them. However, while recipes and crafting are powerful, but they also feel like a bit of a distraction from other gameplay.
On the technical side, I implemented snapshot functionality to save and restore game state. This turned out nontrivial due to the self-inflicted actor architecture, although the approach has its advantages too. I believe the actor design is sound, but I’m still a bit concerned about race conditions I may not have considered.
I extracted some of the more generic ECS code into a new F# library called Garnet. I took a detour from the game to clean up and revise portions of the library, notably the actor system. The library has features useful for Triverse, but I’m not sure how fit it is for other kinds of games. In general, I find occasional detours like this helpful for learning new things or taking a break from a main project, and they often have the side effect of equipping me with new tools or ideas to take back to the project.
Next I switched from Urho3D to Veldrid, a low-level graphics library with a wrapper for ImGUI. This leaves me without a cross-platform audio library, so I’m using NAudio unless I find a better alternative. I also upgraded to .NET Core 3.1, which allows publishing to a single executable file. From that point I switched from using F# interactive for debugging to creating ImGUI elements to inspect the world. These efforts took about a month.
After completing those conversions, I revisited usability and complexity, in particular the way orders interacted with plans and building systems. There could be overlapping removal plans, addition plans, and merge orders, all of which made for too much state and too many edge cases. I’ve also felt the usability suffered from parts of this design, but it wasn’t until recently that I found a simpler alternative.
Worker AI also needed a revision. The simulation worked, but worker orders often conflicted and the overall work wasn’t so efficient. The new approach is much more efficient and supports workers of any shape, although smaller sizes tend to work best. Since then I’ve focused on making this new design complete and bug-free.
Regarding process, the design revisions actually happened quickly once I had a sense of direction. While I can’t predict when I’ll have a flash of insight, I can spend dedicated time refining and analyzing the implications of the design change. But this thinking must go hand in hand with actual review of the code, and it often helps to aggressively make and revert changes just to explore the extent of change needed. The result is a tentative TODO list of reasonably-sized transformations that I think will achieve the goal, but once I actually start to write the code I expect to discover more items or change existing ones. I try to make soft switches when possible, where new functionality is added and confirmed before removing the old way entirely. Each step should ideally take less than a day with minimal bugs introduced. This is not a new process for me, but I felt the execution of it was more systematic than in the past.
- Design breakthroughs
- More technically solid
- More productive
- Released ECS library
- Expanded scope?
- Few devblog posts
- No demo available
After finishing up with workers and the building workflow, I plan to revisit world generation and spawning with the goal of reaching end-to-end gameplay. Then I’d like to fix some longstanding issues with torpedoes, mines, and any other existing mechanics. I don’t plan to introduce any significantly new gameplay at this point.
For presentation, there’s hardly any audio and (intentionally) no use of text whatsoever yet. However, until the player has an intuitive feel for how various parts interact, stats or explanatory text are needed. Graphics are adequate for now, but I hope to improve them at some point. There are other non-gameplay features like the main menu, player blueprint persistence, and world management that need attention too.
On the technical side, I need to revive event logging and replay so I can capture and reproduce problems. The game has many systems interacting in ways I can’t always predict, so I’d like the capability to analyze problems offline rather than attempting to manually reproduce and debug them. And ideally logs or snapshots would help in building automated regression tests once the design is locked down more.
There are also plenty of opportunities for optimization, but performance at a small to medium scale (10-100 drones with ~10 parts each) is not really a concern. I’d also want more rigorous automated testing before making changes that could introduce more complexity, so this is a low priority unless I discover hot spots that affect common scenarios.
Finally, procedural generation is an obvious candidate for further enhancement, but between simple noise-based world generation and a selection of handcrafted drone prefabs to spawn, I feel it’s low priority at this point.
- Focus on end-to-end gameplay
- Refine existing mechanics
- Fill in usability/presentation gaps
- More devblog posts?
- Additional gameplay
- Performance improvements
- Graphics improvements
- Procedural generation