Finally, we are finished with the individual components of the game (at least up to the complexity suitable for this tutorial), and can move on and actually create something playable! Now then, most of this section will deal with integrating all the classes we’ve built into main.cpp.
After the game has started and the preliminary setup is complete (entities loaded and prng seeded), the player needs to be able to select their save file, or create one if they haven’t played before. The startGame function will do this for us by first asking for the name of the player’s character. It will then attempt to open a JSON file with that name (remember each Player is saved to a JSON file named as they are). If it can’t open the file it will ask the player for their class and will create a new Player, otherwise it will load the existing one from the file.
We’ve made use of a few more headers here—specifically iostream, fstream (for std::ifstream which we use to test the existence of the JSON file before opening it properly with JsonBox), "dialogue.hpp", and "player.hpp"—so make sure to include them and also declare a prototype for the startGame function. A very simple
in main and the player can create their character! Now we can create the game loop, which is where all the actual gameplay will take place. All game loops share a very similar structure; they read input from the user, process the input, update the player and environment accordingly, relay those changes back to the user, and then start again. The amount of time spent in each stage depends on the game (a chess game will barely use the first stage but will dedicate a lot of time to the third, whereas an FPS would spend a lot of time in the last stage), and here we care mostly about understanding and processing the user’s input.
Here is main in its entirety.
After creating (or loading) the player we position them in the starting area, and start the game loop. Firstly we add the Area the player is in to their list of visited areas so that any changes they make to the area will be recorded in their save file. Instead of implementing a save menu or save location mechanic, we just automatically save the game on the next line. We don’t want the game continuing if the player has run out of hit points, so next we check that they’re still alive and end the program if they aren’t. Now that we know they’re alive, they can start to move their character around the world.
Each iteration of the game loop will be another action that the player can take; attack an enemy, go through a door, and so on. We therefore present to them the Dialogue of the Area that they’re currently in, but make sure to add options for all the Doors that are in the Area, because the Area class didn’t handle that itself. We also add an option to search the Area, which will move any items in the Area’s inventory into the player’s. That’s the first data presentation stage done (ours is split into a before and after stages), now we read the input from the user.
Thanks to the wonders of the Dialogue class (it’s so small but it’s so useful!), parsing the user’s input is extremely easy. And what’s more, because Area didn’t add the Doors to its dialogue we automatically know how many non-door options the Area has, as well as how many door options. This makes determining the type of action that the user is performing very simple. (Although we still have to leave it up to the Area to deal with non-door and non-search actions.)
If the player chose to go through a door, we use the traverse member function to move them to the next area (if possible) and report back how their traversal attempt went. If they tried searching, we print a list of all the items in the Area and move them to the player’s inventory. Finally, note that we’ve allowed the program to understand an input of 0, even though that wouldn’t be an option on the Dialogue. We briefly mentioned this in a previous section, but now we’re putting it into practise by calling a dialogueMenu function which will open a menu displaying some useful information about the player. Before we define that, try commenting it out and running the program. Hopefully you’ll have a nice little RPG game!
Did it work? If it still didn’t work after fixing compilation errors, compare yours to the source or send me an email. We’re not done yet though, there’s still that menu to create, for starters. It’s a bit of a long function, but it’s really quite simple.
The menu has three separate submenus to it, accessed via a Dialogue; "Items", "Equipment", and "Character". The first simply prints a list of all the items that the player. The second is more involved, and as well as printing all the armour and weapons that the player has equipped, it also asks the player what armor or weapon they would like to equip. Entering 0 again will cancel the action, and take them out of the menu. The third and final submenu prints a nicely formatted information page about the player character, listing their various attributes and the amount required to level up.
It’s at this point we really have nothing more than a walking simulator, to be honest it was a bit of a stretch to call this an RPG. For that, we need the battle system!