安卓和引擎 : handling Collission Detection properly

标签 android collision-detection andengine game-engine collision

我正在开发一个涉及 ff 的简单 AndEngine 游戏。 Sprite

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

我在这里有一个类似的问题:Android AndEngine: Simple sprite collision

游戏的外观:

enter image description here

然而,在解决了最初的问题后,又出现了另一个问题:

当炸弹(通过鼠标点击在飞机当前所在的位置生成并垂直下降直到到达目标或地板)击中目标时,比如士兵,士兵 Sprite 必须分离并在其身后留下一个1 秒的血液飞溅 Sprite ,以及炸弹的爆炸 Sprite 。但是,游戏强制关闭并给出 indexOutOfBoundError。我知道这可能是炸弹与其目标之间的 Sprite 计数差异导致了超出范围的数组错误,但 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 更新处理程序中运行的新代码(根据上面链接的上一个问题的帮助):

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();
        }
    });

}

我注意到,它不会有错误只能是啪啪声或爆炸声。如果 splat 和 explosion 都在碰撞时填充场景,则会发生错误。

此外,即使炸弹没有击中士兵(但在击中地板时仍然分离并被爆炸云取代)它也会给出类似的错误:

我的 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 炸弹函数和碰撞更新处理程序:

    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;
}

我该如何补救?循环逻辑并不完全是我的强项。我也对如何实现这一点持开放态度。

更新:刚刚意识到,即使碰撞的结果是啪啪声或爆炸,也没关系,如果玩家不断发送垃圾炸弹(比如 4-5 次),整个游戏力将关闭。

-似乎每当创建一个焊料/坦克实例时,都有一个允许的轰炸次数。每当炸弹击中一名士兵时,我都会先关闭制造爆炸(这样血迹就会留在原地而不是两者)。它工作正常,但超过 4-6 个炸弹并且游戏关闭。当一个新的士兵实例生成时(意味着当旧的士兵离开屏幕并分离时),玩家将在游戏强制关闭之前获得 4-6 枚炸弹。

最佳答案

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

通常,您希望在使用哪个线程来操作事物方面保持一致,否则会出现奇怪的错误,调试起来很麻烦。

旁注:UI 线程非常适合显示 Toast,请参见此示例:

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

关于安卓和引擎 : handling Collission Detection properly,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12540426/

相关文章:

javascript - p5.j​​s 中的 Angular 碰撞 Angular

macos - 如何在 Mac 上的 Android Studio 中使用 andEngine 制作 "Hello World"

android - 从 Intent 调用 SimpleBaseGameActivity

android - google-services.json 找不到与任何模块的包名称匹配的客户端

Android Facebook 墙贴 - publish_action 权限未授权

javascript - 在尊重 Three.js 中的下一个相邻网格的碰撞时移动一个盒子

reflection - XNA 碰撞检测 - Vector2.Reflect - 帮助计算圆形 Sprite 的法线 - C#

java - 如何在 andengine 中正确销毁和重建场景?

android - picasso 花时间加载图像

android:state_enabled 丢失/不工作?