使用Pool来回收和重用sprite

时间:2012-01-05 05:18:51

标签: java android andengine

我创建了这个通用池来重用我添加到场景中的一些精灵。

public class FruitPool extends GenericPool<Sprite> {
// ===========================================================
// Constants          
// ===========================================================

// ===========================================================          
// Fields         
// =========================================================== 
private  ITextureRegion texture1;
private  ITextureRegion texture2;
private ITextureRegion texture3;
private  ITextureRegion texture4;
private  ITextureRegion texture5;

private Scene mScene;
private Context mContext;
private Camera mCamera;
private LinkedList<Sprite>pool1;
// ===========================================================          
// Constructors          
// =========================================================== 
public FruitPool(final ITextureRegion watermelonRegion,
        ITextureRegion cherryRegion,ITextureRegion mBallTextureRegion, ITextureRegion grapeTextureRegion, ITextureRegion strawberryTextureRegion,Scene mScene2, Camera camera, LinkedList<Sprite>items) {

    this.texture1 = watermelonRegion;
    this.texture2 =cherryRegion;
    this.texture3 = mBallTextureRegion;
    this.texture4 = grapeTextureRegion;
    this.texture5 = strawberryTextureRegion;
    this.mScene = mScene2;
    this.pool1 = items;

    this.mCamera = camera;

}
// ===========================================================          
// Getter & Setter          
// =========================================================== 

// ===========================================================          
// Methods for/from SuperClass/Interfaces          
// ===========================================================  
@Override
protected Sprite onAllocatePoolItem() {

     Random rand = new Random();
     Random randFruit = new Random();
     Sprite fruit = null;
      float x = rand.nextInt((int) mCamera.getWidth() - texture1.getHeight());
     int textureNumber = randFruit.nextInt(5)+1;

     switch(textureNumber){
     case 1:
          fruit = new Sprite(x, 0, this.texture1);
          break;
     case 2:
         fruit = new Sprite(x, 0, this.texture2);
         break;
     case 3:
         fruit = new Sprite(x, 0, this.texture3);
         break;
     case 4:
         fruit = new Sprite(x, 0, this.texture4);
         break;
     case 5:
         fruit = new Sprite(x, 0, this.texture5);
         break;

     }










    mScene.attachChild(fruit);


    return fruit;

}
@Override
protected void onHandleObtainItem(final Sprite pItem) {
    pItem.reset();
}
@Override
protected void onHandleRecycleItem(final Sprite pItem) {
    pItem.setVisible(false);
    pItem.setIgnoreUpdate(true);

}


// ===========================================================          
// Methods          
// ===========================================================  

// ===========================================================          
// Inner and Anonymous Classes          
// ===========================================================  

代码运行良好,但它似乎没有重复使用回收的精灵,但每次分配新的......

我通过调用

检索一个精灵
  face =  fruitsPool.onAllocatePoolItem();

有什么建议吗?

编辑:

我在答案中尝试了这个方法,就像这样......

public class FruitPool extends GenericPool<Sprite> {
// ===========================================================
// Constants          
// ===========================================================

// ===========================================================          
// Fields         
// =========================================================== 
private  ITextureRegion texture1;
private  ITextureRegion texture2;
private ITextureRegion texture3;
private  ITextureRegion texture4;
private  ITextureRegion texture5;

private Scene mScene;
private Context mContext;
private Camera mCamera;
private LinkedList<Sprite>pool1;

private static Sprite fruitOne = null;
private static Sprite fruitTwo= null;
private static Sprite fruitThree = null;
private static Sprite fruitFour = null;
private static Sprite fruitFive = null;
private  Sprite fruit = null;
// ===========================================================          
// Constructors          
// =========================================================== 
public FruitPool(final ITextureRegion watermelonRegion,
        ITextureRegion cherryRegion,ITextureRegion mBallTextureRegion, ITextureRegion grapeTextureRegion, ITextureRegion strawberryTextureRegion,Scene mScene2, Camera camera, LinkedList<Sprite>items) {

    this.texture1 = watermelonRegion;
    this.texture2 =cherryRegion;
    this.texture3 = mBallTextureRegion;
    this.texture4 = grapeTextureRegion;
    this.texture5 = strawberryTextureRegion;
    this.mScene = mScene2;
    this.pool1 = items;

    this.mCamera = camera;

}
// ===========================================================          
// Getter & Setter          
// =========================================================== 

// ===========================================================          
// Methods for/from SuperClass/Interfaces          
// ===========================================================  
@Override
protected Sprite onAllocatePoolItem() {


     Random randFruit = new Random();

     int textureNumber = randFruit.nextInt(5)+1;

     switch(textureNumber){
     case 1:
         if (fruitOne == null) {
              fruitOne = new Sprite(0, 0, this.texture1);
              Log.e("FruitPool", "Item rremade");
            } else {
              fruit = fruitOne;
              Log.e("FruitPool", "Item exist in pool..Used");
            }
          break;
     case 2:
         if(fruitTwo == null){
          fruitTwo = new Sprite(0, 0, this.texture2);
         }else{
             fruit = fruitTwo;
             Log.e("FruitPool", "Item exist in pool..Used");
         }

         break;
     case 3:
         if(fruitThree == null){
              fruitThree = new Sprite(0, 0, this.texture3);
         }else{
             fruit = fruitThree;
             Log.e("FruitPool", "Item exist in pool..Used");
         }

         break;
     case 4:
         if(fruitFour == null){
             fruitFour = new Sprite(0, 0, this.texture4);
         }else{
             fruit = fruitThree;
             Log.e("FruitPool", "Item exist in pool..Used");

         }

         break;
     case 5:
         if(fruitFive == null){
              fruitFive = new Sprite(0, 0, this.texture5);
         }else{
             fruit = fruitFive;
             Log.e("FruitPool", "Item exist in pool..Used");
         }

         break;

     }


    return fruit;

}
@Override
protected void onHandleObtainItem(final Sprite pItem) {
    pItem.reset();
}
@Override
protected void onHandleRecycleItem(final Sprite pItem) {
    pItem.setVisible(false);
    pItem.setIgnoreUpdate(true);

}



// ===========================================================          
// Methods          
// ===========================================================  

// ===========================================================          
// Inner and Anonymous Classes          
// ===========================================================  
}

我打电话

