Android和Engine:正确处理碰撞检测

Android和Engine:正确处理碰撞检测,android,collision-detection,andengine,game-engine,collision,Android,Collision Detection,Andengine,Game Engine,Collision,我正在做一个简单的游戏,包括ff。精灵 a、 )坦克 b、 )士兵 c、 )炸弹 我在这里有一个类似的问题: 游戏是什么样子的: 但是,在解决初始问题后,出现了另一个问题: 当炸弹(在飞机当前所在的位置产卵,并通过鼠标点击垂直下降,直到到达目标或地面)击中目标时,例如士兵,士兵精灵必须分离并在其身后留下一个血溅精灵1秒钟,以及炸弹上的爆炸精灵。但是,游戏力关闭时会出现indexOutOfBoundError。我知道这可能是炸弹和目标之间的精灵数量不一致导致了一个超出范围的数组错误,但是logC

我正在做一个简单的游戏,包括ff。精灵

a、 )坦克 b、 )士兵 c、 )炸弹

我在这里有一个类似的问题:

游戏是什么样子的:

但是,在解决初始问题后,出现了另一个问题:

当炸弹(在飞机当前所在的位置产卵,并通过鼠标点击垂直下降,直到到达目标或地面)击中目标时,例如士兵,士兵精灵必须分离并在其身后留下一个血溅精灵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本身上给出错误,很可能情况并非如此

我在OnCreateSecene更新处理程序中运行的新代码(根据上面链接的上一个问题的帮助):

我的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;
}
public AnimatedSprite createExplosion(){
AnimatedSprite boomSprite=新的AnimatedSprite(0,0,
this.mExplodeTextureRegion,getVertexBufferObjectManager());
DelayModifier delay=新的DelayModifier(.3f);//延迟以秒为单位,可以
//以浮点数为例
//秒
delay.addModifierListener(新的IModifierListener(){
@凌驾
修改器启动时的公共无效(IModifier pModifier,
(皮特姆){
((AnimatedSprite)pItem).设置动画(新长[]{100100100},//持续时间/帧
新的int[]{1,2,3},//哪个帧
true);//循环
}
@凌驾
修改器上的公共无效已完成(IModifier pModifier,
最终结果(pItem){
((动画精灵)pItem.detachSelf();
}
});
boomSprite.registerEntityModifier(延迟);//注册操作
返回精灵;
}
我该如何补救?循环逻辑不完全是我的强项。我也对如何实施这一方案持开放态度

更新:我刚刚意识到,即使碰撞的结果是飞溅或爆炸,也没关系,如果玩家继续滥发炸弹(比如说4-5次),整个游戏力量就会关闭


-每当创建焊料/罐实例时,似乎有允许的爆炸次数。每当炸弹击中士兵时,我首先关闭了“创建爆炸”(这样,血盘就会留在原地,而不是两者同时出现)。它工作正常,但超过4-6枚炸弹,游戏结束。当一个新的士兵实例产生时(意味着当旧的士兵离开屏幕并分离时),玩家将在游戏部队关闭之前得到4-6枚炸弹。

为了调试这个,你需要通过输出(可能通过日志)来监控有多少炸弹被实际添加到
爆炸组和
部队组中,这应该与应该添加的数量一致。还可以尝试输出
getChildCount()
的值以及i和j参数

要进行疯狂猜测,请尝试以下方法:

for (int i = 0; i < toBeDetached.size(); i++) {

     toBeDetached.get(i).detachSelf();

  }
for(int i=0;i
问题可能是由于您通过调用runOnUiThread将炸弹附加到UI线程上,但检查了更新线程上的冲突。尝试在runOnUpdateThread中添加炸弹

一般来说,您希望在使用什么线程来操作东西方面保持一致,否则会出现奇怪的bug,这是调试的难点

附带说明:UI线程非常适合显示祝酒词,请参见以下示例:

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        Toast.makeText(GameActivity.this, "Hello!", Toast.LENGTH_SHORT).show();
    }
});

好的,在约翰尼先生的帮助下,我已经能够在我的代码中解决这个问题。考虑下面的片段:

    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());
                explodeGroup.attachChild(splode);
                // 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 splat = createSplat();
                splat.setPosition(s.getX(), s.getY());
                getEngine().getScene().attachChild(splat);

                Sprite splode = createExplosion();
                splode.setPosition(s.getX(), s.getY());
                explodeGroup.attachChild(splode);
                // getEngine().getScene().attachChild(splode);

            }
            toBeDetached.clear();
        }
    });

}
protectedvoid checkSoldierCollision(){
//TODO自动生成的方法存根
int numBombs=bombGroup.getChildCount();
int numTroops=troopsGroup.getChildCount();
最终ArrayList ToBedeAttached=新ArrayList();
for(int i=0;i
正如我所提到的,游戏崩溃是因为两个碰撞物体的计数不一致。正如JohnEye先生指出的那样,当一个精灵在UI线程中生成时,这种情况就会发生,但在更新线程中就不会了。此外,c
for (int i = 0; i < toBeDetached.size(); i++) {

     toBeDetached.get(i).detachSelf();

  }
runOnUiThread(new Runnable() {
    @Override
    public void run() {
        Toast.makeText(GameActivity.this, "Hello!", Toast.LENGTH_SHORT).show();
    }
});
    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());
                explodeGroup.attachChild(splode);
                // 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 splat = createSplat();
                splat.setPosition(s.getX(), s.getY());
                getEngine().getScene().attachChild(splat);

                Sprite splode = createExplosion();
                splode.setPosition(s.getX(), s.getY());
                explodeGroup.attachChild(splode);
                // getEngine().getScene().attachChild(splode);

            }
            toBeDetached.clear();
        }
    });

}
    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) {
            runOnUpdateThread(new Runnable() {
                @Override
                public void run() {
                    pItem.detachSelf();
                }
            });
            AnimatedSprite explodeSprite = createExplosion();
            explodeSprite.setPosition(pItem.getX(), FLOOR);
            explodeGroup.attachChild(explodeSprite);
            // getEngine().getScene().attachChild(explodeGroup);
        }
    });
    bombSprite.registerEntityModifier(downModBomb);
    return bombSprite;
}
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) {
            runOnUpdateThread(new Runnable() {
                @Override
                public void run() {
                    ((AnimatedSprite) pItem).detachSelf();
                }
            });
        }
    });

    boomSprite.registerEntityModifier(delay); // register action
    return boomSprite;
}
public Sprite createSplat() {
    Sprite splatSprite = new Sprite(0, 0, this.mSplatTextureRegion,
            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) {

        }

        @Override
        public void onModifierFinished(IModifier<IEntity> pModifier,
                final IEntity pItem) {
            runOnUpdateThread(new Runnable() {
                @Override
                public void run() {
                    pItem.detachSelf();
                }
            });
        }
    });

    splatSprite.registerEntityModifier(delay); // register action
    return splatSprite;
}