April 20, 2024 | Building a Roguelike in Rust's Bevy Game Engine

Topics: Coding

Pasted image 20240420205633.png
A screenshot of my "game" in an emulated terminal emulator

One of my goals this year, per my Hierarchy of Fulfillment, is to write four types of software applications:

  1. a game
  2. a Command Line Interface ("CLI") application
  3. an embedded application (software running on a piece of hardware without an operating system)
  4. and some kind of application that uses a Large Language Model ("LLM")

At the end of last year, I completed the DungeonCrawler project game, but I was following a guided tutorial in the excellent Hands-on Rust book instead of writing my own code from scratch. I wanted to do a couple things differently for my game project this year:

  1. craft the code myself instead of following a tutorial
  2. build it in a formal game engine

To meet these requirements:

My Approach

Given these requirements, I found that the author of Hands-on Rust, Herbert Wolverson, had actually made a project tutorial for a Roguelike Dungeon Crawler prior to and different from that in his book called "Roguelike Tutorial". I used this tutorial as more of a feature-list of what I would implement and a bit of a "cheat sheet" for when I got stuck trying figure out how to implement a feature - which happened a lot in the beginning.

Features

After about 13 calendar weeks, but only about 9 or 10 weeks of productive development, I have a "game" that runs, but is not feature complete. What I completed:

Challenges

There were many challenges with implementation of many of the features, mainly with learning how to program in the context of the game engine, Bevy:

The Bevy game engine is unlike other game engines where you build the game by composing an entire scene, which then generates the necessary code, like Unity, Unreal Engine, or Godot. Instead, in Bevy, you build the game by writing the code using a framework called an Entity Component System (ECS).

I chose Bevy over the others because I wanted to learn how to program, not just build a game, and I wanted to do it in the Rust programming language. Bevy isn't the only game engine built in Rust, but because it encourages use of the ECS framework and relies on building the program from code, rather than composing a scene, it was the right choice for my objectives.

Bevy also has a moderately sized plug-in ecosystem. The Bevy Ascii Terminal plug-in abstracted most of the camera work in the beginning of the project. However it would later become a source of frustration as I attempted to add mouse-over support for my game and again when I needed to learn how to implement dual-pane support for the game's user-interface (UI). Still, the plug-in delivered the old-school "terminal" aesthetic I was going for and even provided an example of a limited "Roguelike" in its example documentation.

Another challenge was that after a certain point, the Roguelike tutorial I had been using as a feature-list and cheat-sheet for code became only useful for inspiration since my project had diverged so much from the reference material. This slowed down development as I had to figure out more and more problems on my own - though this is arguably the point of the entire exercise. So perhaps more a "feature rather than a bug" situation.

There were also the typical challenges associated with any programming project: poor project design (on my part), ambiguous goals, inadequate or incomplete documentation, version compatibility, and lack of experience resulting in "re-inventing the wheel".

Learnings

Regardless of, and specifically due to the various and numerous challenges, I consider the project a success.

Through the project, I learned:

Most of all, I gained significant and valuable experience in writing in the Rust programming language.

One of best things I did best was promising myself to commit a new feature to the game every single week day, which I did for most weeks. That kind of promise forced me to write "good-enough" code and not get caught up trying to build bigger systems or plan for size or scale that would never be needed. As a result, I built significant momentum in the project - even when I stopped relying on the Roguelike tutorial for my feature list and cheat sheet. It wasn't until some significant disruptions in real life that forced me to re-prioritize and ultimately take a break from my project that my momentum stopped.

Wrap

With a hard deadline of End of Quarter (EOQ), or March 31st, I must now consider my project "Done" despite not having implemented even half of all the "necessary" features I had intended. I'd love to come back to this project in the future and finish all the primary features so I would feel comfortable calling it a "game" and publishing it. I'd especially like to build out some of the experimental features I've been dreaming up in my head.

I must now move on to my next project, but I did succeed in my objective: I built a game in a game engine using the Rust Programming language.