Design Patterns in Game Engine Development

Just because you know the syntax of a programming language, does not make you a programmer. I hate to say that to you, but it is true. What makes you a programmer is a knowledge about data structures, algorithms, and design patterns. The syntax of a language is synonymous to knowing the alphabet. Anyone, and I mean anyone, can learn the syntax of a programming language in a weekend. But it would be impossible for such person to develop a modular, flexible, maintainable application.

Now that I have broken your heart and aspirations, let me introduce you to the Design Patterns that will make you a great developer.

There are several design patterns. Most of them are explained in this book. But the most used and loved design patterns are the following:

  • Singleton Design Pattern: Allows only one instance of a class to be created.
  • Strategy Design Pattern: Provides flexibility by decoupling class behaviors.
  • Observer Design Pattern: Allows classes to interact with each other without knowing anything about them.
  • Composite Design Pattern: Provides a unified access point to all classes.
  • Model-View-Controller Design Pattern: The ROCK STAR. Period.

I'm going to talk about each design pattern in terms of game engine development (I'm a side hustler game engine developer). However, the concept that follows applies to any app or game development.

Singleton Design Pattern

In a game, just like in a movie, there should be only one director. A director is a class that conducts everything that happens in a game. It controls the rendering of an object. It controls position updates. It directs the player’s input to the correct game character, etc.

The engine should prevent more than one instance of a director to be created and it does so through the Singleton Design Pattern. This design pattern ensures that one and only one object is instantiated for a given class.

Learn how to implement this pattern here.

Strategy Design Pattern

In a game, you should always decouple the interaction between the input controller and the game's logic. The game's logic should receive the same kind of input regardless of the input controller (button, gesture, joystick).

Although each input controller behaves differently to the user, they must provide the same data to the game's logic. Furthermore, adding or removing an input controller should not crash a game.

This decoupling behavior and flexibility are possible thanks to a design pattern known as Strategy Design Pattern. This design pattern provides flexibility to your game by allowing it to change behavior dynamically without the need of modifying the game's logic.

Learn how to implement this pattern here.

Observer Design Pattern

In a game, all of your classes should be loosely coupled. This means that your classes should be able to interact with each other, but have little knowledge of each other. Making your classes loosely coupled makes your game modular and flexible to add features without adding unintended bugs.

This pattern is normally implemented when an object wants to send messages to its subscriber (other objects). The object does not need to know anything about how the subscribers work, just that they can communicate.

Learn how to implement this pattern here.

Composite Design Pattern

A game normally consists of many views. There is the main view where the characters are rendered. There is a sub-view where player's points are shown. There is a sub-view which shows the time left in a game. If you are playing the game on a mobile device, then each button is a view.

Maintainability should be a major concern during game development. Each view should not have different function names or different access points. Instead, you want to provide a unified access point to every view, i.e., the same function call should be able to access either the main view or a sub-view.

This unified access point is possible with a Composite Design Pattern. This pattern places each view in a tree-like structure, thus providing a unified access point to every view. Instead of having a different function to access each view, the same function can access any view.

Learn how to implement this pattern here.

Model-View-Controller Design Pattern

If the Model-View-Controller design pattern was a Rock band, then it would definitely be called "The Beatles". No doubt about it. It is the most widely used and loved design pattern among programmers.

My introduction to Design Patterns was through the Model-View-Controller. And I wish it wouldn't have been that way. I, like many programmers, started learning this pattern without realizing that this pattern is made up of three fundamental Design Patterns. Not realizing this fact, caused a lot of confusion.

The Model-View-Controller design pattern is made up of three patterns:

  • Strategy Design Pattern
  • Observer Design Pattern
  • Composite Design Pattern

As shown in the illustration above, the Strategy pattern represents the Controller part of the MVC. The strategy pattern decouples user inputs from the game's logic (Model) and interfaces (View).

The Composite Design Pattern represents all Views (main window & buttons) in an application. This pattern provides a unified access point for all views to the model.

The Observer Design Patten represents the logic of your application (Model). Through this pattern, the Model is able to interact with the views and controllers without knowing anything about them. This pattern makes the interaction between all classes loosely coupled.

Hope this helps.

Harold Serrano

Computer Graphics Enthusiast. Currently developing a 3D Game Engine.