Minigene, Shotcaller, WOTFG, Amethyst and the Future of Rust Gamedev
Hello and welcome to your ~~daily~~ ~~monthly~~ yearly status update! This post is rather long, so feel free to skip sections underlined with dashes, as they are more in-depth explanations of what was mentioned just before them. Let's task about what has been happening in the past few months and what is coming in the future!
Minigene
Minigene is a new game engine. It is meant to fill the empty space between indie game development and professional game development. https://github.com/jojolepro/minigene By that, I mean that it sits between the "we do everything for you and hold your hand" approach and the "build everything yourself" approach. Minigene is built from a wide collection of small (and not so small) crates. To understand how it works, we can think of the engine using layers. For instance, here are the layers used for the game Shotcaller: - 4: Game - 3: Minigene - 2: Glue - 1: Features
Layers Explained
Let's start at the bottom, with layer 1: the features. This layer is composed of many small and specialized crates. For instance, one crate for i18n, one crate for game inventory and item management, etc... https://github.com/jojolepro/game_features This layer also includes crates which aren't "game features" but are "engine features". For instance, the crate game_engine_core gives us a structure in which we can run our game logic using global states. https://github.com/jojolepro/game_engine_core Crates in layer 1 are small and usually aim to have all of their functions verified using unit tests. They also aim to have clear documentation. Finally, they aim to limit the number of different ways you can do the same thing. This is so it is easier to learn how to use them and it also limits complexity. Now, let's talk about layer 2: the glue! The glue is the part of the engine that takes data from some global storage and updates/calls the layer 1 features. In the case of minigene, we use planck_ecs, the easiest entity-component-system to use and also the most tested and minimalist. At layer 2, we "wrap" the layer one features inside of the glue. One layer 2 crate can use one or more layer one crate, although we usually try to limit ourselves to one. For instance, we can have a planck_game_features crate that creates Systems which execute game_features update functions using Components coming from Planck's World structure. Now, layer 3 is simply minigene, the crate. It re-exports a bunch of layer 2 crates into a convenient package. To avoid importing a billion crates when using minigene, we place the different features into groups and hide them behind feature gates. You can enable those features using:
minigene = { git = "https://github.com/jojolepro/minigene",
    features = ["feature1", "feature2", "..."] }
