我有一个 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,以在池中创建一个 Sprite ,如下所示..
FruitPool pool1 = new FruitPool(TextureRegion);
Sprite blueBall = pool1.obtainItem();
然后,我使用
在 Sprite 离开屏幕后对其进行回收 pool1.recyclePoolItem(blueBall);
我遇到的问题是我有一个计时器,大约每 2 秒添加一个 Sprite。
问题是,如果 Sprite 还没有离开屏幕并被回收,我会在 Logcat 中收到“ Sprite 已经有父级”错误。
有没有一种方法可以让我从池中取出尽可能多的 Sprite ,然后在它们离开屏幕时回收每个 Sprite 以供以后重复使用?
我现在的方式显然不起作用。
感谢大家的帮助!
编辑:这也是我根据所选数量添加 Sprite 的方法
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();
}
}
}
最佳答案
这可能是因为您在获得 Sprite 后尝试将其附加到场景(即使它不会在您的代码中发生..),并且在回收它后您没有将其分离。
我建议你使用的方法是这样的(我在我的游戏中使用它,我有一个像你一样的 Sprite 池,并且效果很好):
FruitPool
保存对场景的引用。然后,当创建 Sprite 时(在onAllocatePoolItem
中),您将其永久附加到场景中。您永远不再将其分离(当然,除非游戏重置......)- 当获得 Sprite (
onHandleObtainItem
)时,您可以对其调用reset()
。这会重置所有字段,例如位置、旋转等...注意:这不会删除EntityModifier
!它只是重置它们。完成后您应该将其删除,否则会导致问题。 - 当 Sprite 被回收时 (
onHandleRecycleItem
),您可以调用方法setIgnoreUpdate(true)
和setVisible(false)
,这样该 Sprite 就不会被回收。无需绘制和更新。
这样,当您获得元素时:
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
// ===========================================================
}
关于java - AndEngine GenericPool 带有计时器,从池中添加 Sprite ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8611074/