Originally published at Codegram's blog
A couple of years ago, back when I was doing my first steps with Vue, I decided to create a videogame using this framework. It’s called Live, and it’s a mostly text-based survival game with a very minimal UI (you can play it here). I had a lot of fun creating it, people had fun playing it, and it helped me learn a lot about Vue.
Nowadays, the hype around the office revolves mostly around Rust. I’ve been reading a bit The Rust Programming Language book and doing rustlings, but we all know the best way to learn something is by doing it. Codegram’s Retreat™ offered me an excellent opportunity to build something with Rust, although doing a big project felt a bit overwhelming.
But hey, history repeats itself, and what worked before should work again, so why not build Live again with Rust? With the business logic already defined and clear, I could focus on the code.
Luckily, not everything is entirely different and frustrating. You still have functions, modules,
let. Even though everything works a bit differently, you can get your mind around that easily. And
cargo feels like a super-powered
I followed a pragmatic approach and tried to have a functional game before worrying too much about following Rust’s best practices. That means a lot of mutability, cloning things, and when something doesn’t work, just try to add an
* or a
& and see if it solves it. Make it work, understand it later. That’s my motto! It might not be the most academic way to learn a new language, but it works for me. Let me give you an example.
Most of the game revolves around items. Finding items, consuming them, using them to craft other items (even though that is not implemented yet, I wanted to leave the data structure in place to be able to add the feature later). A standard item, like
wood, should have an
description. A consumable item, like a
berries, should also have other properties like the points of
food it adds to your stats once consumed. This meant that I really had different types of items, but since Rust doesn’t have inheritance, I could not have a
BaseItem to extend. To avoid getting stuck with this for hours, my first approach was to add all the properties possible to all the items. So I ended up with
water: 0 and
food: 0 properties, which is pointless. I also had to add a
consumable: true property to check and inform the user if the item could be consumed or not. It worked, although it wasn’t ideal. But at least I could go on with the project, and that's important for morale!
So once I had all the features of the game in place, I came back to this problem that I knew it should be done differently. At this point, I was a bit more confident because I had already developed a game with Rust. If I tried to solve the problem the right way when I first encountered it, it would have been a painful and frustrating process, and probably would have failed anyway because I just didn’t know Rust. With David’s and Txus’ help, we explored a few approaches. Having different types of items didn’t work, since most of the time I needed to work with a single
Item type. Also, it didn’t feel right having to repeat the common properties for each one. We tried to create an
Item trait and have all the item types implement it, but since a trait has no knowledge of the attributes of the struct that implements it, it just didn’t work without having to duplicate a lot of code for each implementation of the trait. And that didn’t feel right either.
If you have little or no knowledge of Rust, don’t worry if what I’m saying makes no sense. The point is that we kept trying things that didn’t work. And of course, that can be frustrating, but what was happening is that Rust was preventing me from going the wrong way. The cool thing about Rust being so strict is that, much like Michelangelo’s statue that already exists within the marble block, it seems that there is just one simple solution waiting to be found. And we did find it. In the end, it was as simple as having a single
Item struct that had the common
description attributes, and a
properties enum that could have different sets of properties (
values for consumable items,
So, history repeated itself indeed, and I managed to create a functional game, learning a lot about Rust in the process. There is a lot of stuff I didn’t explore, like working with threads, but it’s been a great first experience with Rust, and I feel I’ve advanced a lot as a developer getting out of my comfort zone and trying a language so different to everything else I’ve tried before.
Next steps: finish the missing features (like crafting objects and upgrades), play with threads for better time control, and explore WASM to be able to play the game on the browser!
You can find the project here, clone it and play by running