gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-29 05:15:46 26 4
gpt4 key购买 nike

我已经实现并添加了一个 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com