 Sprite sprite = fruitPool.onAllocatePoolItem();

 then i attach it to the scene(this method i use is called about every second)

但每次我都会得到实体(精灵)已经拥有父母且已被附加的错误。

或者其他时间精灵只返回null。

有什么东西我做错了或丢失了吗?

2 个答案:

答案 0 :(得分:2)

new关键字用于通过调用该类的一个构造函数来创建类的新实例。它不会检查是否存在任何实例。

您需要编写逻辑来检查该类的任何实例是否已存在。如果不存在则创建一个新实例然后使用实例

请参阅http://java.sun.com/developer/technicalArticles/Programming/singletons/

答案 1 :(得分:1)

这是因为在switch(textureNumber)语句中,您每次都会创建一个new Sprite()并将其返回给调用者。您应该检查之前是否已创建Sprite并将该实例返回给调用者。

修改 :(根据评论)

根据我的理解,当你recycle()它只是隐藏了精灵,所以你想得到一个参考。

你可以做的是让你的精灵静态对象作为你班级的一部分,然后改变你的开关语句,如下所示:

private static Sprite fruitOne;
private static Sprite fruitTwo;
private static Sprite fruitThree;
. . .

//Other code in here

switch(textureNumber) {
  case 1:
    if (fruitOne == null) {
      fruit = new Sprite(x, 0, this.texture1);
    } else {
      fruit = fruitOne;
    }
    break;
  case 2:
    if (fruitTwo == null) {
      fruit = new Sprite(x, 0, this.texture2);
    } else {
      fruit = fruitTwo;
    }
    break;

   //Rest of code here. . .

基本上这段代码会检查是否已经创建了一个Sprite实例,如果没有 - 它会创建一个。