136
\$\begingroup\$

I have a few books on Design Patterns, and have read some articles, but cannot intuitively figure out which programming design patterns would be useful in game development.

For example, I have a book called ActionScript 3 with Design Patterns that details several design patterns such as Model View Controller, Singleton, Factory, Command, etc.

As someone new to this, I cannot figure out which of these would be useful, or in fact if any of these are the design patterns I should be learning and trying to use. Perhaps there are other, more game-programming-specific design patterns that I am not even aware of?

If you have experience using a certain design pattern in game development, I'd love to hear it. Reasoning as to why it was used, code samples, or online resources would all be very helpful as well if you have them. I am at the moment most interested in ActionScript 3 and C++ implementations, but could definitely benefit from experience and examples from any language.

Thanks!

\$\endgroup\$
4
  • \$\begingroup\$ "Perhaps there are other, more game-programming-specific design patterns that I am not even aware of?" - no, these patterns are generic, and apply more to extending the capabilities of the language you're using. They have nothing to do with the subject matter of your application. \$\endgroup\$
    – Kylotan
    Sep 29, 2010 at 13:25
  • 4
    \$\begingroup\$ @Kylotan It seems from my limited point of view that since each design pattern is meant to address a particular problem in an effective manner, by their nature some design patterns would be more useful than others given a specific problem set, namely in this case, those problem sets unique to game development. Surely there are some guidelines, or based on your experience, particular design patterns that you find yourself using more frequently than others? \$\endgroup\$
    – jcurrie33
    Sep 29, 2010 at 13:38
  • \$\begingroup\$ Before anyone goes off and learns 1000 different design patterns, please read this and this \$\endgroup\$ Jul 27, 2011 at 22:41
  • \$\begingroup\$ @BlueRaja-DannyPflughoeft Secon link is invalid. Can you resend it \$\endgroup\$
    – Emadpres
    Aug 24, 2015 at 21:26

9 Answers 9

171
\$\begingroup\$

Now for a less flippant response, with some suggestions. Don't take these as implementation recommendations, more as examples of possible use.

  • Builder: set up component-based entity one component at a time, based on data
  • Factory Method: create NPCs or GUI widgets based on a string read from a file
  • Prototype: store one generic 'Elf' character with initial properties and create Elf instances by cloning it.
  • Singleton: this space deliberately left blank.
  • Adapter: incorporate an optional 3rd party library by wrapping it in a layer that looks like your existing code. Very useful with DLLs.
  • Composite: make a scene graph of renderable objects, or make a GUI out of a tree of Widgets
  • Facade: simplify complex 3rd party libraries by providing a simpler interface to make your life easier later.
  • Flyweight: store the shared aspects of an NPC (eg. models, textures, animations) separately from the individual aspects (eg. position, health) in a mostly transparent way
  • Proxy: Create small classes on a client that represent larger, more complex classes on a server, and forward requests via the network.
  • Chain of responsibility: handle input as a chain of handlers, eg. global keys (eg. for screen shots), then the GUI (eg. in case a text box is focused or a menu is up), then the game (eg. for moving a character)
  • Command: encapsulate game functionality as commands which can be typed into a console, stored and replayed, or even scripted to help test the game
  • Mediator: implement game entities as a small mediator class that operates on different components (eg. reading from the health component in order to pass the data to the AI component)
  • Observer: have the renderable representation of a character listen to events from the logical representation, in order to change the visual presentation when necessary without the game logic needing to know anything about rendering code
  • State: store NPC AI as one of several states, eg. Attacking, Wandering, Fleeing. Each can have its own update() method and whatever other data it needs (eg. storing which character it is attacking or fleeing from, the area in which it is wandering, etc.)
  • Strategy: switch between different heuristics for your A* search, depending on what sort of terrain you're in, or perhaps even to use the same A* framework to do both pathfinding and more generic planning
  • Template method: set up a generic 'combat' routine, with various hook functions to handle each step, eg. decrement ammo, calculate hit chance, resolve hit or miss, calculate damage, and each type of attack skill will implement the methods in their own specific way

