Java jMonkeyEngine针对单个碰撞的多个碰撞事件
我已经实现并添加了一个Java jMonkeyEngine针对单个碰撞的多个碰撞事件,java,jmonkeyengine,Java,Jmonkeyengine,我已经实现并添加了一个physiccollisionlistener,以在投射物击中玩家时进行注册。但当一颗炮弹击中一名球员时。触发多个事件。 我使用simpleInitApp()方法中的bulletAppState.getPhysicsSpace().addCollisionListener(collisionListener)添加侦听器。我在碰撞后取出了弹丸 我需要做什么才能为每个射弹只获得一个事件 这是我的密码: public void collision(PhysicsCollision
physiccollisionlistener
,以在投射物击中玩家时进行注册。但当一颗炮弹击中一名球员时。触发多个事件。
我使用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引擎以固定的帧速率在不同的线程中运行。如果
physicspace
的状态从外部更改,则不会立即识别更改
引用jME Wiki:
应用力或检查重叠仅在物理更新周期(不是每一帧)生效。如果在simpleUpdate()循环中的任意点进行物理交互,调用将以不规则的间隔被丢弃,因为它们发生在循环之外 解决方案是从
physicticklistener
中删除物理对象,该文件将调用与jBullet的帧速率同步。维基上也有一些描述。此实现将只产生一个冲突事件:
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);
}
}
}
}
射弹现在需要一个射弹CollisionControl
。设置如下:
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);
}
我已经将删除例程移到了tick listner,现在它可以工作了。你的GhostControl解决方案不起作用,它会让我与地形发生大量碰撞。但是非常感谢你详细的回答。