Gamasutra: The Art & Business of Making Gamesspacer
Design Patterns in Game Programming
Printer-Friendly VersionPrinter-Friendly Version
View All     RSS
April 23, 2014
arrowPress Releases
April 23, 2014
PR Newswire
View All





If you enjoy reading this site, you might also want to check out these UBM TechWeb sites:


 
Design Patterns in Game Programming
by Michael Haney on 09/20/11 03:34:00 pm   Featured Blogs

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.

 

Preface

Before we start, you should know that the definitive book on design patterns is Design Patterns: Elements of Reusable Object-Oriented Software. My disclaimer is that I am but a student of Computer Science...don't take my word as the end-all be-all. This article (like many of my articles) will be but a scratch upon the surface of this subject. That being said...let us move on.

Motivation
This is a topic I've been struggling with myself. We know that in object oriented programming, design patterns are tried and true solutions to problems we encounter. However, we usually don't employ design patterns to solve problems, we employ them usually without knowing it or because it seems like a good idea and we were taught to do it. This might be ok because it helps us avoid problems, but it simultaneously masks the problems we're (unknowingly) avoiding and makes it difficult to understand why the pattern exists, or why we would choose one pattern over another.

What a Design Pattern Is
Design patterns are generalized solutions to generalized problems that occur with some modicum of frequency when you're creating software using the object oriented programming paradigm.

Why Use Design Patterns
The most basic and condescending answer is: because these solutions have existed for a relatively long time and many experts have used them, they're likely better than any solution you could come up with on your own. And even if you did come up with a solution on your own, it's likely already a design pattern in some way. Knowledge of contextually pertinent design patterns helps you to make good architecture and design decisions.

Common Game Programming Patterns
  • Singleton - You create objects that ensure that only a single instance of which can exist at a time. In my game Total Toads, this is the design pattern used because it was easiest to fit with cocos2d's design. For example, in cocos2d, there's a Singleton CCDirector, CCSpriteFrameCache, etc. It seems this is an often-used panacea in game programming. Though the general consensus seems to be that it isn't a panacea so much as it is a cancer because it actually masks poorly designed architecture. You should probably avoid using this design pattern if you can because there's likely a better way to design the architecture of your game. This can avoid the problem of having multiple instances of objects of which there should only be one, like a "Player" object in a single player game.
  • Factory - You create an object whose purpose it is to create other objects. For example, you can have a factory class called "GameObjectFactory" with static (possibly parameterized) methods to create other game objects like a "Player", "Enemy", "Gun", or "Bullet". The latter classes might have complex constructions that make obtaining a instance of that specific class difficult. The factory can take care of the object's complex configuration (adding to an object pool, adding to physics engine, etc) and simply return a reference to the created object. This pattern helps you avoid the problem of complex object instantiation by keeping these complex configurations in a single place, rather than scattered around in your code.
  • Observer - The object in question maintains a list of other objects that are interested in its state and notifies these listening objects of a change in its state. In Total Toads, we have 3 Frog objects and 3 FrogAnimation objects that can control the animation of the frogs based on their state. In this case, the FrogAnimation objects are observers of the Frog objects. Every time the state variable for a Frog changes, it notifies the associated FrogAnimation object to notice the new state and take an action if necessary (like animating the frog). This pattern helps you avoid the problem of event notification in your game. Since games are user-interaction driven, objects can change state at almost any time. When an object changes state oftentimes that object needs to be animated or have other objects change their state with respect to the new state.
  • State - You have an abstract (empty implementation) class that has subclasses to define the current state. An example of this might be a first person shooter that has a "Player" class who has several possible states like "PlayerInCombat", "PlayerOutOfCombat", and "PlayerInMenu". When the state is changed, the player shall be represented as an instance of the appropriate state class. When the player starts to be shot at, the player object "switches" to an instance of the PlayerInCombat class to take advantage of that class's implementation of the mouse's left button click which makes the player able to shoot their gun. Similarly for the "PlayerOutOfCombat" and "PlayerInMenu" classes, where the mouse might allow usage of items or the clicking of menu options, respectively. This pattern helps you avoid monolithic methods that perform differently based on the object's state by having a bunch of switch or if/elses in your code. Instead, the object just changes and runs its appropriate code. This also simplifies your code and allows you to more easily find problems in your objects behavior since the state is right in the object's class name.
Thoughts
I don't pretend to be an expert game programmer...I'm nowhere even close to one, my first game hasn't even hit the market yet! However, this subject seems to not be extremely well represented or explained on the internet...and I would love an expert book on this specific subject. There's many more patterns than the ones I explained here, and you can find ok explanations in my below references. I'd appreciate it if some experts mentioned additional patterns that should be covered and why.


