GenericPool 可重用每秒所需的精灵

发布于 2024-12-24 20:47:01 字数 4286 浏览 2 评论 0原文

我创建了这个有 5 个静态变量的池。

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;
private static Sprite fruitTwo;
private static Sprite fruitThree;
private static Sprite fruitFour;
private static Sprite fruitFive;
private  Sprite fruit;
// ===========================================================          
// 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          
// ===========================================================  
}

正如您在我的 onAllocate 方法中看到的,我检查该项目是否存在,如果存在,我会在方法中返回它。

因此,在我的主要活动中,我使用

          face =  fruitsPool.onAllocatePoolItem();

This 最初有效,但问题是我大约每秒将面部附加到场景。并且我收到错误,表示精灵已附加到场景。起初,我发现做到这一点的唯一方法是每秒创建一个新的精灵,并在完成后将其分离,但这会使用大量内存并导致滞后,不冻结。

有人对我需要做什么有任何指示,或者对我的代码有建议吗?

I have created this Pool that has 5 static variables.

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;
private static Sprite fruitTwo;
private static Sprite fruitThree;
private static Sprite fruitFour;
private static Sprite fruitFive;
private  Sprite fruit;
// ===========================================================          
// 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          
// ===========================================================  
}

As you see in my onAllocate method i check to see if the item exist's if it does i return it in the method.

So in my main activity i use

          face =  fruitsPool.onAllocatePoolItem();

This works initially but the problem is i attach the face to the scene about every second.And i get the error that the sprite has already been attached to the scene. At first the only way i found to do this was to create a new Sprite each second, and detach it when im finished with it, but this uses wayy to much memory and causes lag, na freezes.

Does anyone have any pointers for what i need to do, or suggestions for me code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

撞了怀 2024-12-31 20:47:03

永远不会调用onAllocatePoolItem。当池为空且请求项目时,会在 GenericPool 类内部调用此方法。

您应该从 FruitPool 类外部调用的唯一方法是:

  1. obtainPoolItem 获取池项目; 不是 onAllocatePoolItem
  2. recyclePoolItem 回收项目。记得在完成该项目后调用它。
  3. batchAllocatePoolItems,但您的情况不需要它。当您想在某个点创建池项时可以使用它;但启动 Sprite 并不是一个繁重的过程,因此您不需要。

您不应该调用任何其他方法。

再说一次,你破坏了对象池的目的! onAllocatePoolItem 应该始终返回一个全新对象!不是现有的!这就是你得到的原因

实体已有父级

错误。

顺便说一句,当我第一次为您构建此类时,我在创建场景时将精灵附加到场景中。你为什么现在不做呢?

我已经编辑了它,并添加了一些评论。

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

// ===========================================================          
// Fields         
// =========================================================== 
private ITextureRegion[] mTextureRegions = new ITextureRegion[5];
private Scene mScene;
private int mCount;
// ===========================================================          
// Constructors          
// =========================================================== 
public FruitPool(final ITextureRegion watermelonRegion, ITextureRegion cherryRegion,ITextureRegion mBallTextureRegion, ITextureRegion grapeTextureRegion, ITextureRegion strawberryTextureRegion,Scene attachedScene) {
    this.mTextureRegions[0] = watermelonRegion;
    this.mTextureRegions[1] =cherryRegion;
    this.mTextureRegions[2]= mBallTextureRegion;
    this.mTextureRegions[3]= grapeTextureRegion;
    this.mTextureRegions[4] = strawberryTextureRegion;
    this.mScene = attachedScene;
}
// ===========================================================          
// Getter & Setter          
// =========================================================== 

// ===========================================================          
// Methods for/from SuperClass/Interfaces          
// ===========================================================  
@Override
protected Sprite onAllocatePoolItem() {
    //This method is called internally by GenericPool<T> class.
    //It is called when the pool is out of items, so a new one should be allocated.
    //Remember - you MUST create a new item here! Don't return a reference to an existing one.
    int fruitPos = MathUtils.random(0, 4);
    final Sprite fruit = new Sprite(0, 0, this.mTextureRegions[fruitPos]);
    this.mScene.attachChild(fruit);
    return fruit;
}
@Override
protected void onHandleObtainItem(final Sprite pItem) {
    //Before we return the sprite to the caller, we reset it's fields.
    //This method is called internaly by GenericPool<T> class.
    pItem.reset();
}
@Override
protected void onHandleRecycleItem(final Sprite pItem) {
    //When an item is recycled, this method is called. We make it invisible and set it to ignores updates.
    //We DONT detach it from the scene, just make it ignore updates.
    //Again, this method is called internally by GenericPool<T>class.
    pItem.setVisible(false);
    pItem.setIgnoreUpdate(true);
}
// ===========================================================          
// Methods          
// ===========================================================  

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

请记住 - 您从池中附加/分离精灵!它在创建时附加一次。

You never call onAllocatePoolItem. This method is called internally in the GenericPool<T> class when the pool is empty and an item is requested.

