java - jMonkeyEngine 单次碰撞的多个碰撞事件

标签 java jmonkeyengine

我已经实现并添加了一个 PhysicsCollisionListener 以在射弹击中玩家时进行注册。但是当射弹击中玩家时。触发多个事件。 我在我的 simpleInitApp() 方法中使用 bulletAppState.getPhysicsSpace().addCollisionListener(collisionListener) 添加我的监听器。我在碰撞后移除弹丸。

我需要做什么才能为每个射弹只获取一个事件?

这是我的代码:

public void collision(PhysicsCollisionEvent event) {
        //nodeA is a projectile
        if(event.getNodeA().getName().startsWith("Projectile")) {
            //projectile hits player
            if(event.getNodeB().getName().startsWith("Player")) {
                onHit(event.getNodeA(), event.getNodeB().getParent().getUserData("player");
            }
            //projectile hits projectile
            else if(event.getNodeB().getName().startsWith("Projectile")) {
               return; 
            }
            //in any case, remove projectile
            projectileNode.detachChild(event.getNodeA());
            bulletAppState.getPhysicsSpace().remove(event.getNodeA());
        }
        //nodeB is a projectile
        if(event.getNodeB().getName().startsWith("Projectile")) {
            //projectile hits player
            if(event.getNodeA().getName().startsWith("Player")) {
                onHit(event.getNodeB(), event.getNodeA().getParent().getUserData("player");
            }
            //in any case, remove projectile
            projectileNode.detachChild(event.getNodeB());
            bulletAppState.getPhysicsSpace().remove(event.getNodeB());
        }
    }

最佳答案

问题在于底层的 jBullet 引擎以固定的帧率在不同的线程中运行。如果从外部更改了 PhysicsSpace 的状态,则不会立即识别更改。

引用 jME Wiki:

http://hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:physics_listeners#physics_tick_listener
Applying forces or checking for overlaps only has an effect right at a physics update cycle, which is not every frame. If you do physics interactions at arbitrary spots in the simpleUpdate() loop, calls will be dropped at irregular intervals, because they happen out of cycle.

解决方案是从 PhysicsTickListener 中删除物理对象,它使调用与 jBullet 的帧速率同步。它也在 wiki 中有所描述。此实现只会产生一个碰撞事件:

private class ProjectileCollisionControl extends GhostControl implements PhysicsTickListener {
    public ProjectileCollisionControl(CollisionShape shape) {
        super(shape);
    }

    public void prePhysicsTick(PhysicsSpace space, float tpf) {}

    // Invoked after calculations and after events have been queued
    public void physicsTick(PhysicsSpace space, float tpf) {
        for(PhysicsCollisionObject o : getOverlappingObjects()) {
            Spatial other = (Spatial) o.getUserObject();

            // I just hit a player, remove myself
            if(other.getName().startsWith("Player"))
            {
                space.remove(this);
                space.removeTickListener(this);
            }
        }
    }
}

射弹现在需要一个 ProjectileCollisionControl。像这样设置:

public void simpleInitApp() {
    BulletAppState state = new BulletAppState();
    getStateManager().attach(state);

    PhysicsSpace space = state.getPhysicsSpace();
    space.addCollisionListener(new PhysicsCollisionListener()
    {
        public void collision(PhysicsCollisionEvent event) {
            // Same code but without bulletAppState.getPhysicsSpace().remove()
        }
    });

    Material mat = new Material(getAssetManager(), "Common/MatDefs/Misc/ShowNormals.j3md");
    CollisionShape collisionShape = new BoxCollisionShape(new Vector3f(5, 5, 5));

    ProjectileCollisionControl ctrlA = new ProjectileCollisionControl(collisionShape);
    Box a = new Box(new Vector3f(0.4f, 0, 0), 1, 1, 1);
    Geometry boxGeomA = new Geometry("Box A", a);
    boxGeomA.setMaterial(mat);
    boxGeomA.addControl(ctrlA);

    ProjectileCollisionControl ctrlB = new ProjectileCollisionControl(collisionShape);
    Box b = new Box(new Vector3f(-0.4f, 0, 0), 1, 1, 1);
    Geometry boxGeomB = new Geometry("Box B", b);
    boxGeomB.setMaterial(mat);
    boxGeomB.addControl(ctrlB);

    getRootNode().attachChild(boxGeomA);
    getRootNode().attachChild(boxGeomB);
    space.add(ctrlA);
    space.add(ctrlB);
    space.addTickListener(ctrlA);
    space.addTickListener(ctrlB);
}

关于java - jMonkeyEngine 单次碰撞的多个碰撞事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26614925/

相关文章:

java - 是否可以根据计数在循环内声明多个变量?

java - 满足条件时获取时间变量的实例

java - jMonkeyEngine相机跟随

java - 在 OpenGL 中获取相机在 X、Y 和 Z 轴上的弧度旋转?

jmonkeyengine - 定向边界框

java - Hazelcast 记录 70% 阈值消息而不向 map 添加任何内容

java - 尝试在 Eclipse 中运行更新 UI 时收到消息 "Cannot start the update ui..."

java - XOM 获取文档到字符串

java - jMonkey优化类似于Java3D的

java - Jmonkey碰撞检测