原文地址: https://c0deattack.wordpress.com/2011/01/06/andengine-using-the-object-pool/
PS: 非常不错的分析, 不错 有兴趣的朋友可以看看!
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 calledreset()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 thesendBulletToBulletPool()orgetBulletFromBulletPool()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.