Today many games need tutorial. Tutorial is a hot topic for discussion in indie games community. Anyhow, for programmer-non-designer tutorial implementation is just a job which comes with unwanted problems. Most of them appear because it tends to be made in the end of project. And worst situation is when tutorial is being done incrementally.
I will not discuss topic of tutorial design. Instead I'd like to present some notes about coding a tutorial in online game which are derived from my experience and observations. In the end I'll give my advices for coding tutorials.
Case study - what they wanted
Many design requirements - such as "tutorial has to be short"- do not have much influence on programmer's job. But there aren't few which really do have. Some typical technical requirements for tutorial are:
- first sight (yeah, it's not technical req.) of game is important so account creation procedure has to be short, so...
- ... so tutorial could be offline (and here it turns out as a technical problem!), even if game normally has to be connected with server. That's becase game could be disconnected in the moment of tutorial finish.
- standard but parametrisable content of windows/screens
- pause everything in extraordinary moments and:
- highlight some elements or grey out some others (shader? may harm your performance on mobile platform!)
- display texts/hints, tutorial characters' talks
- display arrows, pointing hands or fingers etc.
- and wait for user random (anywhere on the screen) or desired (pointed button) input
- revert to latest done step in tutorial in case of application reset
- skip some steps
- ability to watch/play tutorial later
- some player stats has to be greater than zero, for example player has achieved some gold in tutorial - it still has to be accounted after tutorial is done
- count steps done in tutorial for analytics purposes
Probably many more. Every little requirement creates some little storm. Sum of little storms is a big hurricane. You're in best position if minimum 80% of those are known at the start of tutorial development. But that may not happen so it's best be ready for everything.
Case study - what I did
As I said before, tutorial development is often done after the game is done. That implicates the fact, that it's not technically planned. That was why in my latest projects I had to improvise by giving many workarounds to not change much of engine or game but rather "add" tutorial into the game.
It was really hard to "just add" tutorial which often breaks rules of engine or game logic, having also an requirement to try not modifying game code. But we did it and I'll list out some workarounds from the latest project (warning! very project-specific):
- most of game architecture was done such way that logic was cut off from visualization. Due to lack of technical leader that was a proposition rather than a requirement to code using state machines - which were making network requests - and implement windows code not making network requests but receiving data from states instead. Unfortunately, it ended that I had windows directly calling server for some information. Of course I didn't want to change it.
What I did? I have done dependency injection to implement fake responses to requests for those windows. It's a hack but worked for a long time and lived well commented.
- this one will be big and strange. Behaviours of windows in our game were implemented by programmers but window elements were mostly set up be graphics people. We still didn't want to change any game code but also we didn't want to reimplement twice the code of window behaviours (normal window and tutorial window) when design had to be (even slightly) changed.
We planned to make class deriving (example: class TutorialBossBattleWindow extends BossBattleWindow) but windows were created by names based on class names due to file names. We couldn't create additional file (example) "TutorialShopWindow.json" because it would break our architecture of WindowManager (which sucked, anyway). What I did was to create another factory and put into the manager. Also not every window could have implemented correspondent tutorial version, so I implemented WindowManager to use first tutorial factory (only in tutorial state machine!) and if it didn't success - then it tried to create normal window. So it created "ShopWindow" if "TutorialShopWindow" didn't exist.
- in tutorial we didn't have state machines. It was only TutorialState in there. But there were some old windows (and again - not much time to refactor those) which used some other managers to request online server for data.
I made fake managers deriving from original ones. I also injected some fake data through "WebSocketConnector". The latter had to be cautiously clean()'ed.
- there were also managers made for tutorial which simulated series of requests and game behaviours, such as camera and avatar movement on chosen tutorial map.
- I didn't want to modify anything due to registered listeners, especially button tap listeners. I made "TouchRegionFilter" which was a configurable fullscreen transparent quad, blocking touch requests in all places abroad specified fragment. There were only single cases where we had to remove swipe listeners for page swiping.
- Due to collaboration (I wasn't the only one implementing tutorial) I didn't want to make class functions calling other class functions and since tutorial was planned to be linear, I've coded TimelineBuilder (based on Builder design pattern) where I have implemented functions such as pointHandAt(x, y), showWindow(type), showTutorsTalk(id) etc.
That was very easy to use because there were few class functions and listeners.
- Skipping tutorial steps. Timeline is best here. I just call clean() on current window and go to next one.
- Analytics. Measure how much steps the player did (and sending that through network) in tutorial. It's easy to write one such function and put it into timeline mechanism.
And again - there were many, many more problems and workarounds.
My advices for coding game tutorials
Since it's not always easy to take a lesson from case study I will present my advices for coding tutorials which I believe aren't that much project-specific. Instead, those are very universal - in my opinion. Let's go:
- possibly do not change any code of the logic or overall architecture in the game. It's better to derive and reimplement things, add them as optional things which could be removed at any time for any reason.
Especially when the rest of team still develops some other features. In my opinion it's even better to make hacks (by commenting and remembering them!) and not modifying the game at such times.
- it's best to know where in timeline you are in the tutorial. I do not recommend to implement classes for each state but rather implement some timeline builder. Why? I've seen classes such as Tutorial1, Tutorial2, Tutorial1AndHalf. It didn't help.
- It's best to not over-script it because it may take too much time and still being buggy. Don't make universal scriptable system, probably it will never be working while constantly changing.
- every tutorial step of tutorial should cleanup memory, data etc. after it's job is done and before next step begins it's work. If it's a programming language with Garbage Collector - don't worry, there's still much to be done (nulling references, for example).
- remember that every parameter of your configurable tutorial can be overused be designer. So don't create/implement parameters that are hard to be done and are not crucial. Also try to comment on parameters broads in documentation.
And the last one but very important - 6. don't leave your "hacks" alone. Bad code should always be commented and assigned to someone in task manager to be repaired.