Advertisement

Ways of differentiating behavior using an object pool pattern?

Started by August 06, 2021 04:00 PM
26 comments, last by DevReign 3 years, 3 months ago

Anyone have experience with using the object pool pattern in C++? I'd like to create different methods for different types of game objects.
I was thinking if I create one main game object class with all the variables I need, but replacing the method function pointers somehow to give them different behavior. any ideas?

None

Not sure exactly what you mean, but wouldn't a derived GameObject class do that?

Advertisement

I was trying to do something like this http://gameprogrammingpatterns.com/object-pool.html

None

it doesn't have derived classes so i'm not sure what my options are other than creating giant methods that handle every case. I read dynamically allocating objects in memory causes memory fragmentation and is slow. is that something I should be worried about for a 2d game? and do i need a custom memory allocator if i did that?

None

First general rule of optimization is neither worry nor act on things that might happen. Life is too short for that.

Instead, only fix the problems you are sure about they will make your life miserable, and happily ignore all other problems.

Second rule of optimization is measure! Yes, dynamic allocation might be slow, but maybe it's not. Or, yes it's slow, but you do it only once, so optimizing it away won't even be noticable. On the other hand, right next to it is a piece of code that eats CPU time like a madman! Let's fix that instead!

It's impossible to predict where performance problems will happen. In all my attempts in finding such sources of trouble I always make a guess where it is, and so far I am 100% consistently wrong. It's always somewhere else, at a spot you never ever suspected.

Third rule of optimization is after fixing measure again that you fixed it.

Note that your current path is already costing you time. Instead of coding a normal solution now, you're thinking about some complicated scheme to shave off some unknown amount of milli-seconds CPU time, assuming you actually need to save those milli-seconds.

So unless you are sure you know stuff will fail if you code it in a simple straightforward manner, I would say don't worry about it. Even if it turns out that the problem is real, changing a working but slow program into something faster is simpler than trying to build a fast and working program from scratch when you don't even know where “slow” is coming from.

EDIT: Fourth rule of optimization is stop optimizing when it's fast enough. Making it even faster is generally possible, but doesn't gain you anything.

@Alberth I suppose that's true. I'll focus on coding things in a simple straightforward manner to get it done rather than trying to optimize everything now. I have a bad habit of over thinking and trying to perfect things. Thanks for the advice.

None

Advertisement

Btw. you should somehow manage your overall memory, not just those of objects. This won't help ya just in decreasing fragmentation but also finding leaks in your code.

You can for example allocate a big blog of memory at the beginning and then use that block to allocate your objects in. You can use different memory blocks for different sized objects (small object heap vs. large object heap) or use a garbage collection pattern which moves memory around and you only access those memory with another indirection.

I recommend this from time to time http://bitsquid.blogspot.com/2010/09/custom-memory-allocation-in-c.html

@Shaarigan Other than those objects, I don't allocate anything else. SDL2 allocates graphics and sounds when i start the game, but that is out of my control, as far as I know?

I think the easiest and fastest implementation may be to make projectiles, effects and items object pool arrays where I can reuse them without having to reallocate. The more complex game objects like creatures can perhaps all be the same size to avoid fragmentation when allocating. Do you think that is sufficient?

I'll read that article though and see if it's something I can use if it isn't too difficult to implement.

None

@DevReign I'm doing something like this for a game where the player kills robots. I have a seperate pool for each type of robot. When the game is started different types of robots can be moved to a vector of type Robot_Base* . In the game loop, I can update each robot by using like this:

for (Robot_Base* &pRobot: vRobots)

pRobot→Update(DeltaTime);

Different behaviors are obtained by overriding a pure virtual Attack() function:

virtual void Robot_Base::Attack() =0; //Abstract Class

void Robot_Melee::Attack(); //This is derived from Robot_Base, the attack function contains code to make the robot punch a target

void Robot_Bomber::Attack(); //This is derived from Robot_Base, the attack function contains code to make the robot launch a bomb

If the robot dies, its status is set to dead, and moved out of the vRobots vector and back into its resource pool. This prevents problems with dead pointers since it's not deleted.

You could make one class of robot and use one resource pool. You would have to encapsulate things that would be different - like how they attack the player, or move around. Maybe give the robot a pointer to Attack_Base, but have derived classes like Attack_Punch and Attack_Bomb.

In my case, The robots have different modes of movement (flying, walking, running, rolling), different meshes, different voices, different weapons, etc. I found it easier to use separate resource pools rather than trying to encapsulate all the differences.

@scott8 I think I understand. You have an array or object pool for each type of robot, like FlyingRobot flyingRobots[32]; and you activate it by sending a pointer from one of the robots to the Robot_base* vector which you later iterate through to update them? That does sound like a good solution. I suppose I should probably just create separate resource pools, because it starts getting really complicated trying to encapsulate all the functionality in one class.

I had thought separating projectiles, entities, items and decor in different pools would be enough, but it sounds like i may have to split up the entities into more as well.
The only other solutions I can think of would be to have a giant UpdateAI() method containing a switch statement with every possible Ai type, or dynamically allocating space for each object as needed and just letting them fragment memory.

None

This topic is closed to new replies.

Advertisement