Week 1
6/29/2021 - 7/5/2021
6/29/2021 - 7/5/2021
Setup was pretty straightforward, installing Rustup and getting Cargos working. The concept of Cargos is interesting... it feels like a wrapper around complication (which it is) -- usually I question why the complication exists in the first place, but it seems like there are some benefits of automatic Crate inclusion and updating. .toml files seem like some management, but also seems like it is just explicit management of what would be implicit requirements in C++, which is definitely better.
I initially thought about trying to get a different IDE working as well, but VS works well enough and without a compelling reason to try something else I would rather not add that as an added complication to learning Rust.
I couldn't find good syntax highlighting options for rust in VS, but the generic version seems ok, if a little bland. It only seems to fail when handling macros, which shouldn't be too big of a negative.
At this point we have (obviously temp) red smileys constantly travelling to the west, and a player who is able to move around with the arrow keys. Most of this was an intro to the Specs ECS library and getting to know Rust a bit more.
Specs inclusion is easy thanks to the explicit dependency management!
Specs seems easy to use. Adding components to entities is straightforward, though I don't use this style of method chaining pattern very much. It definitely fits my expectations of what an ECS system should provide and I am looking forward to digging into more components and systems going forward with this!
Now we have a map drawing, with walls scattered randomly throughout the space. We also have rudimentary collision, preventing the player from walking on the walls. The Smileys are ditched at this point, since they were just for learning/demonstration!
Not much Rust-specific or component related work here. This is pretty standard map generation.
The method used is straightforward, but seems limited in some ways. We are basically just manually defining all the tiles by enumerated type on creation, then letting a map drawing function draw the tiles as glyphs and colors in a super hardcoded way. We are also doing 'collision' by checking this tile type and basing collision off of that.
My plan is to eventually change these tiles to use a renderable component and add some tile info style component to allow walkability and other things to be stored as a component on the tile, instead of being hard coded into the type. The walkthrough might actually cover this though, so we will find out!
Simple, procedural map generation now. We are just generating a bunch of rooms then connecting them by mostly straight corridors. The architecture made this pretty straightforward, which is cool.
The beginning of this step was a bit of busywork, splitting the monolith main.rs file into a couple of other files for components, player, and map. Inclusion and usage of things in other files isn't very clear to me at this point. Not clear on what 'super' does for including some structs, mod vs use for including parts of a file, and pub needing to be set on members within a pub struct (this is just a difference from c++ and is probably actually better because it is more explicit)
This part was good for getting some more practice with Rust function syntax and layouts as well as getting more used to how return values work. Nothing particularly new in terms ECS usage/implementation or logic here, but there are some classic rogue dungeon generation tricks here that I find interesting.
This part is about setting up the visibility system. Limiting what can be seen by the player and implementing a basic fog of war, to maintain previously viewed sections of the dungeon once you leave. This ended up being pretty straightforward once I wrapped my head around how RLTK expects to be used. It definitely feels like a very Rust-like implementation, which is what I wanted!
I found the 'impl' style of Rust to do overrides of included classes to be a bit confusing at first, but I think it makes sense after going over it a bit more. My gut says it will be hard to keep track of what code is running if a lot of these overrides exist in a codebase, but maybe that is a rarified situation.
As I noted before, the Map implementation here is definitely not very ECS, it is basically a monolith for handling map stuff -- a single component with a bunch of tile data and systems to handle those tiles. I am still looking forward to refactoring this if it remains in this state by the end of this walkthrough.
Adding some monsters! They currently just stand in the middle of the room and don't move, but start ticking only when the player is in view, and only once per player move.
This part was very straightforward to implement because of ECS, which is pretty cool. It is easy to use a component as a tag to mark which entities to tick. The AI system is pretty hardcoded at this point, but I imagine that will utilize more components in the future.
The ticking done here is pretty simple, but functional. I will probably want to re-implement this as an energy-based system in the future, to allow entities to tick at different rates.