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 Player
–Skill
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.
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 »