This Month in Lunaria – July 2021
Lunaria is now using the Godot engine, updates can be streaming to clients through the gRPC API, and camera controls have been implemented.
I'm back! Let's just say that living through a global pandemic takes its toll, and I wasn't able to focus on the project as much as I would have liked. I'm trying to learn from this and set smaller, more achievable goals for the future. But the big news for July is that there has been some progress again!
Switch to Godot Engine
The original plan was to use the new game engine Bevy to create Lunaria. Bevy is written in Rust, which provides a good foundation for the low-level services that Lunaria's API needs to run. But Bevy is still very young and in active development, which makes it hard to find good beginner resources.
Godot on the other hand is very mature, and its community has created an abundance of tutorials for all kinds of games. The engine is written in C++, which means tightly integrating the backend into the engine will be more difficult. But Godot supports plugins written in Rust, which should make it possible to stick with Rust for the backend and the core logic.
I have decided to experiment with Godot, since Bevy overwhelms me as complete game development novices. As I gain experience and a better understanding of this domain, I might reconsider this decision. But for now, I want to prototype as quickly as possible to learn if Lunaria can even work as a game...
Streaming API for the Game State
The most interesting development has been a streaming API for the game state, which uses server-side streaming in gRPC to push changes to the client. The idea is that a client can start the game by calling the
startGame method. The response to the method is a stream of game states, starting with
GAME_STATUS_RUNNING. When the game ends or is stopped by the user, the server streams a
GAME_STATUS_STOPPED update to the client, indicating that it can stop running itself.
After experimenting with this idea for a while, I don't think it is well suited for this particular use case. For one, it introduces a significant barrier to entry. Players would have to implement asynchronous methods just to start the game, which will be challenging for less experienced developers. And the value of server-side streaming for this use case is pretty low, as changes do not happen frequently and can easily be captured by an error response to API calls. For example, a call to
moveUnit can simply return an
ERROR: Game stopped response, which eliminates the need to stream the state change in real-time.
A better use case for server-side streaming are updates to systems that are controlled by the server. Taking a weather system for example. Clients could poll the weather ever so often using synchronous method calls, or they could subscribe to a stream of real-time weather updates that get pushed from the server whenever the weather changes.
I am very excited about this experiment, since it enables a few very interesting game mechanics later on...
Less exciting but very practical is the implementation of camera controls in Godot. The controls are inspired by modern strategy games, in which the camera can be moved with the keys
D. Additionally, players can zoom in and out using the keys
Future plans for the camera controls are to support moving the camera with the mouse, for example my moving the cursor to the border of the screen.
The implementation is done in GDScript, which is the default scripting language in Godot. Once the missing features have been implemented and the controls have been tested sufficiently, the plan is to open source the implementations and publish it as a plugin for Godot.
Next Month in Lunaria
This month has laid quite a good foundation with the switch to Godot, a better understanding of gRPC and its capabilities, and the camera controls as a prerequisite for navigating the in-game world.
The focus for August is stabilizing the features introduced in July, and working towards the first game mechanic. This means finishing the implementation of the camera controls, implementing an API to start and stop a game, and then figuring out what the first game mechanic should be.