Some patterns left out due to lack of inspiration.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ A very enlightening discussion on singletons can be found here: misko.hevery.com/2008/08/25/root-cause-of-singletons \$\endgroup\$ Sep 30, 2010 at 7:01
  • \$\begingroup\$ +1 for the Strategy pattern. I've used it for the exact purpose stated above (plugging in different A* heuristics). \$\endgroup\$ Sep 30, 2010 at 16:32
  • 1
    \$\begingroup\$ thanks for this answer, those sound more like design pattern than the usual "singleton" i'm hearing everywhere... \$\endgroup\$
    – jokoon
    Oct 1, 2010 at 21:27
  • \$\begingroup\$ Great list of examples. Despite chronic abuse of the singleton pattern (global state in disguise), there are legitimate uses: When it represents a resource of which you actually only have (or want) one. This can be something like wrapping hardware (e.g. keyboard/mouse) or wrapping a library that is not reentrant (it happens, and not all languages have magical synchronization keywords). \$\endgroup\$
    – charstar
    Mar 2, 2011 at 23:00
  • 11
    \$\begingroup\$ I still wouldn't use singletons for hardware resources - items you think you'll only ever have 1 of tend to multiply later, just like video cards and monitors did as the years went on. Similarly, under some APIs you need to read 2 joysticks to understand 1 gamepad. So I'd say, if you only need one of something, just instantiate a single one, don't enforce arbitrary restrictions that probably aren't necessary. \$\endgroup\$
    – Kylotan
    Mar 3, 2011 at 16:41
64
\$\begingroup\$

I wrote a book on exactly that topic: Game Programming Patterns. The chapters that are there might be helpful for you.

\$\endgroup\$
5
  • 2
    \$\begingroup\$ +1 I was hoping someone had linked to that and I see that the author has! The component pattern description there was pretty helpful, and I like that you try to use complete code examples to demonstrate. \$\endgroup\$ Oct 28, 2010 at 19:54
  • 2
    \$\begingroup\$ Yeah - i remember reading your link a few years ago. You should finish those articles! \$\endgroup\$ May 10, 2011 at 4:37
  • 2
    \$\begingroup\$ Now the book is finished :) \$\endgroup\$
    – dusan
    May 10, 2014 at 21:30
  • 1
    \$\begingroup\$ An amazing resource that helped me translate my existing programming knowledge into programming for games. Thanks for writing it! \$\endgroup\$
    – user6214
    Jul 31, 2014 at 20:57
  • \$\begingroup\$ This explanation of game programming patterns actually helped me understand -design patterns- in a way that no software design pattern book really did! This is in part the power of game development (concrete examples in a language that speaks to me and allows me to better my development overall), but in a larger part because the writing is so excellent. \$\endgroup\$
    – Kzqai
    Feb 8, 2016 at 2:17
22
\$\begingroup\$

One thing Brandon Eich had the good sense to bring up in Coders at Work is that patterns are hacks and workarounds: [Patterns] show some kind of defect in the language. These patterns are not free. There's no free lunch. So we should be looking for evolution in the language that adds the right bits.

As game programmers rather than compiler designers we rarely get the option to evolve the languages we use, but we can learn to evolve our own style to better fit our language and requirements. Patterns are some of this, but not using patterns is another part, especially since as Brandon says, patterns rarely go without a notable performance or memory or code agility cost. MVC just is not a great pattern for many things in games. Singleton is a workaround for lame C++ static initialization rules, and you probably shouldn't be doing those anyway. Factory simplifies complicated object creation - maybe your objects should just be simpler to start with. The popular patterns are tools to resort to when we need them to manage something complex, not tools we should be longing to use to build something complex at the start.

Good (game) code might use patterns, or it might not. If it does use patterns, fine - they're a great communication tool to explain code structure to other programmers at a high, language-independent level. If you think the code is better without using a pattern, don't beat yourself up over it - it probably is.

\$\endgroup\$
16
  • 5
    \$\begingroup\$ Yes, one of the things made clear in the original book (but often overlooked) is that if it were written for C rather than C++/Smalltalk, they might have had included an "Inheritance" pattern, and by the same token, some languages might contain some of the GoF patterns already built in. \$\endgroup\$
    – Kylotan
    Sep 29, 2010 at 14:14
  • 15
    \$\begingroup\$ The other thing often overlooked in the original book (the original original book by Alexander, not GoF) was that patterns are a tool for communication, not implementation. They let designers communicate about implementation at a higher level, and are identified because they are recurring, not necessarily because they should be used when possible. \$\endgroup\$
    – user744
    Sep 29, 2010 at 14:19
  • 1
    \$\begingroup\$ However, merely having the terminology can help you reason about the problem and recognise when such an approach is a good solution. The best patterns have typically been refined over time by skilled and experienced workers, and less skilled workers would not discover the same patterns themselves without there being these codified examples. \$\endgroup\$
    – Kylotan
    Sep 29, 2010 at 14:31
  • \$\begingroup\$ I agree that having the terminology is great, and part of the definition of a pattern is that it is a good recurring solution for some problem. Unfortunately the less skilled workers tend to find mostly Singleton, and apply it to every problem, even when there is not yet a problem. \$\endgroup\$
    – user744
    Sep 29, 2010 at 14:36
  • \$\begingroup\$ Thanks for this response; I feel relieved to read that design pattern are made to resolve problems created by the software's design. I think that the structure of a whole big software should be thought throught from start to end before actually starting to code anything. You can't always implement functionalities once at a time, sometime you have to think about each particular feature, and check if it won't mess with the global structure of the software or just get in the way on how the software is suposed to behave. Dividing tasks to several programmers can sometime create contradictions... \$\endgroup\$
    – jokoon
    Oct 1, 2010 at 21:36
