Followers

Thursday, June 2, 2011

Custom Object Pool for Java

Just a foreword, this is made specifically for AndEngine but can be adapted to anything that uses lists.

Creating and destroying objects is costly on a CPU and on a platform like Android, CPU usage needs to be wise. With the method I'll lay out, we employ the use and power of Lists, where a projectile is either recycled or a new one is created.

Step 1: Initialize the list

private List enemyMissileSprites = new ArrayList();

MissileSprite is a class I made that extends the Sprite class in AndEngine. Not much is different from its parent other than it has a reset function that removes it from the screen (sets its position to (500,500) just to get it off the screen), and an update method that moves it 10 units to the left every tick.

Lists are cool, they are like arrays but they are more easily expanded. To add an element to a list one just needs to do listName.add(objectName). It's that easy. Accessing the parts of the list are different than arrays where in lists you use listName.get(indexNumber) rather than arrayName[indexNumber]. With that let's continue.

Step 2: Make the function to retrieve missiles/objects

private int getEnemyMissile()
{
   for(int x = 0; x < enemyMissileSprites.size(); x++)
   {
      if(enemyMissileSprites.get(x).offScreen(CAMERA_WIDTH, CAMERA_HEIGHT))
      {
         //Log.d("GeoFlight", "Reusing #: " + x);
         return x;
      }
   }
         
   Log.d("GeoFlight", "Expanded Enemy Missile Sprites to size: " + enemyMissileSprites.size());
         
   this.enemyMissileSprites.add(new MissileSprite(TextureRegionFactory.createFromAsset(misTexture, this, "gfx/480/missile.png", 0, 0)));
   scene.getLastChild().attachChild(this.enemyMissileSprites.get(this.enemyMissileSprites.size() - 1));
         
   Log.d("GeoFlight", "Expanded Enemy Missile Sprites to size: " + enemyMissileSprites.size());
         
   return this.enemyMissileSprites.size() - 1;
}
Here we check to see if the object has moved off the screen and if it has then it will return the number of it's location back through the function. If there are no projectiles offscreen, then it will make a new object and return its place. We can know its place as the add function of lists adds it to the end of the list, thus whatever object you add will have the index of listName.size - 1. That is really it, but here's implementation use too.
BaseShip temp = encounter1.checkForMissileFiring();
if(temp != null)
{
   enemyMissileSprites.get(getEnemyMissile()).setPosition(temp.getX() + temp.getWidth() / 2, temp.getY() + temp.getHeight() / 2);
}
if(enemyMissileSprites.size() != 0)
{
   for(MissileSprite mS : enemyMissileSprites)
   {
      if(!mS.offScreen(CAMERA_WIDTH, CAMERA_HEIGHT))
      {
         mS.update();
      }
   }
} 

Basically I have my encounter check for firing missiles, if there is one then it passes the ships information back to my game class or else it will return null. It then proceeds to get the enemy missile from our getEnemyMissile function and sets its position to be equal to that of the ship it returned. As well, I added to it where it will only update the missiles that are on screen.

I hope this helps people, if you like it please comment and follow, and if you have any critique, please let me know, I'm still learning and growing and looking to sharpen my trade daily.