AndEngine GenericPool с таймером, добавляющим спрайты из пула - PullRequest
2 голосов
/ 23 декабря 2011

У меня есть этот GenericPool, который я использую для игры, которую создаю в AndEngine.

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

// ===========================================================          
// Fields         
// =========================================================== 
private final TextureRegion mTextureRegion;
// ===========================================================          
// Constructors          
// =========================================================== 
public FruitPool(final TextureRegion pFruitTextureRegion) {
this.mTextureRegion = pFruitTextureRegion;
}
// ===========================================================          
// Getter & Setter          
// =========================================================== 

// ===========================================================          
// Methods for/from SuperClass/Interfaces          
// ===========================================================  
@Override
protected Sprite onAllocatePoolItem() {
return new Sprite(0, 0, this.mTextureRegion);
}
@Override
protected void onHandleObtainItem(final Sprite pItem) {
pItem.reset();
}
@Override
protected void onHandleRecycleItem(final Sprite pItem) {
pItem.setVisible(true);
pItem.setIgnoreUpdate(true);
}
// ===========================================================          
// Methods          
// ===========================================================  

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

Как вы видите, я предоставляю TextureRegion в пул, чтобы создать спрайт в пуле, как этот ..

FruitPool pool1 = new FruitPool(TextureRegion);
Sprite blueBall = pool1.obtainItem();

Затем я перерабатываю спрайты после того, как они исчезли с экрана, используя

  pool1.recyclePoolItem(blueBall);

Проблема в том, что у меня есть таймер, который добавляет спрайт примерно каждые 2 секунды.

Проблема в том, что если спрайт еще не исчез из экрана и не был переработан, я получаю сообщение об ошибке «У Sprite уже есть родитель» в моем Logcat.

Есть ли способ сделать так, чтобы я мог вытянуть из пула столько спрайтов, сколько захочу, а затем перерабатывать каждый из них, когда он уходит с экрана, чтобы позже использовать его?

То, как я сейчас это понял, явно не работает.

Спасибо за помощь, ребята!

РЕДАКТИРОВАТЬ: Также вот метод, где я добавляю спрайты в зависимости от выбранного числа

  private void addFace2() {
         Random rand = new Random();
         Random randFruit = new Random();


         if(isGameRunning){
         face = null;

            int fruitNumber = randFruit.nextInt(6) + 1;



                switch(fruitNumber) {
                   case 1:
                      //Item 1 code
                       face = pool1.obtainPoolItem();
                       this.pool1List.add(face);

                      break;
                   case 2: 
                        face = pool2.obtainPoolItem();
                         this.pool2List.add(face);
                      break;
                   case 3:
                       face = pool3.obtainPoolItem();
                     this.pool3List.add(face);
                       break;
                   //etc. . . 
                   case 4:
                       face = pool4.obtainPoolItem();
                     this.pool4List.add(face);
                       break;
                   case 5:
                       face = pool5.obtainPoolItem();
                     this.pool5List.add(face);

                       break;

                 }
                this.mFaceCount++;
           Log.e("Faces: ", "Face" + this.mFaceCount);

           if(face !=null){
            int rangeDuration = maxDuration2 - minDuration2;
            int actualDuration = rand.nextInt(rangeDuration) + minDuration2;
            MoveYModifier mod = new MoveYModifier(actualDuration, face.getY(), mCamera.getHeight());
            face.registerEntityModifier(mod);
            if(face.hasParent()){
                Log.e("Face", "Face has parent");
            }else{
                  this.mScene.attachChild(face); 
            thump.play();
            }

           }
     }

1 Ответ

3 голосов
/ 23 декабря 2011

Вероятно, это потому, что вы пытаетесь прикрепить спрайт к сцене, как только вы его получили (даже если это не произойдет в вашем коде ...), и вы не отсоединили его, когда он был переработан.

Подход, который я предлагаю вам использовать, заключается в следующем (я использую его в своей игре, где у меня есть пул спрайтов, такой же, как у вас, и он отлично работает):

  1. В FruitPool хранятся ссылки на вашу сцену. Затем, когда спрайт создан (In onAllocatePoolItem), вы навсегда присоединяете его к сцене. Вы никогда не отсоединяете его снова (если игра не сбрасывается, конечно ...)
  2. Когда получен спрайт (onHandleObtainItem), вы вызываете reset(). Это сбрасывает все его поля, такие как положение, вращение и т.д ... Примечание: это не удаляет EntityModifier s! Это просто сбрасывает их. Вы должны удалить их, когда они будут сделаны, иначе это вызовет проблемы.
  3. Когда спрайт перерабатывается (onHandleRecycleItem), вы вызываете методы setIgnoreUpdate(true) и setVisible(false), чтобы этот спрайт не отображался и не обновлялся.

Таким образом, когда вы получаете предмет:

Sprite sprite = pool.obtainPoolItem();

Вы не присоединяете ее к сцене и не вызываете для нее никаких методов сброса или инициализации - просто установите ее положение, как хотите, и зарегистрируйте EntityModifier.

РЕДАКТИРОВАТЬ: Вот полный источник для пула:

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

      // ===========================================================          
      // Fields         
      // =========================================================== 
      private final TextureRegion mTextureRegion;
      private final Scene mAttachedScene;
      // ===========================================================          
      // Constructors          
      // =========================================================== 
      public FruitPool(final TextureRegion pFruitTextureRegion, final Scene pScene) {
           this.mTextureRegion = pFruitTextureRegion;
           this.mAttachedScene = pScene;
      }
      // ===========================================================          
      // Getter & Setter          
      // =========================================================== 

      // ===========================================================          
      // Methods for/from SuperClass/Interfaces          
      // ===========================================================  
      @Override
      protected Sprite onAllocatePoolItem() {
           Sprite newSprite = new Sprite(0, 0, this.mTextureRegion);
           this.mAttachedScene.attachChild(newSprite); //Attaching it HERE to the scene.
           return newSprite;
      }
      @Override
      protected void onHandleObtainItem(final Sprite pItem) {
           pItem.reset();
      }
      @Override
      protected void onHandleRecycleItem(final Sprite pItem) {
           pItem.setVisible(true);
           pItem.setIgnoreUpdate(true); //Just make it ignore updates while it is recycled, DON'T remove it from the scene.
      }
      // ===========================================================          
      // Methods          
      // ===========================================================  

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