Hi Xander here….
This post is about the design and build of our Text Adventure game over the course of a week. This was a “proof of concept” project to make a framework for a text based game that could be re-used and expanded on for future use. It’s not a polished game but an exercise in execution – and a jolly fun one at that.
The main features of the game are:
A simple 2D UI with Directional buttons an Action/Attack button, and a “Show Map” button. A HUD bar at the top with Player HP (hit points) the outcome of combat interaction (Player vs Monster) and during combat the Monster HP.
A large text area for describing your location and the environment around you. This area also shows the random actions taken by both Players and Monsters during combat.
A map that is gradually exposed as you explore the game.
This is the starting layout (digging the “panelled wood” feel here):
In the Scene the main Game Objects are:
The Canvas for the UI.
An InputControl object to handle what happens when a button is pressed and provide the appropriate response.
A FightClub object to handle combat events.
Another Map Canvas to show the map and hold all the map components.
And what I call the WayPoints which are the different locations and events that can happen during the game. Each one gets a new object and in this sample game there are Thirty Four of these nodes. These objects hold all the information about a particular location including which WayPoint is next in any give direction and what Monster if any appears here.
This is what it looks like in the explorer:
I’ll go through the main scripts one by one.
I will also put all the scripts in our GIT Repository (link below).
This is a custom class that mostly just holds data about a given location and only if required Generates a Monster. See the example below (which shows a section of the full details):
The first boolean tick box Way Point Visited let’s the InputControl script know if an area has been explored before. This allows alternate short descriptions of the location (which makes navigating known areas faster) and is used by the mapping component to tell if an area of the map can be revealed or not.
The Name, UID and Description fields are not actually used but I added them in for future use. Since the Object name includes a UID and is a descriptive name (Eg. 06_StatueFight) I didn’t really need them for coding.
The Write_rate and Text_size are passed to the Main Printing System (also attached the InputControl object) so that there is some control over the speed and size of the text that prints on the screen like a typewriter for managing the pace of the game. Faster and larger for combat and exciting events and slower for more descriptive passages.
The Text Sections are self explanatory. When a Player enters a location the first time or a repeated time this is the text that is printed.
WayPoint _forward, _backwards, _left, and _right point to the name of the next WayPoint object in that direction. If it’s NULL then there is nothing in that direction.
The rest of the script is for defining if a Monster spawns in the given location, it’s attributes, and the text options passed to the FightClub combat module (each Monster has different attack and defence descriptions to make it more variable and exiting).
The WayPoint script has one Function called GenerateMonster() which when called by the InputControl system does just that with the info in the WayPoint class for the monster we defined above).
Input Control Script
The Input Control Script handles input from the four directional buttons (Forwards/Backwards/Left/Right or North/South/East/West), the Action/Attack button and the Map button. The Map button shows the map canvas and the progress the player has made within the dungeon. The Action/Attack button is only used once the Combat feature is triggered. The main body of the script is for handling navigating around with the directional buttons and triggering special events attached to some locations.
The Current Waypoint variable is the most important piece of the whole game system. It holds all the data for the current location such as the available text to print and if there is a Monster to fight or other special action.
The next public variables hold references to all the components we will need in the Input Control Script: The Combat System (FightClub), the UI buttons, and the Map Canvas.
We also have two bools. One to let us know if the game has just started so we can show the appropriate text and one to let us know if there is a Monster present (so we can initiate the Combat System).
The Generate Map function in this script does a find on all the WayPoint objects in the game and collects their names. Each map piece is tagged with it’s related WayPoint name and if the “visited” bool has been check it displays that part of the map.
Print Main Text
This is the printing workhorse of the game. It takes the input from the WayPoint (and a text size and speed of typing) and prints it out on the main screen like a typewriter.
It handles all the printing to the other smaller text components as well like the Title, HP and Combat stats.
This script is made into a Singleton so it’s easy to call from all the other scripts that have printing needs.
The Fight Club script is the combat system. Very simply the Player and any Monster gets a maximum and minimum limit to their random integer attack. The player gets an optional “Weapon bonus” if he/she picks up a magical sword during the course of their adventures which adds the random int. Whoever has the higher number wins. The value of their integer is also the amount of damage done. Damage is done against another integer (Hit Points or HP) which if it reaches 0 indicates that the combatant has died (usually horribly).
This is the public behaviour of the script:
The Monster’s HP and Min/Max Damage is recorded in the WayPoint for that location and passed from the MonsterStuff class that is attached to the Monster.
The Monster Stuff script is attached to a Monster prefab and is instantiated when a monster spawns. This is the behavior:
As you can see it’s the same sort of stuff that the Player has in the Fight Club script (HP, Max and Min Damage) but there are also arrays of text fields. The Monster prefab gets passed all this data from the WayPoint script on instantiation so they are really just placeholders waiting for data.
The Dead bool is pretty self explanatory – you couldn’t get more boolean!
The Monster Stuff class presents four functions:
MonsterAttack(), MonsterTakesDamage(), MonsterAttackText(), and MonsterDefenseText(). The attack and damage functions return integers for calling from the FightClub and the text functions return the appropriate text to the FightClub. Each Monster has its own special attacks and defences so the text generated for the fights is unique. The attacks and defences are arrays so you can expand the available text options at will thus making the game more interesting and variable.
That is basically all the scripting that there is to the game! It’s a Text Adventure so most of the work goes into the writing and the story that you build into the WayPoints. It’s pretty light and flexible and able to be extended a number of ways.
There is also script to open the map and close it and to reset the game back to it’s starting position but I won’t talk about them here. They are pretty generic.
All of the code is available publicly on our GIT Repository: https://github.com/zuluonezero/AdventureText