RAVIOLI: Tower Defense

A factory building tower defense game. Oh boy where do I even start. This has been a long project that has gone through many, many iterations.

The core idea of making a factory game has been with me for a good while now and I’ve been working on it for about a year at this point. But ravioli itself, I’ve been working on for the past 6 months.

Initially, this was meant to be a 3D game, with a voxel engine. And while the tech of a voxel engine was evidently very interesting to me (I mean, I’ve written not one, but two posts about it. The latter of which was an in-depth guide on how to make one, even if not optimised) I wasn’t able to make the gameplay feel enjoyable. Primarily because of the 3D grid-based nature of it combined with me not being able to think outside of the box (heh).

But I think this 2D version we have now works great. I’ve been working on it and really enjoying it a ton. More about the tech behind it after you check it out.

RAVIOLI: Tower DefenseSource code

The Tech

If you’ve ever read my previous blog posts, you probably already know I’m very comfortable not using a game engine. Ergo, I didn’t use one for ravioli either. The game is completely written in Rust, using wgpu for graphics and winit for window management.

Other than that, the rest is pretty standard.

I think I should address a question I get surprisingly a lot for someone who has 30 people in their discord: why not use a Rust game engine.

Or, more specifically, why not use bevy? For the unacquainted: bevy is, in their own words, “A refreshingly simple data-driven game engine built in Rust”.

The reason I didn’t use bevy is because I don’t think an ECS is the correct driver for my game. At its core, ravioli is a very simple game. You have structures like assemblers, belts, turrets, and you have entities like bullets, enemies, explosives.

Obviously there are different ways these things interact with each other, for example while all other structures can be evaluated in pretty much any order belts need to be evaluated in a certain order to ensure items flow correctly. Or Martyr nodes need special handling so that you can form health networks without them destroying each other.

But nevertheless, none of these would benefit from an ECS. They’re entities with systems yes, but I have no need for components and what little need I might have is trivially solvable by using tagged unions.

You could argue it’d make the game faster, more performant. And you might be right, it would maybe allow you to get 50,000 entities at 60fps instead of 10,000. A 5x difference! It might make the code a bit more complicated but come on, a FIVE TIMES DIFFERENCE IN PERFORMANCE!

But also, in ravioli maps are small and contained. It’s not open world with an infinitely vast horizon.

But also, if it was open-world like for example factorio, I wouldn’t want a generic ECS like bevy either. I’d hand-roll my own system that’s specialised for my usecase.

I think it’s amazing that we have engines that people can just pick up and use, I mean for a good portion of my life I’ve used raylib for everything because I didn’t want to learn OpenGL. But I don’t think bevy is the right choice for me.

If you’re interested, I recommend reading this by LogLog Games. It’s quite a long read about Rust and gamedev. If you have the time, definitely read all of it it, but if you only have 5 minutes, at least read the section about ECS.

Conclusion

ravioli is currently in development, so I’d absolutely love to hear what you think. So please join us in my discord server and if you want to support the development monetarily, I have a ko-fi page!

Thank you for reading, and I hope you enjoyed the game!