References

Related Jobs

Turbine Inc.
Turbine Inc. — Needham, Massachusetts, United States
[04.23.14]

Director, Analytics Platform Development
Gameloft Toronto
Gameloft Toronto — Toronto, Ontario, Canada
[04.23.14]

Technical Artist
Muti Labs
Muti Labs — Santa Monica, California, United States
[04.23.14]

Senior Game Engineer
Digital Extremes
Digital Extremes — London, Ontario, Canada
[04.23.14]

Programmers






Comments


Fernando Fernandes
profile image
Michael, thanks for posting this. I find it very useful. And I do agree, this subject isn't well explored on the internet / books / whatever. During my personal research on the topic, I hit two articles, kind of outdated but may be useful for someone (maybe as starting point?):



- http://gameprogrammingpatterns.com/

- http://www.mine-control.com/zack/patterns/gamepatterns.html (mentions MVC, which is nice (:)



As far as I can tell, it seems that the State Patter is pretty common (and I can understand why: http://www.gotoandplay.it/_articles/2004/08/statePattern.php).



Again, thanks for posting.

Michael Haney
profile image
No problem, it was my pleasure. If anything, I wanted this post to be a combination of research and analysis. If it helps someone out, then I did my job.

Wesley Paugh
profile image
Great post! Here's some of my experience with the patterns you've listed:



Singleton: Cocos2D's Director does kind of feel like a replacement for what might have been a separate library. When it's used to just swap scenes in and out, it feels fine, but it's also the place to go to for input registry, screen->scene coordinate mapping, and even a degree of hardware access. (More recent updates than I've worked with have surely addressed some of this). Their TextureManager class is an excellent use of a singleton, in my opinion; it provides a safe, simple and secure way of making sure that only one instance of a texture object can ever exist (at least, as long as you only use the sprite and atlasnode abstractions provided). This in itself could be the subject of an article on how 'better' architectures might affect secondary requirements like performance benchmarks or memory limits.



Observer: My most recent game was designed entirely around using this pattern as an event system. We had one MessageRouter (a Singleton) that registered listeners for messages that interested them (Actors registered to listened to incoming attack events, the Hud registered to listen to changes in player health, etc.). It worked really well for our tile-based, turn-based game, but I'm not sure it would have been as reusable a solution in a continuous-space, real-time world. I'm not sure how it would work for an Animation system; our animations (and most animation systems I've heard of [like, 2 others]) were driven by registering with a scheduler, updating a timer count each tick, and switching frames after the period of time specified by the animation system.



State: Think very carefully before using this. In our game, we had a Genie boss fight. The Genie started in a Floating state, and then had a Lamp state in which he regained health, and a Floating state after his lamp had been destroyed. He would switch between the first two, could transition to the third from either, and could be killed in either the first or third. The state he was in affected the abilities he could use, the abilities that could be used against him, and the rate at which spawners in the room could spawn minions.



The most restrictive requirement of all was that, at any point, the player could quit the game and resume at the exact same moment. Even after weeks implementing the abilities and getting a state machine to transition properly between Floating, Lamp, Cracked Lamp and Dead states, and affect all the spawners and abilities (since neither had state information that was implemented at a savable model level), even simple requirements changes meant hours more tweaking and testing. Stuff broke for months.



tl;dr State Machines can save you time and are cleaner, if you're looking at a really complicated set of states and have either lax save / load requirements or very little data & relationships that can't be serialized. Otherwise, some extra bools, ifs and elses are well worth the extra bloat and time spent commenting it to a comprehensible level.

Jonathan Jou
profile image
I'm not sure I get your State Pattern usage; as a stout believer of design patterns I don't actually believe this is a case of a misused pattern as it is a misrepresentation of responsibilities. The fact that you combine states into a large switch/case statement or if/elses is generally harder to read, regardless of how well commented compared to separate classes, especially when it happens in multiple functions for any number of states. An UpdatePosition, UpdateHealth, and UpdateSprite set would be more than enough to justify separating classes for as few as two states. It's definitely the case that the State Pattern is one that would fit well when it comes to a Boss who behaves very differently in each phase. Let me see if I have the phases correct:



Dead <= Floating Lamp => Cracked Lamp => Dead



In order for the State Pattern to be used correctly, you'd need some way to be able to transition between them, which would be a class which knows the "Current State" and has access to the other states. It's not a good idea for State Classes to know about other State Classes, and even worse idea for State Classes to actually transition from one to the next. It's a good idea for them to have access to an enum in which you define all possible states, and perhaps a function called every cycle that returns the next state to transition to, but I'd need to hear more to even have a guess as to what data needed to be saved, and where the complexity arises.



I'd be really interested in hearing more about your problem, because my guess is I'm wrong, and I'm always keen on learning from other people's experiences!

Wesley Paugh
profile image
I'll try and explain without getting to far into the specifics of the entire game's architecture.



Actors and ActorControllers exist. The former have health, energy, name, and other serializable modelly type data. Their controllers are updated with events about incoming attacks, switches being triggered, cutscenes, and other in-game goings on. Controllers also house Command objects for the abilities an Actor can execute each turn, and are polled for their decision on how to act each turn. These abilities weren't serializable when the problem was first tackled (and they still aren't, except in the case of the player, but I digress).