8
\$\begingroup\$

Of course, as others have said, all patterns are useful in the right circumstances, and part of learning how to use them is learning when to use them. However, the excellent book Core Techniques and Algorithms in Game Programming by Daniel Sanchez-Crespo Dalmau, lists six programming patterns and six usability patterns as especially useful in game programming.

Programming:

  • Singleton: I don't hate this one like many people do; it can be used for things like the single-player player or the keyboard reader.
  • Factory: Lets you create and destroy objects efficiently.
  • Strategy: Lets you change out AI strategies elegantly.
  • Spatial Index: Helps perform queries on spatial data sets.
  • Composite: Sets up a useful object heirarchy.
  • Flyweight: Frees memory by genericizing things like identical enemies.

Usability:

  • Shield: Protects from accidental activation of dramatic actions.
  • State: Visual cues of the world/UI status.
  • Automatic Mode Cancellation: Makes the game work more intutitively.
  • Magnetism: Autoaiming and easy unit selection.
  • Focus: Eliminating distracting UI elements.
  • Progress: Universally useful.

The book, of course, goes into more detail on each of these.

\$\endgroup\$
3
  • \$\begingroup\$ Thanks for the input! I was not aware of that book, but will look into it now as a result of your post. Thanks again! \$\endgroup\$
    – jcurrie33
    Sep 29, 2010 at 15:02
  • 2
    \$\begingroup\$ Singleton for the keyboard reader is exactly the situation where I have to ask - Can you really not just make it a global pointer set early in your main function? Have you ever actually accidentally instantiated two keyboard readers? \$\endgroup\$
    – user744
    Sep 29, 2010 at 15:09
  • \$\begingroup\$ Please do hate the singleton. It does two things poorly. Global access and arity. Often developers think global access == singleton. There a very few problems than need a true singleton, and possibly a few more that are more elegant when solved with a singleton. \$\endgroup\$
    – deft_code
    Oct 17, 2010 at 1:00
8
\$\begingroup\$

Entity systems are a nice kind of pattern. It's not exactly a design pattern since it's not strickly OOP. However you can mix it with OOP.

Some good links (start from top for intro):

\$\endgroup\$
3
  • 3
    \$\begingroup\$ "It's not exactly a design pattern since it's not strickly[sic] OOP." Design patterns have nothing to do with OOP; if anything, OOP itself is a design pattern. Design patterns appear not just outside of OOP, but outside software development entirely. \$\endgroup\$
    – user744
    Sep 30, 2010 at 19:05
  • \$\begingroup\$ There are OOP design patterns that typically show relationships and interactions between classes/objects. And there are many other design patterns. OOP is a set of concepts, not a pattern really. Design pattern is a concept, too. \$\endgroup\$
    – topright
    Oct 2, 2010 at 0:42
  • 6
    \$\begingroup\$ Instead of talking about semantic, shouldn't you rate the usefullness of the response I gave? \$\endgroup\$
    – Wernight
    Oct 4, 2010 at 9:56
7
\$\begingroup\$

All of them. Except Singleton. [/flippancy]

\$\endgroup\$
3
  • \$\begingroup\$ Could you possibly name one or two design patterns that you've used frequently in your game development, and for what reason? As a beginner with respect to design patterns, "all of them" is not a particularly helpful response. Thank you for responding, though. \$\endgroup\$
    – jcurrie33
    Sep 29, 2010 at 13:24
  • 5
    \$\begingroup\$ Asking "what patterns have you used?" is like asking "what variable names have you used?" It comes down to personal style and requirements and domain. At some point, you will probably use any pattern that's ever been named. You will probably use many more that have not been named, and maybe even invent some new ones. \$\endgroup\$
    – user744
    Sep 29, 2010 at 14:07
  • \$\begingroup\$ @jcurrie33: sorry, I just couldn't resist having a dig at singletons first. ;) \$\endgroup\$
    – Kylotan
    Sep 29, 2010 at 14:16
7
\$\begingroup\$

The curiously recurring template pattern can be really useful for avoiding virtual methods and the performance penalty that can come from the virtual function calls.

