As part of the 2022 RoguelikeDev Does The Complete Roguelike Tutorial I've decided to adapt the tutorial for ROT.js. There's a variety of ways to get a ROT.js application up and running. For this tutorial we'll be writing our code in Typescript so we have nice strongly typed code, to handle our transpiling and bundling we'll use ViteJS, and of course we'll use ROT.js, a javascript library modeled after libtcod. So let's get started!
Now that we have a working application to start from, it's time to add one of the most important parts of a roguelike game: a player character that you can move around on screen! We'll start with a little housekeeping on the code we've written so far, get a character drawn on the screen, then add the ability to move it around via the arrow keys on your keyboard.
We have a player character that can move around the screen, but it's pretty inflexible at this point. In this tutorial, we're going to lay the groundwork to have more than just a single character on screen, and start working towards being able to generate a map to play in. We'll also do a little cleanup again to make sure we have a maintainable code base in the future. Let's get started!
In this part of the tutorial series we'll make a more interesting world for our player to move around in; consisting of several rooms all connected by hallways. We'll also get to use a not too commonly used feature in modern JavaScript/TypeScript: Generator Functions.
In the previous tutorial, we made it so our game can render a full map on screen. However, roguelike games are about exploration into the unknown. In this chapter, we'll make it so we only draw portions of the map the player can see or that they have already explored. We'll be calculating the player's field of view to accomplish this and displaying the map in different ways based on that calculation.
We have a randomly generated dungeon, and a player that can move around in that dungeon. In this chapter, we'll add enemies to our dungeon. They won't move or be able to be damaged, but that will come soon enough.
Previously, we added some monsters to our dungeon, but they just stand around lifeless. In this chapter, we'll bring them to life. We'll make it so the monsters follow us once we enter their line of sight. Then we'll add the ability for them to damage our player as well as for our player to damage them. Finally, we'll update the game so that dealing enough damage will kill an entity.
In the last chapter we added ways for the player to interact with the world in our game. We can deal damage to and take damage from monsters. In this chapter we'll add some ways to provide some valuable information about the world to the player. We'll add user interface elements for displaying the player's current health, a log of events that have happened during the course of the game, and a way to get information about the entities visible on the screen.
In this chapter, we're going to add an inventory to our player character and give them the ability to pick up, drop, and consume health potions. We'll be building on the work we've done previously to add to our actor classes, create new entities, and show some new user interface elements.
In this chapter we'll add the ability to target enemies at range using various scroll items. This will involve creating new input handlers, new items, and a new AI type. We'll also add some UI handling for displaying to the player where they are targeting. However, before we add all that new functionality, we have some housekeeping to take care of in the form of refactoring once again.
In this chapter we'll add the functionality to save and load our game. Before we can add that important functionality, we need to do some more refactoring. I've been writing these chapters as I work through the Python version of the libtcod tutorial. I do the chapter from the Python tutorial, then implement that same chapter myself in TypeScript. Once that implementation is finished for the chapter, I write a chapter here on this blog. Because I haven't gone through the complete Python tutorial, I've made some assumptions in early parts of the TypeScript implementation that aren't fitting as well as I get further into the chapters.
In this chapter we'll be adding functionality for our players to be able to move in to deeper floors of the dungeon. We'll add a new tile type to represent a staircase down to the next floor, and generate a new dungeon when the player chooses to move down. We'll also be adding a progression system to the game allowing for players to level up and get stronger when they kill enough monsters. And the best part is......no big refactors this time!
In this chapter, we'll be updating our game to get more difficult as the player goes deeper into the dungeon. Each successive floor will have a chance of having more monsters per room and spawning more difficult monsters. We'll balance this with an increased chance for strong items.
We've reached the final chapter of this tutorial series. In this entry, we'll add weapons and armor that the player can add to their inventory and then equip. This equipment will bolster the player's attributes and allow them to hit harder or block more damage.