我正在开发一个简单的AndEngine游戏,其中涉及以下几种精灵:
a.) 坦克 b.) 士兵 c.) 炸弹
我在这里有一个类似的问题:Android AndEngine: Simple sprite collision
游戏的样子如下:
然而,在解决了最初的问题后,又出现了另一个问题:
当炸弹(通过鼠标点击,从飞机当前位置生成并垂直向下移动到达目标或地面)击中目标(比如士兵)时,士兵精灵必须分离出来,并留下1秒钟的血液喷溅精灵,以及一枚来自炸弹的爆炸精灵。然而,游戏会强制关闭,并给出一个indexOutOfBoundError错误。我理解这可能是炸弹和目标之间的精灵计数不一致导致了数组越界错误,但logCat没有提供任何帮助。
09-22 11:13:37.585: E/AndroidRuntime(735): FATAL EXCEPTION: UpdateThread
09-22 11:13:37.585: E/AndroidRuntime(735): java.lang.IndexOutOfBoundsException: Invalid index 5, size is 5
09-22 11:13:37.585: E/AndroidRuntime(735): at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
09-22 11:13:37.585: E/AndroidRuntime(735): at java.util.ArrayList.get(ArrayList.java:304)
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.entity.Entity.onManagedUpdate(Entity.java:1402)
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.entity.Entity.onUpdate(Entity.java:1167)
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.entity.Entity.onManagedUpdate(Entity.java:1402)
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.entity.scene.Scene.onManagedUpdate(Scene.java:284)
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.entity.Entity.onUpdate(Entity.java:1167)
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.engine.Engine.onUpdateScene(Engine.java:591)
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.engine.Engine.onUpdate(Engine.java:586)
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.engine.Engine.onTickUpdate(Engine.java:548)
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.engine.Engine$UpdateThread.run(Engine.java:820)
如您所见,logCat对我的代码没有错误提示,但是针对的是AndEngine本身,这很可能不是问题的原因。
我在onCreateScene Update Handler中运行的新代码(参考前面链接中提供的帮助):
protected void checkSoldierCollision() {
// TODO Auto-generated method stub
int numBombs = bombGroup.getChildCount();
int numTroops = troopsGroup.getChildCount();
final ArrayList<Sprite> toBeDetached = new ArrayList<Sprite>();
for (int i = 0; i < numBombs; i++) {
Sprite s = (Sprite) bombGroup.getChildByIndex(i);
for (int j = 0; j < numTroops; j++) {
Sprite s2 = (Sprite) troopsGroup.getChildByIndex(j);
if (s.collidesWith(s2)) {
/*Sprite splat = createSplat();
splat.setPosition(s.getX(), s.getY());
getEngine().getScene().attachChild(splat);*/
Sprite splode = createExplosion();
splode.setPosition(s.getX(), s.getY());
getEngine().getScene().attachChild(splode);
// WARNING: cannot detach from the list
//while looping through the list
toBeDetached.add(s);
toBeDetached.add(s2);
}
}
}
runOnUpdateThread(new Runnable() {
@Override
public void run() {
for (Sprite s : toBeDetached) {
s.detachSelf();
Sprite splode = createExplosion();
splode.setPosition(s.getX(), s.getY());
getEngine().getScene().attachChild(splode);
}
toBeDetached.clear();
}
});
}
我注意到只有星号展开符或爆炸才不会出现错误。如果星号展开符和爆炸都在碰撞时同时出现,就会出现错误。
即使炸弹没有击中士兵(但仍然会脱落并在地面撞击时产生爆炸云),也会出现类似的错误:
我的createBomb函数:
public Sprite createBomb(float x, float y) {
Sprite bombSprite = new Sprite(x, y, this.mBombTextureRegion,
getVertexBufferObjectManager());
MoveYModifier downModBomb = new MoveYModifier(1, 60, FLOOR);
downModBomb.addModifierListener(new IModifierListener<IEntity>() {
@Override
public void onModifierStarted(IModifier<IEntity> pModifier,
IEntity pItem) {
}
@Override
public void onModifierFinished(IModifier<IEntity> pModifier,
final IEntity pItem) {
pItem.detachSelf();
AnimatedSprite explodeSprite = createExplosion();
explodeSprite.setPosition(pItem.getX(), FLOOR);
getEngine().getScene().attachChild(explodeSprite);
}
});
bombSprite.registerEntityModifier(downModBomb); // register action
return bombSprite;
}
我的onCreateScene炸弹函数和碰撞updateHandler:
scene.setOnSceneTouchListener(new IOnSceneTouchListener() {
@Override
public boolean onSceneTouchEvent(Scene pScene,
TouchEvent pSceneTouchEvent) {
if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Sprite bomb = createBomb(f16Sprite.getX(),
f16Sprite.getY());
bombGroup.attachChild(bomb);
}
});
return true;
}
return false;
}
});
// periodic checks
scene.registerUpdateHandler(new IUpdateHandler() {
@Override
public void onUpdate(float pSecondsElapsed) {
// checkTankCollision();
// checkSoldierBackCollision();
checkSoldierCollision();
}
@Override
public void reset() {
}
});
我的createExplosion方法:
public AnimatedSprite createExplosion() {
AnimatedSprite boomSprite = new AnimatedSprite(0, 0,
this.mExplodeTextureRegion, getVertexBufferObjectManager());
DelayModifier delay = new DelayModifier(.3f); // delay in seconds, can
// take float numbers .5
// seconds
delay.addModifierListener(new IModifierListener<IEntity>() {
@Override
public void onModifierStarted(IModifier<IEntity> pModifier,
IEntity pItem) {
((AnimatedSprite) pItem).animate(new long[] { 100, 100, 100 }, // durations/frame
new int[] { 1, 2, 3 }, // which frames
true); // loop
}
@Override
public void onModifierFinished(IModifier<IEntity> pModifier,
final IEntity pItem) {
((AnimatedSprite) pItem).detachSelf();
}
});
boomSprite.registerEntityModifier(delay); // register action
return boomSprite;
}
我该如何解决这个问题?循环逻辑不是我的强项。我也愿意尝试其他实现方式。
更新:刚刚意识到,即使碰撞的结果是splat或explosion中的任意一个,如果玩家一直轰炸(比如说4-5次),整个游戏将被强制关闭。
-在创建士兵/坦克实例时似乎有一定数量的可允许轰炸次数。我已经关闭了当炸弹击中士兵后首先创建爆炸(所以血液会留在原地而不是同时爆炸和留下)。它运行得不错,但如果超过4-6个炸弹,游戏就会关闭。当新的士兵实例出现(也就是旧的离开屏幕并分离时),玩家可以再使用4-6个炸弹,然后游戏就会强制关闭。