libGDX、Box2D、碰撞和禁止空中跳跃

3
我正在编写一个球类游戏,希望球不会跳两次或在没有接触地面的情况下跳起来。
我使用了ContactListener中的方法beginContact()endContact()来检测球是否碰到地面。我实现了一个状态(FLYINGLANDED),并在beginContact()方法中将球的状态设置为LANDED,然后在endContact()方法中将其重置为FLYING。在施加跳跃力之前,我会检查该状态。
问题在于,jump()方法在主渲染循环中被调用,而box2D有时会花费两个循环迭代才调用endContact()方法。因此,在box2D模拟与地面接触结束之前,jump()方法会被调用两次。
以下是ContactListener的一部分代码(这不是libGDX的ContactListener,而是直接调用这些方法,将对象传递给它所碰撞的对象):
@Override
public void beginContact(Contact contact, Object objetB) {
    if(objetB instanceof Floor){
        System.out.println("Begin");
        ball.floorBeginContact(contact);
    }
}

@Override
public void endContact(Contact contact, Object objetB) {
    if(objetB instanceof Floor){
        System.out.println("End");
        ball.floorEndContact(contact);
    }       
}

球的部分代码是Actor

public void floorBeginContact(Contact contact){
    state = State.LANDED;
}

public void floorEndContact(Contact contact){
    state = State.FLYING;
}

private void jump(){
    if(state == State.LANDED){
        body.applyForceToCenter(0f, 30f);
        System.out.println(i++ + " - Jump!");
    }
}

public void act(float delta){
    ...

    if(Gdx.input.isKeyPressed(Keys.SPACE)){
        jump();
    }
}

控制台输出大致如下:

Begin
0 - Jump!
1 - Jump!
End
Begin
2 - Jump!
End

我不知道这为什么会发生,也不确定这是否是最好的做法。

在允许另一次跳跃之前,设置一个超时时间,比如说0.2秒怎么样? - iforce2d
3
iforce2d的解决方案:https://www.iforce2d.net/b2dtut/jumpability - Pavel
1个回答

2
public void floorBeginContact(Contact contact){
state = State.LANDED;
 canApplyForce = true;
}

public void floorEndContact(Contact contact){
state = State.FLYING;
}

boolean canApplyForce = true;

private void jump(){
if(state == State.LANDED){
    if(canApplyForce)
    body.applyForceToCenter(0f, 30f);
   canApplyForce = false;
    System.out.println(i++ + " - Jump!");
}
}

public void act(float delta){
...

if(Gdx.input.isKeyPressed(Keys.SPACE)){
    jump();
 }
   }

我想这应该能解决你的问题。

这种方法的缺点是,如果跳跃尝试没有将玩家与地面分离(例如,如果有重物压在他们身上),那么canApplyForce将不会被重置为true。 - iforce2d
这正是他想要的...跳跃不能被启动。他只想在球触地时跳一次。下一次跳跃只能在他离开地面并再次接触地面时进行。 - Paras Mittal
对的。如果有什么重物压在上面,他将永远不会离开地面再次触碰它,因此canApplyForce将不会被重置为true,之后他将无法再跳跃。这可能不是他想要的。 - iforce2d
我感谢您的关注,先生,您说得对,但所有这些都取决于开发人员想要什么。在这个问题中,他希望在触地时回调一次,只有当他再次触地时才能接收到下一个回调。 如果物体上有重物,他将不会收到任何回调,因为他没有离开地面以接收另一个回调,但所有这些都取决于他想要的动态效果,他必须相应地解决它。 - Paras Mittal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接