So, GenieController became a special subclass of ActorController, because it had enough special-case logic to justify it, and my first attempt gave GenieController a GenieStateController, which managed GenieState objects. As for why it was necessary to give GenieController a state machine, rather than MAKE geniecontroller a state machine, here's the reason: GenieController had plenty of Genie-specific logic to override from ActorController to deal with the fact that it was a multi-tile actor (most actors occupy only one tile). I wanted to keep all the specifics about how to play a death animation or how to apply and unapply buffs to an actor (which are all unrelated to the state workings) abstract from the state stuff. So, GenieController was given, rather than made, a state machine.



GenieStateController initialized the state machine with a floating state. Here were the complete set of transitions:



Floating => Lamp. Precondition: lamp health > 0. Trigger: at least 8 turns had passed and a random roll succeeded that turn ) Post-condition: spawners have increased likelihood to spawn minions.



Lamp => Floating. Trigger 1: at least 10 turns had passed, and a random roll succeeded one turn. Trigger 2: Lamp health < 0. Trigger 3: Player was standing on a spawner in the room causing an attempt to spawn a minion failed. Post-condition: Spawners have decreased likelihood to spawn minions.



Floating => Dead. Precondition: Genie health < 0. Trigger: None. Post-condition: Spawners deactivated.





So, the interesting updates to these conditions that GenieController was registered to listen for (e.g. an actor taking damage, a turn passed, something failing to spawn) were forwarded to the GenieStateController which, in turn, forwarded these messages to the current GenieState. The state would modify its internal state and, if necessary, return a new state to the StateController to accomplish the transition.



So yes, states were aware of one another. I have heard of both ways of doing state machines, but it just made more sense to me to let states know about the states to which they're connected than to have the StateController make the call about how to transition based on the internal workings of each State. I see arguments both ways, but I instinctively try to pull logic as deep into the model as possible.



Not only did states need to be updated with world information as it came in, they needed to be polled for decision-making information by GenieController each turn; the turn system would ask GenieController for a TurnAction each turn, and that decision would be different depending on the state of the machine. I could (and should) have just had a few if-elses for what to do if the genie were floating or in the lamp state, or if the lamp was live or dead, but this would have been ignoring the advantages of having a proper state machine (namely, abstractly polling a state object for the appropriate behaviour).



So, a call to decideTurnAction also got forwarded GenieController->GenieStateController->GenieState to decide if the Genie should hurl a fireball, spawn a monster, pass a turn, etc. The best I could do was to pass Ability IDs in and out of the States, and have GenieController associate a state ID with the actual ability object. In retrospect, I probably could have given States references to the actual ability objects, but I can't guess what that might have entailed. In any case, the ID approach required the information be updated as requirements changed in each state that cared about the boss' abilities (2/3 of them), and paired correctly with the code in GenieController that mapped that Data to the abilities.



As for actual state information that needed serialized: 1) references to the spawners in the room (so that their likelihood of spawning minions each turn could be changed when transitions occurred). 2) The number of turns that had passed in the given state, so that states could continue the same delay before transitioning to a new state. 3) References to the Genie / Lamp, so each state could react appropriately to them being killed.



I suppose the actor references could be re-referenced manually when rebuilding the state machine after a reload, but manually recreating states also seemed to be requiring more responsibility and knowledge of the code that rebuilt the state machine.



The biggest wrench in the works were some of the assumptions I made about how the genie behaves. The early requirements had the Genie himself spawning monsters OR shooting fireballs, and so SpawnMonster became one of the Genie's abilities. A state could make a decision to do one or the other just fine, but when the requirement came down that both needed to happen simultaneously each turn sometimes, the only solution was to make spawner 'monsters' that had to be retrofitted into this state machine. The fact that the game didn't yet have spawners meant retrofitting a somewhat jury-rigged solution for spawners into a state machine with other changing requirements about what could cause transitions (does the player need to just step on a spawner, or does said spawner have to fail to spawn because of it? etc etc)



