使用Pool来回收和重用精灵

发布于 2024-12-24 23:28:52 字数 7546 浏览 0 评论 0原文

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

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。

我做错了什么或遗漏了什么吗?

I created this generic pool to re-use some sprites that i add to the scene.

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

The code runs well but it doesnt seem to be reusing the recycled sprites but allocating new ones Each time..

I retrieve a sprite by calling

  face =  fruitsPool.onAllocatePoolItem();

Any suggestions?

EDIT:

I tried the method in the answer setting it up like this..

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

And i call

 Sprite sprite = fruitPool.onAllocatePoolItem();

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

But each time around i get the error that the entity(sprite) already has a parent and has been attached.

Or other times the sprites just return null.

Is there something im doing wrong or missing?

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

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

发布评论

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

评论(2

抹茶夏天i‖ 2024-12-31 23:28:52

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

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

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

new keyword is used to create a new instance of a class by invoking one of the constructors for that class. It doesnot check whether any instance exists or not.

You need to write logic to check whether any instance of the class already exists. if not create a new instance if exists then use the instance

see http://java.sun.com/developer/technicalArticles/Programming/singletons/

听风吹 2024-12-31 23:28:52

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

编辑:(基于评论)

据我了解,当您recycle()时,它只是隐藏了精灵,因此您想要获得对它的引用。

您可以做的是将精灵静态对象作为类的一部分,然后更改 switch 语句,如下所示:

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. . .

基本上,此代码检查是否已经创建了精灵的实例,如果没有,它将创建一个。

This is because in your switch(textureNumber) statement you are creating a new Sprite() every time and returning it to the caller. You should be checking if the Sprite has been created before and returning that instance back to the caller.

Edit: (Based on comment)

From what I understand, when you recycle() it just hides the sprite, so you want to get a reference back to it.

What you can do is make your sprites static objects as part of your class, then change your switch statement, like so:

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. . .

Basically this code checks if there is already an instance of the Sprite created, and if not - it will create one.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文