Game Architecture

I found myself writing a lot of code which later became coupled everywhere because I did not know a lot about programming patterns. I decided to read the book Game Programming Patterns by Robert Nystrom to learn more about said patterns. I implemented some of the patterns on existing code to learn how to work with the patterns.


Scroll down for more information.

Programming Patterns

General

As mentioned in the header, I did not have a lot of experience with programming patterns or code architecture. After reading through Game Programming Patterns I feel like I am familiar with some implementations and with the patterns mentioned. However, I think the real challange is to know when to use a pattern, and of course to know which pattern to use. Implementations may very on every implementation you make and the patterns implementation depends on the use case. To get familiar with this is a matter of experience, which I hope to get more with all the patterns. Not all patterns will be mentioned below, since I am not yet familiar with every pattern.

States, Commands, InputHandler and Behaviours

I made this small program in C++/SFML. I made this to implement some programming patterns. Though not all visable, I implemented Commands, States (or finite state machine) and behaviours. The commands are what takes care of all the movement, and button presses utilize commands as well, alongside function pointers (std::function). An input handler, which is updated each frame, will check for each command if its key is pressed and execute said command when the key is pressed. The input handler also takes certain window events, such as when a key is first pressed. The input handler can be set to remap a key for a certain command, the first time the key pressed event is caught it will remap the command to that key.

The moving cube is done using behaviour. A behaviour can be executed on any Transformable (from the SFML library). In this case the player behaviour is a finite state machine. The pllayer has 3 implemented states: Idle, Moving and Jumping. When idle the player does nothing in its update, but it will respond to both the moving action and the jump action input. When the player is moving, it will continue to move on move action input and it will jump on jump input. The jump however, does nothing with any input action, it will continue to jump and fall until it finishes, then it will tell the player behaviour to go back to the last state it was in. Though this is a simple implementation of the finite state machine, I think it did the jump for me, and it did help me to understand it a bit more, and to help me understand the implementation.

The keyboard in the bottom right was not made by me, but is an overlay plugin for OBS (recording software).

Technical Details

  • C++
  • SFML
  • States
  • Input Handler
  • Command
  • Behaviour

Observers

My first implementation of the observer pattern in project Show-Off My second implementation of the observer pattern in project Show-Off

One of my favorite patterns is the observer pattern. In the last school project of my second year I implemented this pattern in Unity. The left picture shows my first implementation in said project (Click the image to enlarge). After reading about this pattern in Game Programming Patterns by Robert Nystrom I changed my implementation to the image on the right. Though both implementations work, I decided for the one the right because it did not require me to make an implementation of the IObserver interface for every observer. Of course it did require me to make a new implementation of the AObserverEvent class, but that seemed better to me.

Technical Details

  • Observer Pattern
  • C#
  • Unity

Finite State Machine

Finite State Machine UML diagram
//C# Unity //FarmPlot.cs private StateReady ReadyForState(State state) { if (_cooldownTimer >= _cooldown || _neglectCooldown) { return _states.Peek().ReadyForState(state); } else { return StateReady.OnCooldown; } } //FarmPlotDugState.cs public class FarmPlotDugState : FarmPlotState { //code public override FarmPlot.StateReady ReadyForState(FarmPlot.State state) { if (state == FarmPlot.State.Planted) return FarmPlot.StateReady.Ready; else return FarmPlot.StateReady.InvalidAdvancement; } //code }

Though I had heard of the state pattern, I had never implemented it myself. When reading about the state pattern I understood how to implement it, but more important, why the implementation can make your life easier. In previous mentioned school project I wrote a FarmPlot class. This farm plot was going to be shoveled, planted, watered, harvested, that sort of things. I used enums to keep track of its current state. However when using the enums I already started to question if there wasn't a better/easier way, since I started writing very long switch statements as can be seen below.


I decided to redo some of this code after the project and see if I was able to implement a state pattern here. The UML for this implementation can be viewed above. I started off by making an abstract FarmPlotState scriptableObject (since we were working in Unity for the project). I made a implementation of the abstract class for all the states I was going to have. When entering a new state the farm plot would call EnterState on the entered state and UnLoad on the left state. When going back a state in the states stack the farm plot would call ExitState and the state would destroy itself. The farm plot would also call Update on the current state everytime the farm plot was updated. The function shown earlier is now made into the functions shown above. As seen the function calls ReadyForState on the current state, states now get to decide which next state is allowed, making all the switch and if-statements a lot smaller. Even though I did not get any of the luxeries of the pattern since I was replacing code and never extended anything after, I did like how easy it was to implement all the states and how much easier it was to fix a bug. The bug appeared after implementing the pattern because something was going wrong when switching to a certain state, but that was easy to solve and did not require coupling or any weird if-statements.

Technical Details

  • Finite State Machine
  • C#
  • Unity

Command & Input Handler

UML diagram of the command and input handler implementation
//C++ GLFW OPENGL //InputHandler.h class InputHandler { public: InputHandler(et::Window& window); void update(); void addCommand(Command& command, int button = -1); void setCommandButton(Command& command, int button); private: GLFWwindow& window_; std::vector commands_; std::map commandButtons_; }; //InputHandler.cpp InputHandler::InputHandler(et::Window& window) : window_(*window.getGLFWWindow()) { } void InputHandler::update() { for (int i = 0; i < commands_.size(); ++i) { if (glfwGetKey(&window_, commandButtons_[commands_[i]])) { commands_[i]->execute(); } } } void InputHandler::addCommand(Command& command, int button) { commands_.push_back(&command); commandButtons_.emplace(&command, button); } void InputHandler::setCommandButton(Command& command, int button) { if (commandButtons_.find(&command) != commandButtons_.end()) { commandButtons_.at(&command) = button; } }

When reading about commands combined with an input handler for the first time I was really intreged. I think this system works great. However, I think the command pattern itself might be more useful in turn-based games or software where undoing is a useful feature. I think an input handler like this is great for games where players are able to change the controls. I decided to try the pattern myself. The UML and code can be seen above.

Technical Details

  • Command pattern
  • Command based Input Handler
  • C++

Click to close

Contact

You can click on any of the above links for my profiles or you can also send an email to jelle.vrieze@gmail.com