Tutorial systems are a part of game design that can’t be avoided. You’ve developed the game so you know it inside and out – its the most intuitive gameplay in the world! However, others who play your game will have had no exposure to it and thats when the cracks start to show. You need a way to impart your knowledge to the player in a format that is easy to understand.
In the past I’ve put a twist on the standard screen of text. This is probably one of the least effective methods of imparting knowledge (due to players looking for instant engagement). When it came to Astro Noughts, I had originally planned on creating a playable tutorial which would guide you through the gameplay mechanics. Whilst this would no doubt be optimal, two things struck me. First – its a lot of work, and second – my game is fairly small in scope and may not warrant such an investment from the player. There are also other considerations with this style of tutorial, like how is it accessed? how long should it last? is it skippable? etc.
It occurred to me that most of the gameplay in Astro Noughts is easy to understand and can be figured out after a few plays. There are however, some hidden controls that are not immediately apparent. What I’ve ended up settling on is a dynamic hint system. This is not a full blown tutorial but instead a system that dynamically collects data about the player and displays hints as and when the player is struggling with specific elements of the gameplay.
I’ve set myself a deadline of the end of November for submitting Astro Noughts so I’ve kept this system light and to the point. Nothing fancy, and its not terribly reusable either. The code isn’t worth sharing but I will take you through the basic setup and how it works.
What you will need
- A HintSystem class (I’m using cocos2d so i’ve subclassed CCNode otherwise you’d probably create it as an NSObject)
- A handful of integers and boolean values (for recording data)
- A game loop that will check the HintSystem periodically (I already have a 1 second timer running for less strenuous tasks)
- The patience to add hooks in the appropriate places in order to populate the player data
How it works
Its really very simple. I’ve created a HintSystem class. Within this I’ve added appropriate integers and booleans to store data about player behaviour. For example, I have an integer called planetsCollected that stores the number of planets the player has collected in the current game. Conversely I have an integer called planetsMissed to store the number of planets the player hasn’t managed to collect. I also have variables for each of the power-ups, recording the number of times each is collected and the number of times they’re used.
I create a single instance of this class within the init method of my main game code. Then, in order to record data about the player, I’ve simply located the appropriate places in my code and incremented the variables within my hintSystem instance. For example, in the code that detects planet collision, I make a call to the hintSystem to increment the planetsCollected integer.
Back in the HintSystem class, I have a method that returns a hint as an NSString. The method just checks for a series of simple conditions and returns the appropriate hint. For example, it checks to see if the planetsMissed integer is greater than 5 and the planetsCollected integer still equals zero. If this condition is satisfied, its safe to assume that the player is struggling with the core gameplay mechanics, so it returns a hint explaining how to collect planets. Likewise, I have test conditions for the power-ups so that if a powerup is collected but never used, a hint is returned explaining how to use that particular power-up.
Moving back to the main game class, in the 1 second loop I mentioned earlier, I’ve added a call to the above method. If a string is returned then it passes it to a hint box and displays it on screen. If its doesn’t return a string then it hides the hint box (because the conditions in the method have now been satisfied).
The system works because a player who is quick to pick up the gameplay elements will never see the hints. A player who doesn’t understand the gameplay at all is likely to see all of the hints. And then there are the shades of grey, players who have picked up some elements of the gameplay but not others (for which they receive hints).
You could extend this system further by making it a Singleton and having methods to store the data between game sessions. You could also mine this data, sending it off to your server for later analysis.
What does it look like in action?
Here’s an example of a hint in Astro Noughts (These are a work in progress). It shows the hint that appears when a power-up appears on screen but doesn’t get collected. I’ve intentionally kept them fairly unobtrusive but you could of course make them flashy.