Finally, layer 4 is the game you want to make. Usually, it will import minigene and use some of its features. It will also import some crates that are specific to the needs of the game. Here's how it will look in practice: https://www.figma.com/file/cv7orWvUWfB6teK7RLqu3L/The-New-Amethyst?node-id=0%3A Quite the mess, I know, but it is the cleanest graph of a full game engine that I have ever seen. I'll let you imagine how horrible it is for engines which are not aiming to have small dependencies! Let's continue: You are free to replace any feature of minigene with your own or an equivalent crate. Minigene is written in such a way that, if you want, you can even use it alongside another game engine! For more details on this, read the section on Shotcaller. Finally, the engine makes heavy use of event chaining. I discussed of this extensively here: https://jojolepro.com/blog/2020-08-20_event_chaining/ In short, it allows to drive the execution of systems using events and to create events from past events. Here is a quick example: <bracket-lib event>::char(x) -> InputEvent::KeyPress(x) -> GameEvent::Jump -> NetworkedAction::PlayerJump(auth_id) -> NetworkEvent::PlayerJumped(entity_id) Here, we started with a key press, inserted it in a more convenient structure, created an event specific to the game we are creating, pushed a network event to the server and finally notified all clients in the game that we jumped.
Features Of Minigene
Currently, Minigene has quite a few features but is far from having all of the planned features. Here are some features that are currently implemented and working: - ASCII rendering in the terminal - 2D Tile-Based graphics in a desktop window - Input handling - Game inventory management - Game stats management (health, mana, damage dealt this game, etc...) - Game engine core (sleeping, executing game frames, managing states) - Game clock & stopwatch - Planck ECS integration - Bracket-lib integration - Runs on WASM (Web Assembly)
Planned Features and Changes
The engine has a lot of planned features, but for now we will mention only a few of them. - Add a command/debug console (clap to events, custom logger output) - Add network backend nakama-rs - Add network backend message-io - Integrate planck_ecs_bundle - Create bundle with game_features related systems (planck_game_features crate) - Move code (when applicable) from minigene systems to game_features - Integrate a 2D renderer to emulate terminal rendering - Integrate a 2D renderer to render sprites in any position, shape or rotation. - Choose a math crate that will be used as the base on which we build other crates. - Mobile device support (high priority!)
Shotcaller
Shotcaller is a MOBA game inspired by DOTA 2 and League of Legends. https://github.com/amethyst/shotcaller It is built on minigene and was the reason the engine was created in the first place. Interestingly, we actually run Minigene inside of the bracket-lib engine. Bracket-lib drives the execution, either through its own event loop or through web assembly, and then calls Minigene's Engine::engine_frame function. The game can be tested using:
git clone https://github.com/amethyst/shotcaller
cd shotcaller
git checkout ac07a7bfb4224e8af4bd43e6df3afcaa879d4a48
In the case this doesn't work, there is also an online version: https://shotcaller.jojolepro.com/ This version is quite a bit older, however. Desktop Version: Old WASM Build:
WOTFG
World Of The Fox God is a tile-based MMORPG (multiplayer roguelike/roleplay). https://github.com/jojolepro/wotfg It is inspired by games like Cataclysm: Dark Days Ahead (graphics and skills), Path Of Exile (depth of items and skills) and Minecraft Faction servers (core gameplay ideas). It aims to be an anarchist (without hierarchy) game, meaning that there is no strongly enforced concepts like groups, leaders and chiefs. It is up to players to communicate, form alliances and figure out how they best want to play together. It also aims to be a hardcore game while still being easy to enjoy, meaning that it is punishing when you do bad actions, but there will be plenty of room to enjoy the game and learn from your mistakes. To achieve this, we will make death very punishing: You will lose your character, experience, skills and items. When you create a new character, you will appear in a random location in the giant world, with no indication of where you are until you find a map. The reason for this is twofold: - We want to encourage players to cooperate and for this to happen we need to discourage attacking other players. Since the downside to dying is so high, attacking players is a risky gamble that not many players would risk taking. - Players should be more likely to cooperate with others and should avoid fighting others in most cases. The game also aims to maximise enjoyment while minimising the time spent actively playing it. To this effect, we took some inspiration from Runescape's model: Crafting and farming items takes a long time. This means that you can start crafting a new chestplate, go cook yourself some food in real life, and come back to a brand new chestplate. The time it takes to make something will depend on its rarity and level. Some items will take 5 seconds to craft, while the best items will take 24 hours. Crafting recipes are pausable, so you could craft one of those longer recipes over multiple nights while still actively playing during the day. Kind of related to this, the game aims to be strategic and gives you some time to think about your actions. Game updates happen every 5 seconds. This means you can only do one thing each 5 seconds, being it to move, continue crafting, attacking a player or mining some ore. This slows the game down quite a bit, removing the stress factor of real-time games. Since the goal is not to make you press a key every 5 seconds and stay in front of the game, there is what I call an "Action Queue". It queues your action that will be executed, one at a time, every 5 seconds. For example, if you press ddddd, your character will move 5 times right over the course of 25 seconds. Again, while this might seem boring, it is not. The game is meant to be played while doing other things (working, cooking, watching videos), so it actually feels fast when you do other things at the same time. The great thing about that is that it can fill this feeling of "not doing progress in life" while still encouraging you to do the things you need to do but might not fulfill you. Currently, the game only runs in a terminal using ASCII graphics. Tile-based 2D graphics are planned. Mobile device support is also planned and a high priority! Let's complete this section with some details with the world and some details about the short-term future of the game. The world is huge, 125x125 chunks of 128x128x16 tiles. That's 4 billion tiles! The current plan is to have a single server containing around 10,000 players. Depending on how much resources that takes and the number of players on the game, it is possible that more servers will be created or that the world will be extended. Right now, the game has around a third of the planned "base" features. - Inventory management - Crafting - World generation - Mining - Moving around the map - Player Action Queue - Picking up items - Partial implementation of multiplayer Here's a preview of some of the planned features for the next couple weeks: - Add placing tiles in the world - Complete world chunk saving - Add description of items at the left of the inventory screen - Add item dropping - Add item containers (chests, lockers) - Show keybinds right side of the screen - Add timing to crafting (currently, crafting does not take time) - Add falling and fall damage - Add mining up (but not down!) - Limit view to what your character can see - Event Log at the bottom of the screen Underground Layer: Surface Layer: Inventory: Crafting: There are way more things I want to talk about, but I will keep those for future blog posts.
Amethyst
I recently joined the Board of Director of the Amethyst Game Engine Foundation! All that means is that is that now I'm in charge of getting the engine back on track. There are a couple ways to do that, so let's start with what we can do RIGHT NOW. First of all, we are making all issues "actionable". What I mean by this is that we will ensure that all Github issues have a list of tasks that, once completed, will lead to the issue being closed. This is to make it easy for contributors to understand what they have to do. It also makes it easy to know which issues we have to close: Issues that have no clear way of getting solved get closed and discussion is encouraged in the RFC process to come up with a solution there. Secondly, Amethyst 0.16.0 NEEDS to be released. The only remaining task to get there is to update the book with new information concerning the legion port and update the code examples. Finally, I have made a longer term list of tasks to improve the engine and also time estimations of the work: - Make all issues actionable (4h) - Fix book for legion port (10h) - Add test_all.sh script and release.sh script (with places to check everything is fine) (4h) - Publish 0.16 (2h) - Replace src/ content with game_engine_core (5h) - Remove hard dependency on git lfs (5h) - Publish 0.17 (1h) - Replace stopwatch by rust-stopwatch2 (1h) - Implement default, serialize, deserialize, debug to more types (2h) - Explore replacements for amethyst rendering (3h) - Explore replacements for amethyst ui (3h) - Look at what code can be moved out of amethyst and into other crates (8h) - Publish 0.18 (1h) - Check that we are using nice color crate (1h) - Implement physics crate with bindings to nphysics_ecs (6h) - Publish 0.19 (1h) - Implement mesh editing and querying (ram-side mesh data) (3h) - Add wgpu renderer (or any renderer with opengl and mobile support) (20+h) - Publish 0.20 (1h) As you can see, there is this "look at what code can be moved out of Amethyst" item. This is because I want Amethyst to follow the example of Minigene: features should be moved to layer 1 crates, legion glue to layer 2, and Amethyst should act as layer 3. This is a ton of work for an engine of this size, so it is fair to assume that Amethyst codebase will contain both layer 2 and layer 3. I'm still hoping we can get layer 1 out of amethyst and into reusable crates that will benefit the whole ecosystem!
Call For Help!
Wew! This was a long blog post! Still here? Good! We need your help! *I* need your help! There are a lot of ways you can help, even if you are not familiar with programming and even if you didn't read the blog post at all!
Donating on Patreon
Donating on patreon helps me spend more time working on open source projects! Whether it is games or game engines, your monetary donation helps create that! It is also the easiest and fastest way to help me and the open source game ecosystem as a whole! https://patreon.com/jojolepro
Contributing Code/Unit Tests
There are multiple ways to contribute code. In the case of Amethyst and Minigene, it can be as simple as taking layer 1 code (features) and layer 2 code (Entity Component System systems) and moving them to small crates. In the case of WOTFG and Shotcaller, you can open pull requests with features that you want. Before doing that, it is always a good idea to contact us to know what is most needed and if your feature is something that would fit well with the game concepts. Finally, for all of those, adding unit tests to ensure that everything is working like it should is extremely appreciated!
Contributing Documentation
Documentation is also something that is very appreciated. Whether it is just fixing a typo or contributing pages of documentation, we are very grateful towards anyone writing documentation, blog posts, tutorials and books!
Talk about us!
If none of the previous options sounds like a good fit for you, simply talk about us! Post the link to this blog post to places you know. Every bit helps!
Joining/Contacting us
Here is how you can contact us for those different projects: Myself: - By Mail: jojolepro [at] jojolepro [dot] com - On Discord: jojolepro#8057 - Patreon: https://patreon.com/jojolepro Minigene and WOTFG Development Team: - On Discord: https://discord.gg/gb2wENz Amethyst and Shotcaller: - On Discord: https://discord.gg/amethyst Follow the blog using RSS! https://jojolepro.com/blog/blog.xml As a final note, I'm currently looking for a job. Feel free to contact me if you have an open position, especially in Rust!