所以我确实有一个我不明白的问题。在尝试找出问题所在之后,我决定记录一个video并在此处询问。

在视频中,请注意左上角的True / False布尔值。这是我的变量canJump的值。首先,只需左右移动“ Player”,该值就在true和false之间。当玩家上下倾斜时也会发生这种情况。

使用Tiled创建地图/碰撞层。

我的TiledObject类:

public class TiledObjectUtil {

public static float PPM = 32;

public static void parseTiledObjectLayer(World world, MapObjects objects) {
    for(MapObject object : objects) {
        Shape shape;

        if(object instanceof PolylineMapObject) {
            shape = createPolyLine((PolylineMapObject) object);

        } else {
            continue;
        }

        Body body;
        BodyDef bdef = new BodyDef();
        bdef.type = BodyDef.BodyType.StaticBody;
        body = world.createBody(bdef);
        body.createFixture(shape, 1.0f);

        shape.dispose();
    }
}

private static ChainShape createPolyLine(PolylineMapObject polyline) {
    float[] vertices = polyline.getPolyline().getTransformedVertices();
    Vector2[] worldVertices = new Vector2[vertices.length / 2];

    for(int i = 0; i<worldVertices.length; i++) {
        worldVertices[i] = new Vector2(vertices[i * 2] / PPM, vertices[i*2+1] / PPM);
    }
    ChainShape cs = new ChainShape();
    cs.createChain(worldVertices);
    return cs;
}}


和我的播放器类:

public class Player {

private BodyDef def = new BodyDef();
public Body playerBody;


private float speed = 10;

public Player() {

}

public void update() {

    if (InputUtil.moveLeft)  {
        playerBody.setLinearVelocity(-speed, playerBody.getLinearVelocity().y);
    }
    if (InputUtil.moveRight)  {
        playerBody.setLinearVelocity(speed, playerBody.getLinearVelocity().y);
    }

    if (!InputUtil.moveLeft && !InputUtil.moveRight) {

        playerBody.setLinearVelocity(0, playerBody.getLinearVelocity().y);
    }
}

public void jump() {
    if (ContactUtil.canJump) {
        playerBody.applyLinearImpulse(0, 80, 0, 0, true);

    }

}


public Body createPlayer(World world) {
    def.type = BodyDef.BodyType.DynamicBody;
    def.position.set(20, 20);
    def.fixedRotation = true;

    playerBody = world.createBody(def);

    PolygonShape shape = new PolygonShape();
    shape.setAsBox(2f / 2, 2f / 2);

    FixtureDef playerFixture = new FixtureDef();
    playerFixture.density = 1f;
    playerFixture.shape = shape;
    playerFixture.restitution = 0f;
    playerFixture.friction = 1f;
    playerBody.createFixture(playerFixture);

    shape.setAsBox(2f / 2, 1f / 2, new Vector2(0, 0 - 1), 0);
    playerFixture.shape = shape;
    playerFixture.isSensor = true;
    playerBody.createFixture(playerFixture).setUserData("player");

    shape.dispose();

    return playerBody;
} }


最后,我的ContactListener:

public class ContactUtil implements ContactListener {

public static boolean canJump;


public ContactUtil() {

}

@Override
public void beginContact(Contact contact) {

    Fixture fixtureA = contact.getFixtureA();
    Fixture fixtureB = contact.getFixtureB();

    System.out.println(fixtureA.getUserData() + ", " + fixtureB.getUserData());

    if (fixtureA.getUserData() == "player" && fixtureB.getUserData() == null) {
        canJump = true;
    }
    if (fixtureA.getUserData() == null && fixtureB.getUserData() == "player") {
        canJump = true;
    }

}

@Override
public void endContact(Contact contact) {

    Fixture fixtureA = contact.getFixtureA();
    Fixture fixtureB = contact.getFixtureB();

    System.out.println(fixtureA.getUserData() + ", " + fixtureB.getUserData());

    if (fixtureA.getUserData() == "player" && fixtureB.getUserData() == null) {
        canJump = false;
    }
    if (fixtureA.getUserData() == null && fixtureB.getUserData() == "player") {
        canJump = false;
    }

}


而且,我的播放器每次在斜坡上停下来都会跳一点。我知道是由于以下这一行:playerBody.setLinearVelocity(0, playerBody.getLinearVelocity().y);

如果有人知道更好的方式来处理运动,将不胜感激。

最佳答案

我似乎记得过去有这个确切的问题!我认为问题在于您在beginContactendContact中的逻辑。

我将用我粗俗的MS Paint技术来解释这个问题。想象以下情况:您的播放器在空中,跌落到下面的平台上。如您所料,canJump为false:
java - Box2D碰撞检测失败-LMLPHP

玩家跌落并降落,并调用平台一的beginContact。将canJump设置为true。同样,这是我们所期望的:
java - Box2D碰撞检测失败-LMLPHP

现在,玩家向右移动,直到他们与第二平台接触。具有平台2的beginContact被调用。同样,canJump设置为true。
java - Box2D碰撞检测失败-LMLPHP

这就是问题所在。在最后一步,玩家仍与平台一保持联系。但是现在它们还不是,所以调用平台1的endContactcanJump现在设置为false。这解释了您得到的意外行为。
java - Box2D碰撞检测失败-LMLPHP

解决方案非常简单。您需要维护播放器底部正在接触的联系人列表。在此iforce2d文章中,有一个指南可以准确地做到这一点:http://www.iforce2d.net/b2dtut/jumpability

祝好运!

10-01 18:46