A 2D RPG-like groundwork with Bevy and LDtk.
A year and a half ago I saw a simple google promotion rpg-like game. I was surprised by the curiosity a simple game like that can create. Not only did I enjoy walking around in that small world, thinking how well some of the sprites turned out, but also how much time it had to take, even though it was released just as a weekly free easter-egg almost.
I started thinking if I could make something like that, if that would be even possible. I never used any other game engine. I knew practically nothing about Unreal, Unity or Godot. But one month before that I made this article where I experienced working with Bevy, which is mostly intended as a game engine, though in that article I used is just as an ECS system.
If my goal was to make just a game, I would probably use Typescript and some recommended library. But this was not really my goal. One of the reasons I like rust, is that it promises strong utility through performance, while being more accessible to newcomers than C++. I enjoy using rust, Bevy was interesting and I became curious how a real game would be even started, so I started looking into it.
I set my goals low, I just wanted to get something going. Under some Bevy links I found “bevy_retrograde”. It looked at that time absolutely perfect to what I wanted to achieve. Basically a starting point to just get going with a simple rpg-like game. I went through the code in the examples of both Bevy and Bevy_retrograde and after many tries and errors, I ended up with with a moving and animating Gabe, the name of the default character provided as part of a few Bevy assets. He even collided with some shapes I created. Bevy retrograde provided some tool for creating these collisions out of shapes. It took less than 100 lines of code, but I was very proud of myself anyway, since the process wasn’t easy. I never knew exactly which examples to take guidelines from.
And there start the problems. This bevy_retrograde was not really the big help as I was hoping. The only extra thing it really provided was this collision tool, but you also don’t always want to collide with every single pixel you or your surroundings are made of. Also I had no idea how to create the graphics for levels with just this. I realized if I wanted to continue, it would make little sense to continue building on this retrograde tool. This made me put it on the side for another year.
Almost exactly one year later, I noticed Bevy gaining slowly but steadily more and more traction. Before there was Amethyst and some other competitors, but by this time Bevy seamed the clear leader among Game engines in Rust. New versions were coming out and I was tempted to try to port my old code to the new version and have another look at it. That was the second commit.
A slow process
I could write a small article about every single commit after that. This was by far my biggest Rust project so far. It currently has around 1.000 lines but it feels like much much more, lol. I will mention that planning was and is a big part of such a process. After every single commit, I rewrote my priorities of the features that should be made next and a vision of the tools that could achieve that. I knew that I will eventually have to implement another solution for colliders and some tool to help with graphics. Luckily both Rapier and LDtk fit those roles well.
Rapier is such a polished tool, I was most worried about colliders, but in th end, his was the least buggy part of my tools. I wrote down the 4 major issues I stumbled upon in my my dev process at the bottom of the
README.md they have links to the connected issue trackers and descriptions. I managed to workaround all of them, but the first was probably the most obscure one. Shortly the UI and text elements that you can spawn through Bevy are not perfect yet. This will be hopefully addressed in the future or be superseded by some other solution. The text box for displaying text to the user is probably one of the most lacking parts of my code. But its implementation is already so complicated, I dread touching it again. Thankfully there are new libraries dedicated to gui in bevy coming out like bevy_egui. I wonder what would be a good solution for better text boxes or speech/alert bubbles next to entities.
The other three issues were connected to
bevy_ecs_ldtk which is the library that connects the LDtk editor to Bevy. Among the other libraries, this is probably the weakest link, but when using LDtk with Bevy, this library seams like the by far best option. It is maintained by one dedicated and awesome guy, but it’s just one guy. I took allot of help from the libraries' Platformer example, and also the author’s game
ludum-dare-51 build with the same tools. Those source codes were a great help for deciding how to implement certain things in rusty-woods. If I get to implement patrolling in the future, I would again compare the Platformer and ludum before deciding how do add it here. I submitted a few PRs and Issues, but the scope of the whole library is really quite big. Bigger than the support for it right now. The LDtk editor is made by a professional
company or at least appears that way. And Bevy is also a huge project by now. I hope the love for
bevy_ecs_ldtk grows and receives more help from the community. Since both Bevy and LDtk are amazing and we also need an amazing bridge.
Why it is amazing
I am happy to have brought this to something like a proof of concept level and that it can be smoothly run in wasm on my site. Please feel free to click here or the link on top of the page. After it loads, just click once into the middle of the canvas so it focuses, and after you can move the player with wasd or arrows. There is no other input currently.
I hope this can motivate anybody to try out some of these tools, or even build upon my own repo. It is free to use! I hope it helps somebody to build something awesome.