Implementing a basic object pool

Let's first start off by creating an object pool for a simple class that we can create multiples of:

class GameObject 
{
private:
// Character's health
int currentHealth;
int maxHealth;

// Character's name
std::string name;

public:
GameObject();
void Initialize(std::string _name = "Unnamed",
int _maxHealth = -1);
std::string GetInfo();

};

So, this sample GameObject class contains a name of the object to identify it by and some example properties to make the class seem more game-object-like. Obviously, you can easily add more properties and the same principles apply. In this case, we have a function called Initialize, which provides both a set and reset of values for the class. Finally, I added in a GetInfo function to print out information about the class so we can verify that things are working correctly.

The implementation for the class will look something like this:

/*************************************************************************/ 
/*!
Constructor that initializes the class' data
*/
/*************************************************************************/
GameObject::GameObject()
{
Initialize();
}

/*************************************************************************/
/*!
Initializes or resets the values of the class
*/
/*************************************************************************/
void GameObject::Initialize(std::string _name, int _maxHealth)
{
name = _name;
maxHealth = _maxHealth;
currentHealth = maxHealth;
}

/*************************************************************************/
/*!
Prints out information about the class
*/
/*************************************************************************/
std::string GameObject::GetInfo()
{
return name + ": " + std::to_string(currentHealth) + "/" +
std::to_string(maxHealth);
}

Now that we have our game objects created, we need the pool to be created:

class GameObject; 

class ObjectPool
{
private:
std::list<GameObject*> pool;
static ObjectPool* instance;

// Private constructor so users are unable to create without
// GetInstance
ObjectPool() {}

public:

static ObjectPool* GetInstance();
GameObject* AcquireObject();
void ReleaseObject(GameObject* object);
void ClearPool();

};

To start off with there are two variables: pool, which will contain all of the available objects within our object pool, and instance, which is a way for us to access it. Note that our object pool uses the Singleton design pattern, in that there can only be one per type of object you'd like to have copies of. In this instance, we have the same issues that we talked about earlier, namely that you have to actually delete the pool and remove all of the elements that were created, which is why we added in a ClearPool function which does exactly that. The implementation for the class will look something like this:

ObjectPool* ObjectPool::GetInstance() 
{
if (instance == nullptr)
{
instance = new ObjectPool();
}
return instance;
}

In this preceding function, we first check if instance is set. If it's not, we dynamically allocate memory for it and set the instance variable to it. Either way, we'll have an instance afterwards, and that is what we return:

/*************************************************************************/ 
/*!
Returns the first available object if it exists. If not, it will create a new
one for us
*/
/*************************************************************************/

GameObject* ObjectPool::AcquireObject()
{
// Check if we have any objects available
if (!pool.empty())
{
// Get reference to an avaliable object
GameObject* object = pool.back();

// Since we are going to use it, it's no longer available,
// so we need to remove the last element from our list
pool.pop_back();

// Finally, return the reference
return object;
}
else
{
// If none are available, create a new one
return new GameObject()
}
}

/*************************************************************************/
/*!
Marks an object as being available again

param
The object to be made available again
*/
/*************************************************************************/
void ObjectPool::ReleaseObject(GameObject* object)
{
// Reset the object
object->Initialize();

// Add it to our avaliable list
pool.push_back(object);
}

/*************************************************************************/
/*!
Takes care of removing all of the objects from the pool whenever we're finished
working with it.
*/
/*************************************************************************/
void ObjectPool::ClearPool()
{
while (!pool.empty())
{
GameObject * object = pool.back();
pool.pop_back();
delete object;
}
}

The ClearPool function will continuously remove objects from the pool until it is empty. We first get a reference to the object, by retrieving the last element using the back function.

We then remove the element from the pool before deleting the object itself safely:

ObjectPool* ObjectPool::instance = 0;

Finally, C++ requires that we initialize the instance variable, so we add that last.

Once we have this foundational code in, we can start to use the classes. An example usage could be the following:

  ObjectPool* pool = ObjectPool::GetInstance(); 
GameObject * slime = pool->AcquireObject();

std::cout << "Initial: " << slime->GetInfo() << std::endl;

slime->Initialize("Slime", 10);

std::cout << "After Assignment: " << slime->GetInfo() <<
std::endl;

pool->ReleaseObject(slime);

slime = pool->AcquireObject();

std::cout << "Reused: " << slime->GetInfo() << std::endl;

pool->ClearPool();
delete pool;

If we save this script and run it in a blank project, you'll see the following:

In this case, we first get our ObjectPool that makes use of the GetInstance function, and then obtain an object from the object pool using the AcquireObject function (which calls new to create the object). From there we print out its values and, due to the constructor, it is set to our predefined default values. We then assign the values and use it. Afterward, we release it from the list in which we placed it on the pool, to be reused when we are ready. We then get the object again and show that it's already reset to be reused in exactly the same way as before!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.158.165