The only methods you should be calling from outside of your FruitPool class are:

  1. obtainPoolItem to get a pool item; Not onAllocatePoolItem.
  2. recyclePoolItem to recycle an item. Remember to call it when you are done with the item.
  3. batchAllocatePoolItems, but you don't need it in your case. It could be used when you want to create the pool items at a certain point; But initiating Sprite's is not a heavy process, so you don't need.

You shouldn't call any other methods.

Again, you are breaking the purpose of the object pool! onAllocatePoolItem should always return a brand new object! Not an existing one! That's the reason you get the

Entity already has a parent

error.

By the way, when I first built this class for you, I attached the sprite to the scene when it's created. Why aren't you doing it now?

I have edited it, and added some comments.

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

// ===========================================================          
// Fields         
// =========================================================== 
private ITextureRegion[] mTextureRegions = new ITextureRegion[5];
private Scene mScene;
private int mCount;
// ===========================================================          
// Constructors          
// =========================================================== 
public FruitPool(final ITextureRegion watermelonRegion, ITextureRegion cherryRegion,ITextureRegion mBallTextureRegion, ITextureRegion grapeTextureRegion, ITextureRegion strawberryTextureRegion,Scene attachedScene) {
    this.mTextureRegions[0] = watermelonRegion;
    this.mTextureRegions[1] =cherryRegion;
    this.mTextureRegions[2]= mBallTextureRegion;
    this.mTextureRegions[3]= grapeTextureRegion;
    this.mTextureRegions[4] = strawberryTextureRegion;
    this.mScene = attachedScene;
}
// ===========================================================          
// Getter & Setter          
// =========================================================== 

// ===========================================================          
// Methods for/from SuperClass/Interfaces          
// ===========================================================  
@Override
protected Sprite onAllocatePoolItem() {
    //This method is called internally by GenericPool<T> class.
    //It is called when the pool is out of items, so a new one should be allocated.
    //Remember - you MUST create a new item here! Don't return a reference to an existing one.
    int fruitPos = MathUtils.random(0, 4);
    final Sprite fruit = new Sprite(0, 0, this.mTextureRegions[fruitPos]);
    this.mScene.attachChild(fruit);
    return fruit;
}
@Override
protected void onHandleObtainItem(final Sprite pItem) {
    //Before we return the sprite to the caller, we reset it's fields.
    //This method is called internaly by GenericPool<T> class.
    pItem.reset();
}
@Override
protected void onHandleRecycleItem(final Sprite pItem) {
    //When an item is recycled, this method is called. We make it invisible and set it to ignores updates.
    //We DONT detach it from the scene, just make it ignore updates.
    //Again, this method is called internally by GenericPool<T>class.
    pItem.setVisible(false);
    pItem.setIgnoreUpdate(true);
}
// ===========================================================          
// Methods          
// ===========================================================  

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

Remember - you don't attach/detach a sprite from the pool! It is attached once when it's created.

微暖i 2024-12-31 20:47:03

我不确定这是否有帮助。看看这是否有帮助。为什么需要链表?你可以使用数组,对吗?

private final Fruit fruits[] = new Fruits[4];
//Initialize this in the constructor...
for(int i =0; i < fruits.length; i++) {
    fruits[i] = new Fruits();
}

@Override
protected Sprite onAllocatePoolItem() {


     Random randFruit = new Random();

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

     switch(textureNumber){
     case 1:
         if (fruitOne == null) {
              fruitOne = fruits[textureNumber];
              //new Sprite(0, 0, this.texture1);
              //use setters to set the values here..
              Log.e("FruitPool", "Item rremade");
            } else {
              fruit = fruits[textureNumber];
              Log.e("FruitPool", "Item exist in pool..Used");
            }
          break;
     case 2:
         if(fruitTwo == null){
              fruitTwo = fruits[textureNumber];
          //new Sprite(0, 0, this.texture1);
          //use setters to set the values here..
              Log.e("FruitPool", "Item rremade");
         }else{
             fruit = fruits[textureNumber];
             Log.e("FruitPool", "Item exist in pool..Used");
         }
....

I am not sure, if this helps. See if this helps. Why do you need a LinkedList? You can use arrays, right?

private final Fruit fruits[] = new Fruits[4];
//Initialize this in the constructor...
for(int i =0; i < fruits.length; i++) {
    fruits[i] = new Fruits();
}

@Override
protected Sprite onAllocatePoolItem() {


     Random randFruit = new Random();

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

     switch(textureNumber){
     case 1:
         if (fruitOne == null) {
              fruitOne = fruits[textureNumber];
              //new Sprite(0, 0, this.texture1);
              //use setters to set the values here..
              Log.e("FruitPool", "Item rremade");
            } else {
              fruit = fruits[textureNumber];
              Log.e("FruitPool", "Item exist in pool..Used");
            }
          break;
     case 2:
         if(fruitTwo == null){
              fruitTwo = fruits[textureNumber];
          //new Sprite(0, 0, this.texture1);
          //use setters to set the values here..
              Log.e("FruitPool", "Item rremade");
         }else{
             fruit = fruits[textureNumber];
             Log.e("FruitPool", "Item exist in pool..Used");
         }
....
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文