I think this whole state machine wound up taking about 3 days to develop initially, but easily a week in debugging the save / load code as requirements changed. I also tried to factor BossController out of GenieController as we the other bosses were added, which might have been a mistake. The Genie, Satan and the Dark Pope shared less and less over time as their requirements changed, and I might have been better off with distinct classes that shared utility objects like cutscene dialog boxes and the like, rather than make those objects Parent class features. I ended up sharing more bugs than features.



In any case, were I to do it again, a state enumeration for Genie, Floating and Dead would have done just fine. When decideTurnAction was polled on GenieController, I could have had it check which state was current and return the right turn action. One single, serializable state class could have housed this enum, the turn counter, and the necessary actor references, and GenieController could have updated this one state object directly as needed. It's hard to tell if that approach does, in fact, qualify as a state machine; it would be transforming one state object into other state objects, rather than replacing a state object with other objects of different state classes.



Hmm, maybe this should have been its own blog post.

Dustin Chertoff
profile image
I've typically seen the Observer pattern described in the context of Model-View-Controller (eg http://content.gpwiki.org/index.php/Observer_Pattern). The biggest advantage is keeping the visualization of data separate from the modeling of the data, which is separate from the input controls that will manipulate the data.



The nice thing about MVC is that other design patterns can still work with it. You can have a Factory generate new instances of a Model and assign the generated Model to a View. Changes in State are updates to the Model code (so the model might go into a "dying" State which loads some new set of art or queries some particle Factory to display an effect). The View is not concerned with tracking changes in State, it just renders whatever the Model is currently holding.



The main downside to MVC is that you can end up over-designing your code. Sometimes its just easier (and potentially more efficient due to OOP overhead) to have update and render functionality in the same class. This downside seems to go away as you get more experienced with the pattern though.

Michael Haney
profile image
awesome commentary! it seems maybe that i should write individual articles for individual patterns. additionally, any patterns in use i didnt mention?

Andrew Grapsas
profile image
Builder, Facade, Adapter, Command, Strategy, to name a few.

Glenn Storm
profile image
[just a bark from the peanut gallery, not from a programmer, but someone who plays one on tv]:



The term 'design' is used in many contexts, having different meanings, although there are many crossover concepts, including design patterns. These refer to patterns of designing the architecture and component systems, down to the nitty gritty; but make no mistake, we're talking about code. (patterns are good things, particularly in collaborative development of any kind)



Other design patterns include those of UI design, where the context changes the meaning to be one of a set of expectations (standards) users have toward working with interactive systems. (not code) There are design patterns for graphic design, product design, ... just about every kind of design.



This peanut only mentions this because, working in close proximity, close enough to overhear conversations and confuse topics, it makes some sense to make sure it's clear people are talking about code. That context has some added weight, as to the importance and history these patterns have evolved in. The way a UI design may break a standardized design pattern (to develop an innovative conversation wheel) is counter to the more rigid needs of adhering to a design pattern of code, particularly during development or when applying past experience.



Make no mistake, any game/level designer who understands this level of code pattern knowledge is better prepared to contribute. But, while it could be easy to think a pattern is a pattern is a pattern, all likewise treated and adhered to; it may be a mistake to consider non-code patterns the same as these. There's a subtle need for better terminology.



Nice article, Michael. Thank you. And thanks for making 'programming' a part of the post's title. :)

Kelly Thomas
profile image
Nice article, great links.



It is hard to find documentation on game patterns in general. I find that each textbook or tutorial I read reveals a (very ) few more but it is hard to find material on them as a topic.



I have found the references to gameprogrammingpatterns.com to be invaluable, for the patterns covered it has frank coverage of cost/benefit considerations.

Kevin Swiecicki
profile image
Singleton.......every time I say it, I get a bit of a bad taste in my mouth. Let's face it, there are a ton of problems with them. First thing is that it's basically a global variable. Your audio object shouldn't even have the capability of sticking it's nose into our graphics singleton. Not to mention, the resource contention is going to be like an hourglass.



However, I've always been curious about using protected singletons. At the very least it makes it so that only classes that inherit from the singleton can use it's data. Although, it is possible that doing something like that could lead to poor architecture requiring double inheritances or something crazy like that.



Just my thoughts on it.


none
 
Comment: