AndEngine GenericPool与计时器从池添加精灵 [英] AndEngine GenericPool with Timer adding sprites from the Pool

查看:143
本文介绍了AndEngine GenericPool与计时器从池添加精灵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的GenericPool我使用了一个游戏,我创造了AndEngine。

 公共类FruitPool扩展GenericPool<雪碧> {
// ================================================ ===========
//常量
// ================================================ ===========

// ================================================ ===========
//领域
// ================================================ ===========
私人最终TextureRegion mTextureRegion;
// ================================================ ===========
//构造函数
// ================================================ ===========
公共FruitPool(最终TextureRegion pFruitTextureRegion){
this.mTextureRegion = pFruitTextureRegion;
}
// ================================================ ===========
//吸气和放大器;二传手
// ================================================ ===========

// ================================================ ===========
//方法/从父类/接口
// ================================================ ===========
@覆盖
保护雪碧onAllocatePoolItem(){
返回新的Sprite(0,0,this.mTextureRegion);
}
@覆盖
保护无效onHandleObtainItem(最终雪碧pItem){
pItem.reset();
}
@覆盖
保护无效onHandleRecycleItem(最终雪碧pItem){
pItem.setVisible(真正的);
pItem.setIgnoreUpdate(真正的);
}
// ================================================ ===========
//方法
// ================================================ ===========

// ================================================ ===========
 //内部类和匿名类
// ================================================ ===========
 }
 

正如你看到的我提供一个TextureRegion池中创建在这样的池精灵..

  FruitPool池1 =新FruitPool(TextureRegion);
精灵蓝色圆球= pool1.obtainItem();
 

我再回收精灵后,已经关闭屏幕使用

  pool1.recyclePoolItem(蓝色圆球);
 

遇到的问题IA是,我有一个计时器,增加了一个雪碧差不多每2秒。

现在的问题是,如果精灵去处理不当关闭屏幕还和被回收,我收到了雪碧已经有父的错误在我的logcat中。

有没有一种办法可以使人们有可能,我希望在对泳池的拉尽可能多的精灵,然后再利用每一个,因为它熄灭屏幕稍后重用?

我的样子是不是正确的,现在清楚心不是工作。

感谢您的帮助家伙!

