Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
SDL Game Development

You're reading from  SDL Game Development

Product type Book
Published in Jun 2013
Publisher Packt
ISBN-13 9781849696821
Pages 256 pages
Edition 1st Edition
Languages
Author (1):
Shaun Mitchell Shaun Mitchell
Profile icon Shaun Mitchell

Chapter 3. Working with Game Objects

All games have objects, for example, players, enemies, non-player character (NPC), traps, bullets, and doors. Keeping track of all these objects and how they interact with each other is a big task and one that we would like to make as simple as possible. Our game could become unwieldy and difficult to update if we do not have a solid implementation. So what can we do to make our task easier? We can start by really trying to leverage the power of object-oriented programming (OOP). We will cover the following in this chapter:

  • Using inheritance

  • Implementing polymorphism

  • Using abstract base classes

  • Effective inheritance design

Using inheritance


The first powerful feature of OOP we will look at is inheritance. This feature can help us enormously when developing our reusable framework. Through the use of inheritance, we can share common functionality between similar classes and also create subtypes from existing types. We will not go into too much detail about inheritance itself but instead we will start to think about how we will apply it to our framework.

As mentioned earlier, all games have objects of various types. In most cases, these objects will have a lot of the same data and require a lot of the same basic functions. Let's look at some examples of this common functionality:

  • Almost all of our objects will be drawn to the screen, thus requiring a draw function

  • If our objects are to be drawn, they will need a location to draw to, that is, x and y position variables

  • We don't want static objects all the time, so we will need an update function

  • Objects will be responsible for cleaning up after themselves; a function...

Implementing polymorphism


This leads us to our next OOP feature, polymorphism. What polymorphism allows us to do is to refer to an object through a pointer to its parent or base class. This may not seem powerful at first, but what this will allow us to do is essentially have our Game class need only to store a list of pointers to one type and any derived types can also be added to this list.

Let us take our GameObject and Player classes as examples, with an added derived class, Enemy. In our Game class we have an array of GameObject*:

std::vector<GameObject*> m_gameObjects;

We then declare four new objects, all of which are GameObject*:

GameObject* m_player;
GameObject* m_enemy1;
GameObject* m_enemy2;
GameObject* m_enemy3;

In our Game::init function we can then create instances of the objects using their individual types:

m_player = new Player();
m_enemy1 = new Enemy();
m_enemy2 = new Enemy();
m_enemy3 = new Enemy();

Now they can be pushed into the array of GameObject*:

m_gameObjects.push_back...

Using abstract base classes


If we are to implement our design correctly, then we have to be certain that all of our derived classes have a declaration and definition for each of the functions we want to access through the base class pointer. We can ensure this by making GameObject an abstract base class. An abstract base class cannot be initialized itself; its purpose is to dictate the design of derived classes. This gives us reusability as we know that any object we derive from GameObject will immediately work in the overall scheme of the game.

An abstract base class is a class that contains at least one pure virtual function. A pure virtual function is a function that has no definition and must be implemented in any derived classes. We can make a function pure virtual by suffixing it with =0.

Should we always use inheritance?


Inheritance and polymorphism are both very useful and really show off the power of object-oriented programming. However, in some circumstances, inheritance can cause more problems than it solves, and therefore, we should bear in mind a few rules of thumb when deciding whether or not to use it.

Could the same thing be achieved with a simpler solution?

Let's say we want to make a more powerful Enemy object; it will have the same behavior a regular Enemy object will have but with more health. One possible solution would be to derive a new class PowerEnemy from Enemy and give it double health. In this solution the new class will seem extremely sparse; it will use the functionality from Enemy but with one different value. An easier solution would be to have a way to set the health of an Enemy class, whether through an accessor or in the constructor. Inheritance isn't needed at all.

Derived classes should model the "is a" relationship

When deriving a class, it is...

Putting it all together


We can now put all of this knowledge together and implement as much as we can into our framework, with reusability in mind. We have quite a bit of work to do, so let's start with our abstract base class, GameObject. We are going to strip out anything SDL-specific so that we can reuse this class in other SDL projects if needed. Here is our stripped down GameObject abstract base class:

class GameObject
{
public:

  virtual void draw()=0;
  virtual void update()=0;
  virtual void clean()=0;

protected:

  GameObject(const LoaderParams* pParams) {}
  virtual ~GameObject() {}
};

The pure virtual functions have been created, forcing any derived classes to also declare and implement them. There is also now no load function; the reason for this is that we don't want to have to create a new load function for each new project. We can be pretty sure that we will need different values when loading our objects for different games. The approach we will take here is to create a new...

Summary


We have covered a lot of complex subjects in this chapter, and the concepts and ideas will take some time to sink in. We have covered the ability to easily create classes without having to rewrite a lot of similar functionality and the use of inheritance and how it allows us to share code between similar classes. We looked at polymorphism and how it can make object management a lot cleaner and reusable while abstract base classes took our inheritance knowledge up a notch by creating the blueprint we want all of our objects to follow. Finally, we put all our new knowledge into the context of our framework.

lock icon The rest of the chapter is locked
You have been reading a chapter from
SDL Game Development
Published in: Jun 2013 Publisher: Packt ISBN-13: 9781849696821
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime}