Read it like a book – Painless way of programming Game Modes and Skills (Part III)

Strategy is a meritorious pattern, and I think it may interest you. Why? Because you want your code to be flexible. That flexibility allows you, for example, to switch behavior with ease, whenever you like. You don’t want to replace half of the classes when the rules of your game change. Or maybe you want to have different game modes, and you’re struggling with switch statements all around the place? Strategy pattern allows you to code another game mode without the fear of breaking the rest of the game.

‘Read it like a book’ series

Part I – Centralized Control
Part II – What to do when Centralized Control does not work?
Part III – Painless way of programming Game Modes and Skills (this)
Part IV – Soon

Content

When you might need a Strategy?
Strategy Example – Player Skills
Strategy Example – Game Modes
One more thing
Summary

When you might need a Strategy?

Even if you’ve got only two game modes you’ll make use of the Strategy, because of the effortless switching between them in runtime. Cases where you’ll take advantage of the pattern, don’t have to be such big things like whole game modes, though. Maybe you’ve got a bunch of skills (mapped from 1 to 9 on the keyboard) that are used by pressing a key, but their behavior differs from each other fundamentally. One skill will increase the player’s HP; another one will change him into a super-fast blue tapir. All the skills have few things in common:

  • They all are used by the player the same way – press a key, and wait for an animation to end.
  • The class that uses them shouldn’t know the difference between one and another, so it won’t be dependent on their implementation – the skills are interchangeable.
  • They can be switched between the keys on the fly.
  • They change the player somehow, so they need a reference to him or a proper player’s interface. We assume that skills are very different, so we cannot extract common parameters for them. In that case, the best solution is to pass the player’s object to them (if a ‘Dependency Injection’ term came up to your mind, you’re damn right).
  • You want to add/remove/update skills independently from the rest of the codebase, and you probably wish to have a painless way of doing that.

Let’s see how the Strategy pattern looks like in general:

You’ve got a Strategy abstract class that the Context uses. Concrete strategies derive from a Strategy to define a particular behavior. Each of them has its class so that they can be defined independently.
Context is configured with a concrete strategy by another class or by itself. It delegates the operation to its current strategy class to avoid switch statements here and there.

Strategy Example – Player Skills

Below you can see how the Strategy may look like when put into the player’s skills scenario:

The most important question now is probably ‘How to configure the Player with a concrete PlayerSkill class?’

The simplest solution is probably to call an event in SkillBar script every time the player had pressed a proper key. Catch that event in the UIController, which has a reference to the player, and cast a chosen skill from there.

The above solution lets you add many skills without worrying that it’ll affect the rest of the game. You don’t have to have switch statements with a case for every skill. You don’t need an additional enum field in skills or dynamic casting to know which skill is it. You may have a few other programmers working on their skills implementation without interfering with each other. How does it sound?

Strategy Example – Game Modes

While PlayerSkill relation is quite ephemeral (we’re using a skill and moving on), Gameboard will definitely keep a reference to the GameMode through the whole play:

Gameboard delegates a few different operations to the GameMode Strategy. We’ve got a Chess game and two modes: Classic and Battle.
Classic:
StartGame(): Set up chess normally.
EndGame(): Clear out the board and show statistics.
OnPlayerMoved(): Switch active player

Battle:
StartGame(): Set up chess and randomize positions of a few pawns for both players.
EndGame(): Clear out the board and show statistics (same behavior as Classic).
OnPlayerMoved(): Disable random empty field, so the chess cannot be moved there.

And Gameboard doesn’t know about any of that. It is initialized with a particular GameMode depending on a button the player clicks. All its operations which behavior depends on a game mode are delegated to the Strategy pattern. Do you need a new game mode? Create a new class that derives from a GameMode, implement its abstract interface and place a new game mode button in the menu. Simple as that.

One more thing

It is worth to mention one more variation of the pattern. If you’ve got many operations in the Strategy and a bunch of game modes that differ only in one or two of them, you can have a default game mode with virtual methods. It would be placed between the abstract class (GameMode) and concrete strategies (Classic and Battle). If your game mode doesn’t change default behavior it doesn’t override its method.

Summary

Today, we haven’t mentioned the Singleton. The Strategy MIGHT help you avoid using Singleton, but it isn’t its primary purpose and the biggest advantage. However, it is a very precious tool in your arsenal as many games would make a very good use of it. In the next post, you’ll see a design pattern that is very similar to the Singleton but somehow better. It should fill all the gaps that we haven’t filled yet.

And now I wish to ask you for advice. Tell me how do you feel about the Games Architecture. Do you think that I should change something, or everything is perfect for you? Maybe you’ve got a particular problem and want to share it with us so we can think how to solve it together? I’m here, and I can hear you.

Share these goodies:

4
Leave a Reply

avatar
3 Comment threads
1 Thread replies
191 Followers
 
Most reacted comment
Hottest comment thread
4 Comment authors
DimaRuhan BelloBartoszJediPanda Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
JediPanda
Guest

Hey It’s me again… every now and then I keep following your blog to see if you post anything new and every-time I see a new post I jump in an read it carefully and I can say it’s really enjoyable. In regards to your last question, or better said, invitation to ask or share anything. I just want to say that for the past several months I’ve been trying to learn all these design patterns(command, observer, singleton, strategy). I had ran into really good books and even tutorials from premium websites, YouTube and so on. Now maybe is just me, or I maybe the way I organize myself to learn this just doesn’t seems to work good. When reading this or watching a tutorial, even following along I’m understanding and feel like “ok, this is how it works, I’ve managed to do it.”. However, in practice when I start developing a game or an app, I don’t really know how to apply all that I’ve learned, its like I keep doing the stuff that I’ve don before, something like, “do it like this, it works” and not really think of any design patter for that matter(except for singleton pattern,… Read more »

Ruhan Bello
Guest
Ruhan Bello

Hi!
Unity3D does have a tutorial about a “pluggable AI”, that does this:
You have a base MonoBehaviour class that choices what behaviour that entity will use, based on scriptable files.
It is like “Ok, now I want my entity to be more aggressive, so my MonoBehaviour will point to the AgressiveScriptable and perform its behaviours based on that. With a simple “drag and drop”, the agressive behaviour can be switched to a more peaceful behaviour, for example”.
Is this an example of the Strategy Pattern?

Here are the videos about what I mentioned:
https://www.youtube.com/watch?v=cHUXh5biQMg&list=PLX2vGYjWbI0ROSj_B0_eir_VkHrEkd4pi

Dima
Guest
Dima

Hi!
Where is part 4?