编辑:另外这里的方法,其中我添加取决于所选的号码精灵

 私人无效addFace2(){
         随机兰特=新的随机();
         随机randFruit =新的随机();


         如果(isGameRunning){
         面对= NULL;

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



                开关(fruitNumber){
                   情况1:
                      //项目1 code
                       FACE = pool1.obtainPoolItem();
                       this.pool1List.add(面);

                      打破;
                   案例2:
                        FACE = pool2.obtainPoolItem();
                         this.pool2List.add(面);
                      打破;
                   案例3:
                       FACE = pool3.obtainPoolItem();
                     this.pool3List.add(面);
                       打破;
                   //等等。 。 。
                   壳体4:
                       FACE = pool4.obtainPoolItem();
                     this.pool4List.add(面);
                       打破;
                   壳体5:
                       FACE = pool5.obtainPoolItem();
                     this.pool5List.add(面);

                       打破;

                 }
                this.mFaceCount ++;
           Log.e(脸,脸+ this.mFaceCount);

           如果(脸!= NULL){
            INT rangeDuration = maxDuration2  -  minDuration2;
            INT actualDuration = rand.nextInt(rangeDuration)+ minDuration2;
            MoveYModifier模=新MoveYModifier(actualDuration,face.getY(),mCamera.getHeight());
            face.registerEntityModifier(MOD);
            如果(face.hasParent()){
                Log.e(面子,面子有父);
            }其他{
                  this.mScene.attachChild(面);
            thump.play();
            }

           }
     }
 

解决方案

这可能是因为您尝试一旦你得到它的精灵附着到现场(虽然它不会发生在你的code ..) ,而你没有脱离它一旦被回收。

我建议你使用的方法是这样的(我用它在我的游戏,我有像你这样的精灵池,并能正常工作):

  1. FruitPool 取值保持引用到场景。然后,当精灵是的的(在 onAllocatePoolItem )将其附加到现场,为好。您的永远的再次分离它(除非游戏复位,当然...)
  2. 当得到一个精灵( onHandleObtainItem )你叫重设()就可以了。重置所有它的领域里,如位置,旋转等... 注意:这样做的没有的删除 EntityModifier 小号!它只是对它们进行复位。您应该删除它们当他们完成,否则会引起问题。
  3. 当精灵被回收( onHandleRecycleItem )调用方法 setIgnoreUpdate(真)的setVisible(假)所以这个精灵不会被绘制和更新。

这样,当你得到一个项目:

 雪碧雪碧= pool.obtainPoolItem();
 

您的的附加到了现场,你不调用它的任何复位或初始化方法 - 刚刚成立它的位置,只要你想,并注册 EntityModifier

编辑:下面是完整的源池:

 公共类FruitPool扩展GenericPool<雪碧> {
      // ================================================ ===========
      //常量
      // ================================================ ===========

      // ================================================ ===========
      //领域
      // ================================================ ===========
      私人最终TextureRegion mTextureRegion;
      私人决赛现场mAttachedScene;
      // ================================================ ===========
      //构造函数
      // ================================================ ===========
      公共FruitPool(最终TextureRegion pFruitTextureRegion,最后一幕pScene){
           this.mTextureRegion = pFruitTextureRegion;
           this.mAttachedScene = pScene;
      }
      // ================================================ ===========
      //吸气和放大器;二传手
      // ================================================ ===========

      // ================================================ ===========
      //方法/从父类/接口
      // ================================================ ===========
      @覆盖
      保护雪碧onAllocatePoolItem(){
           精灵newSprite =新精灵(0,0,this.mTextureRegion);
           this.mAttachedScene.attachChild(newSprite); //附加在这里现场。
           返回newSprite;
      }
      @覆盖
      保护无效onHandleObtainItem(最终雪碧pItem){
           pItem.reset();
      }
      @覆盖
      保护无效onHandleRecycleItem(最终雪碧pItem){
           pItem.setVisible(真正的);
           pItem.setIgnoreUpdate(真正的); //只是让它忽略更新,同时其回收,不要将其从场景中删除。
      }
      // ================================================ ===========
      //方法
      // ================================================ ===========

      // ================================================ ===========
      //内部类和匿名类
      // ================================================ ===========
}
 

I have this GenericPool i am using for a Game i am creating in 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          
// ===========================================================  
 }

As you see i supply a TextureRegion to the pool to create a sprite in the pool like this..

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

I then recycle the sprites after it has gone off the screen using

  pool1.recyclePoolItem(blueBall);

The issue i a having is that i have a Timer that adds a Sprite just about every 2 seconds.

The problem is if the sprite hasnt gone off the screen yet and been recycled i get a "Sprite already has Parent" error in my Logcat.

Is there a way i can make it possible to pull as many Sprites as i want out of the Pool and then recycle each one as it goes off the screen to be later reused?

The way i have it right now clearly isnt working.

Thanks for the help Guys!

EDIT: Also here is the method where i add the sprites depending on the number selected

  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();
            }

           }
     }

解决方案

It's probably because you try to attach the sprite to the scene once you obtained it (Even though it won't happen in your code..), and you didn't detach it once it is recycled.

The approach I suggest you to use is this (I am using it in my game where I have a sprite pool like yours, and it works fine):

  1. The FruitPools hold references to your scene. Then, when a sprite is created (In onAllocatePoolItem) you attach it to the scene, for good. You never detach it again (Unless the game resets, of course...)
  2. When a sprite is obtained (onHandleObtainItem) you call reset() on it. That resets all it's fields, like position, rotation, etc... Note: this does not remove the EntityModifiers! It just resets them. You should remove them when they are done, otherwise it will cause problems.
  3. When a sprite is recycled (onHandleRecycleItem) you call the methods setIgnoreUpdate(true) and setVisible(false) so this sprite won't be drawn and updated.

This way, when you obtain an item:

Sprite sprite = pool.obtainPoolItem();

You don't attach it to the scene, and you don't call any reset or initialization methods on it - just set it's position as you want, and register the EntityModifier.

EDIT: Here is the full source for the pool:

 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          
      // ===========================================================  
}

这篇关于AndEngine GenericPool与计时器从池添加精灵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