This can be the appropriate pattern when you don't actually need to have a container of the base class type which has the interface you're after, but you'd like to have similarly named behaviors and interfaces.

For example you can use this when compiling classes for multiple platforms or engines (dx vs. opengl) where the variance of type is known at compile time.

\$\endgroup\$
2
  • \$\begingroup\$ I always hated that the os abstraction layer was virtual. It's not like you'll ever need two os abtraction layers. Much better to use CRTP. \$\endgroup\$
    – deft_code
    Oct 17, 2010 at 0:58
  • \$\begingroup\$ Maybe I'm just old, but I wouldn't even use CRTP for DX/OpenGL or platform interfaces. It's too slow to compile - I'd just use typedefs. CRTP is good when you want to share interfaces and implementations between classes but have no other relation, not when you just want to pick one struct or the other. \$\endgroup\$
    – user744
    Oct 28, 2010 at 20:22
6
\$\begingroup\$

Not really about patterns, but about basic principles behind them. In "Design Patterns: Elements of Reusable Object-Oriented Software" (1995), the gang of four (Gamma, Erich; Richard Helm, Ralph Johnson, and John Vlissides) recommends only two principles for object oriented design: (1) program to an interface and not to an implementation and (2) favor object composition over class inheritance.

These 2 principles are very helpful in many tasks of game development. For example, many game programmers have used a deep class hierarchy to represent game entities. There is another approach based on composition - component-based game objects. Article about this approach. Even more links. It is a Decorator pattern example.

\$\endgroup\$
3
  • \$\begingroup\$ Components as used in game design are more like a stateful strategy pattern - which is naturally expressed as closures outside of C/C++/Java/C#, and as component objects inside them. The decorator pattern is more like a proxy; its ownership and data flow are opposite those we normally mean when we talk about component systems in games. \$\endgroup\$
    – user744
    Sep 30, 2010 at 19:01
  • \$\begingroup\$ Components also need to talk to each other, bringing in patterns like Mediator, Observer, and Composer. "Component-Based Game" is a composite design pattern all by itself. \$\endgroup\$ Oct 28, 2010 at 19:52
  • \$\begingroup\$ @CodexArcanum, Observer, definetely, but not always Mediator (Chain of Responsibility can be used instead). It is Composer only if GameObject (composed of GameObjectComponent) is GameObjectComponent itself (not nessesary). \$\endgroup\$
    – topright
    Oct 28, 2010 at 23:06
4
\$\begingroup\$

A design pattern that I evolved over the course of many years, and which has been spectacularly useful to me, is something I refer to as "brokered definition sets"; how to summarize it in GOF terms appears to be controversial, but this question I wrote about it on StackOverflow goes into some detail about it.

The core concept is that some property of a model, like the species of a creature, is set up so that each possible value for the property has a corresponding definition object -- a single, shared object per value -- that specifies its behavior, and these are accessed through a central broker (which, GOF-wise, may be a Registry, a Factory, or both). In my usage, they're also generally accessed via scalar keys, to facilitate weak binding for runtime morphism purposes.

\$\endgroup\$
6
  • \$\begingroup\$ I don't see how this is a singleton at all and when discussing the flyweight pattern the word "registry" is redundant. This is just flyweight. \$\endgroup\$
    – user744
    Jan 19, 2011 at 16:13
  • \$\begingroup\$ My understanding from the SO thread was that people identified Singleton as being part of it because of the definitions being set up as classes. As far as Registry goes, I don't see how it can be redundant when it can be replaced or combined with Factory. \$\endgroup\$
    – chaos
    Jan 19, 2011 at 17:14
  • \$\begingroup\$ -1, to the extent patterns are about quickly communicating, this is probably the biggest failure I've seen. I really can't take this description seriously. \$\endgroup\$
    – user744
    Jan 19, 2011 at 19:49
  • \$\begingroup\$ Jesus, pardon me for not being cookie-cutter enough for you. Are you going to vote down the "Entity systems" answer too because it isn't instantly summarizable in GOF terms? \$\endgroup\$
    – chaos
    Jan 19, 2011 at 20:47
  • 1
    \$\begingroup\$ Some amount of "cookie-cutter," or at least semantic clarity, is exactly what patterns must be to be useful. Terms like "flyweight" and "singleton" as they are commonly understood are mutually exclusive. The first is about automatically sharing data between multiple instances; the second is about having exactly one instance. I'm not saying your design choice is useless or even bad, but cramming "close enough" pattern names together just confuses everyone more. (Please don't take downvotes personally, especially on CW.) \$\endgroup\$
    – user744
    Jan 19, 2011 at 21:01

Not the answer you're looking for? Browse other questions tagged .