AndEngine: Using the Object Pool

When developing a game or application for a mobile device you, as the developer, must concern yourself in actively keeping your memory footprint small. One of the best ways to do this is to reuse Objects. Android does this, the best example must be the ListView. To achieve the super smooth, super fast scrolling the list items are reused! This is performant as you will not be wasting precious CPU cycles creating and destroying objects, so you see why that’s important in a game, right!?

So here I present a tutorial for using Object Pools in AndEngine (http://www.andengine.org).

The Object Pool

As you may know, I’ve been making a game which involves shooting (If you don’t know, see here), naturally a shooting game means many bullets will be fired in the game. This could mean that you will create a large number of objects which represent those bullets. Bullets will move offscreen or they may collide with other objects. These bullets are ideal candidates for reuse, once they’re offscreen or they’ve hit something we can hide them from being drawn, and recycle them by sending them to the pool and then requesting one again if we need one.

If you’re on the ball you might at this point think “what will happen if I ask the pool for a bullet but there aren’t any?”, well you’ll get a brand new one. Which you can put back in the pool once you’re done with it.

If you’re struggling to understand how the pool would work, you could think of it as such:

Game: I need a bullet! Mr. Object Pool can I have an instance of a Bullet please?
Mr. Object Pool: Let me check my pool…I don’t have spare Bullets, I’ll create a new Bullet for you
Game: Thanks!
Game: Mr. Object Pool, this bullet has moved offscreen so I don’t need it anymore, please recycle it for me
Mr. Object Pool: Ok, thanks, I’ll put that instance in my pool
Game: Hey, I need another Bullet again
Mr. Object Pool: No problem, I have one in my pool which you gave me, I don’t need to waste time making a new Bullet, you can have this one!

Creating the Object Pool

First thing to do is to create the Pool that will hold and return Bullets. There is an abstract class named GenericPool.java which you extend to implement a few methods. So let’s do that.

public class BulletPool extends GenericPool<BulletSprite> {
 private TextureRegion mTextureRegion;

 public BulletPool(TextureRegion pTextureRegion) {
  if (pTextureRegion == null) {
   // Need to be able to create a Sprite so the Pool needs to have a TextureRegion
   throw new IllegalArgumentException("The texture region must not be NULL");
  }
  mTextureRegion = pTextureRegion;
 }

 /**
 * Called when a Bullet is required but there isn't one in the pool
 */
 @Override
 protected BulletSprite onAllocatePoolItem() {
  return new BulletSprite(mTextureRegion);
 }

 /**
  * Called when a Bullet is sent to the pool
 */
 @Override
 protected void onHandleRecycleItem(final BulletSprite pBullet) {
  pBullet.setIgnoreUpdate(true);
  pBullet.setVisible(false);
 }

 /**
  * Called just before a Bullet is returned to the caller, this is where you write your initialize code
  * i.e. set location, rotation, etc.
 */
 @Override
 protected void onHandleObtainItem(final BulletSprite pBullet) {
  pBullet.reset();
 }
}

That’s pretty straight forward right? I’ll explain a couple of the methods though just in case. onHandleRecycleItem() this is one of the methods you need to implement in your subclass. In this method I’ve set the sprite to be invisible, this doesn’t really matter if the bullet has gone offscreen but it does matter if the bullet has collided with an object on screen. Also, I’ve called setIgnoreUpdate(true), this will exclude the sprite from being updated whilst the game continues to run, for example; if you had set a Velocity on your sprite you don’t want to continue to have the position of the bullet updated based on that velocity if you’re putting the bullet in the pool. onHandleObtainItem() this is called just before the Sprite is returned to the caller. In the code above I’ve called reset() which just sets the initial values of the bullet back to what they were when the sprite was first created. You could put the reset()  call in the onHandleRecycleItem, I just put it there as an example.

And that’s it, now you’re ready to use the pool.

Using the Object Pool

Now that we’ve created a pool to fetch and send objects to and from we’re ready to make use of it. For berevity I’ll only show relevant code rather than the whole Game Activity.

public class ShooterActivity extends BaseGameActivity {
 private static BulletPool BULLET_POOL;

 @Override
 public void onLoadResources() {
  // Set up the bullets pool so bullet sprites can be created and reused
  BULLET_POOL = new BulletPool(mBulletTextureRegion);
 }

 /**
 * Called because the bullet can be recycled
 */
 private void sendBulletToBulletPool(BulletSprite pBulletSprite) {
  BULLET_POOL.recyclePoolItem(pBulletSprite);
 }

 /**
 * The player fired, we need a bullet to display
 */
 private BulletSprite getBulletFromBulletPool() {
  return BULLET_POOL.obtainPoolItem();
 }
}

Really simple uh! I’ve not included how the sendBulletToBulletPool() or getBulletFromBulletPool() are invoked as that’s not important. The important part is the using the Pool. When the game starts and the resources are loaded we make sure we create an instance of the BulletPool, the mBulletTextureRegion is needed when the Pool needs to create new bullets. The rest should be simple enough to understand, but if you don’t understand just leave a question in the comments area below.

About these ads
  1. #1 by samyboy on January 7, 2011 - 1:02 pm

    Very informative article indeed. Is your game going to be open source by the way? I’ve been looking for a full open source game for quite a while now, sadly without any success.

    And yes I have seen the Snake and the Racer examples, but those are practically useless.

    • #2 by c0deattack on January 7, 2011 - 8:44 pm

      It’ll be open source yes, but not immediately. I’ll put it up on GitHub after it’s been on the Android Market for a few months.

  2. #3 by Tyler on January 12, 2011 - 5:33 am

    This works amazingly, thanks a bunch. I’ve been rolling the idea around for a bit when I found this on andEngine. This is why I dropped out of CS in college. I can learn 10x what I learned from outdated profs with one forum search :D

  3. #4 by Dave on February 1, 2011 - 4:00 am

    Hi,

    Great post! One follow-on question on this topic that has me perplexed as I dive into AndEngine. Can you explain how you set the position of a recycled bullet? In my game, I can set the initial bullet body and sprite position, but after it flies offscreen and I recycle it, I dont have a good example on how to set it back to my turret’s position and fire it again in another direction. Could you give a little example code for doing that?

    Thx!
    -Dave

  4. #5 by Gunston2084 on February 5, 2011 - 11:28 am

    Nice post. Appreciated.

  5. #6 by vlab22 on May 2, 2011 - 9:45 pm

    Nice Post,
    Pools are essential too for any OS, Server, etc (Games too :P )

    We need to thanks “pools”, without it we didn’t have fun in our lives :P

  6. #7 by Ted Hughes on May 14, 2011 - 4:03 pm

    This part of the code is not working for me.
    @Override
    16 protected BulletSprite onAllocatePoolItem() {
    17 return new BulletSprite(mTextureRegion);
    18 }

    I get an error here:
    17 return new BulletSprite(mTextureRegion);

    eclipse wants arguments to match a BulletSprite, i.e. add x , y coordinates
    return new BulletSprite( 0, 0, mTextureRegion);

    Now when I send to pool I have all the recycled sprites stack up at 0, 0 on the screen;

    Is that correct?

  7. #8 by Torbjörn Josefsson on June 8, 2011 - 11:01 am

    Seems nice! (AndEngine noob here)

    I have a sprite that comes in variants; a set of differently colored balls, each represented in image form by their own TextureRegion – how can I make onAllocatePoolItem create the sprite from the right TextureRegion? – can I in any way send arguments to it? (an int, to say which TextureRegion to pick from an array thereof)

    Thanks for the article!

  8. #9 by JiMMaR on October 21, 2011 - 6:10 pm

    Good job man , I used your tutorial in my own :D

  9. #10 by Thomas on February 1, 2012 - 7:32 am

    really well explained. Good work!!

  10. #11 by Sokol on February 7, 2012 - 6:47 pm

    Nice article. thx.

  11. #12 by Narayan on June 19, 2012 - 3:45 pm

    Thanks for the explanation, can you please help me when i get recycled item how to reset update handlers and entity modifiers again which i have unregistered onHandledRecycleItem()

  12. #13 by Felipe on October 19, 2012 - 6:44 am

    Very nice explanation, thanks!

  13. #14 by Rose R. on December 10, 2012 - 9:11 am

    Hi! Do you by any chance have the source code uploaded to github ?

  14. #15 by hitmanfak on December 11, 2012 - 11:33 am

    Hi I am using the pools but i need to configure the overloaded constructor parameters such that the pool waits to enque atleast 15 items before recycling them… can you explain how the 3 parameters work?

    GenericPool.class :

    public GenericPool(final int pInitialSize, final int pGrowth, final int pAvailableItemsMaximum)

  15. #16 by Waqas on May 23, 2013 - 7:05 pm

    Please give the link of the Source Code Thanks mail me at muhammadwaqas2@yahoo.com

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: