Game Design Patterns

Status: In Progress

Details

Bob Nystrom and Dog

The Why


After years of telling myself Ill learn C++... someday”, I finally decided to buckle down and give it a try, and I'm glad I did! While it was no cakewalk, I was able to put together a few small examples of some basic game design patterns (hence the project name). My reference was the excellent book Game Programming Patterns by Bob Nystrom (see photo (not the dog)); it's a great read, and very accessible (which is saying something for a book about design patterns).

Command Pattern


The first pattern I implemented was a simple command pattern. Inputs are turned into commands, commands are run and then stored in an array; Ctrl+Z and Ctrl+Y will undo and redo the array of commands, respectively, thus allowing a user to move back and forth. While many games could probably benefit from an undo/redo feature, for tools and editors it's usually an absolute must.

Command Pattern Example

Input Queue


I tried to implement a version of the event queue pattern, but it's more of an input queue (still important, especially in fighting and platforming games). Let's say you're building a combo system: you can chain multiple attacks together indefinitely. Since the inputs are constantly being read - clearing up space for new inputs to be written!

Input Queue Pattern Example

User inputs are converted into commands and added to the queue - provided the queue isn't currently full. Notice how the modulus operator is applied after incrementing the tail - this ensures that the next command is stored at position 0, thus allowing the same space in memory to be used to process a neverending chain of commands.


bool InputQueue::addInput(Command *command)
{
  // do not add if pending is full
  if ((tail + 1) % COMMAND_COUNT == head)
    return false;
  
  // add to the end of the list
  pending[tail] = command;
  tail = (tail + 1) % COMMAND_COUNT;
  return true;
}

During the update call, a timer is ticked down until it reaches zero; when it does reach zero, if there are any commands in the queue, the command at the head of the queue is returned. Like the tail, the head is also wrapped back around to position 0, chasing the tail until the queue is empty.


Command *InputQueue::update()
{
  // first, check timer for movement
  timer -= GetFrameTime();
  if (timer > 0.f)
  {
    return NULL;
  }
  else if (head == tail)
  {
    timer = 0.f;
    return NULL;
  }
  else
  {
    timer = COOLDOWN;
  }
  
  // return command
  Command *command = pending[head];
  head = (head + 1) % COMMAND_COUNT;
  return command;
}

Status Report


Currently, I need to get a working version for web (for a few small demos, I think web is best - and it's safer than downloading). Once I do, I hope to keep adding to it over time - I really want to try a bytecode demo!