2017-07-08 87 views
0

我遇到这种情况,同时使用libgdx开发我的小2D横向滚动平台游戏。主要问题是beginContact(Contact contact)在明确需要时未被调用。下面是一些简单的代码片段给出一个简要概述:Libgdx box2d ContactListener是非常糟糕的

ContactListener类记录传感器和地面之间的每次接触:

public class WorldContactListener implements ContactListener 
{ 
Player player; 

public WorldContactListener(Player player, World world) 
{ 
    this.player = player; 
    world.setContactListener(this); 
} 

@Override 
public void beginContact(Contact contact) 
{ 
    Object userDataA = contact.getFixtureA().getUserData(); 
    Object userDataB = contact.getFixtureB().getUserData(); 

    if((userDataA == Tomb.UserData.GROUND || userDataB == Tomb.UserData.GROUND) 
    && (userDataA == Tomb.UserData.PLAYER_FEET || userDataB == Tomb.UserData.PLAYER_FEET)) 
    { 
     Gdx.app.log("collision", "start"); 
    } 
} 

@Override 
public void endContact(Contact contact) 
{ 
    Object userDataA = contact.getFixtureA().getUserData(); 
    Object userDataB = contact.getFixtureB().getUserData(); 

    if((userDataA == Tomb.UserData.GROUND || userDataB == Tomb.UserData.GROUND) 
    && (userDataA == Tomb.UserData.PLAYER_FEET || userDataB == Tomb.UserData.PLAYER_FEET)) 
    { 
     Gdx.app.log("collision", "stop"); 
    } 
} 

@Override 
public void preSolve(Contact contact, Manifold oldManifold) 
{ 
} 

@Override 
public void postSolve(Contact contact, ContactImpulse impulse) 
{ 
} 
} 

球员创造:

//Main rectangle: 
    BodyDef bodyDef = new BodyDef(); 
    bodyDef.position.set(spawnCoordinates); 
    bodyDef.type = BodyType.DynamicBody; 
    body = world.createBody(bodyDef); 
    FixtureDef fixtureDef = new FixtureDef(); 
    PolygonShape shape = new PolygonShape(); 
    shape.setAsBox(5/Tomb.PPM, 14/Tomb.PPM); 
    fixtureDef.shape = shape; 
    fixtureDef.friction = FRICTION; //1 
    fixtureDef.restitution = RESTITUTION; //0 
    body.createFixture(fixtureDef).setUserData(Tomb.UserData.PLAYER); 

    //Circle-shaped sensor: 
    fixtureDef = new FixtureDef(); 
    CircleShape feet = new CircleShape(); 
    feet.setPosition(new Vector2(0, -16/Tomb.PPM)); 
    feet.setRadius(10/Tomb.PPM); 
    fixtureDef.shape = feet; 
    fixtureDef.isSensor = true; 
    body.createFixture(fixtureDef).setUserData(Tomb.UserData.PLAYER_FEET); 

球员动作:

private void handleInput(float delta) 
{ 
    if(Gdx.input.isKeyJustPressed(Input.Keys.UP)) 
    { 
     body.applyLinearImpulse(new Vector2(0, JUMP_POWER), body.getWorldCenter(), true); 
    } 
    if(Gdx.input.isKeyPressed(Input.Keys.RIGHT) && body.getLinearVelocity().x <= MAX_HORIZONTAL_VELOCITY) 
    { 
     body.applyLinearImpulse(new Vector2(HORIZONTAL_SPEED, 0), body.getWorldCenter(), true); 
    } 
    if(Gdx.input.isKeyPressed(Input.Keys.LEFT) && body.getLinearVelocity().x >= -MAX_HORIZONTAL_VELOCITY) 
    { 
     body.applyLinearImpulse(new Vector2(-HORIZONTAL_SPEED, 0), body.getWorldCenter(), true); 
    } 
} 

从Ti导入的.tmx映射的初始化领导地图编辑器。值得注意的是整个地形是一个单独的PolygonMapObject,所以在这种情况下,for循环是不需要的。

protected void defineGround(int layerIndex) 
{ 
    for(PolygonMapObject object : map.getLayers().get(layerIndex).getObjects().getByType(PolygonMapObject.class)) 
    { 
     BodyDef bodyDef = new BodyDef(); 
     ChainShape chainShape = new ChainShape(); 
     FixtureDef fixtureDef = new FixtureDef(); 
     Body body; 

     Polygon polygon = object.getPolygon(); 
     bodyDef.type = BodyType.StaticBody; 
     bodyDef.position.set(polygon.getX()/Tomb.PPM, polygon.getY()/Tomb.PPM); 
     body = world.createBody(bodyDef); 
     float[] scaledVertices = new float[polygon.getVertices().length]; 
     for(int i = 0; i < polygon.getVertices().length; i++) 
     { 
      scaledVertices[i] = polygon.getVertices()[i]/Tomb.PPM; 
     } 
     chainShape.createChain(scaledVertices); 
     fixtureDef.shape = chainShape; 
     body.createFixture(fixtureDef).setUserData(Tomb.UserData.GROUND); 
    } 
} 

最后,自我解释图片,显示游戏画面本身与WorldContactListener日志Eclipse控制台:

enter image description here enter image description here

enter image description here

同样的事情发生抢时(或绝对不平的表面):

enter image description here enter image description here

我已经尝试了所有可能的传感器的形状和尺寸的变化,所以这种行为不是由CircleShape的大小引起的。可能是什么情况?或者不涉及ContactListener的任何解决方法?

回答

0

这笔交易是在那里发生多次碰撞。在你的最后一张图片上,你可以看到玩家和多边形之间仍然存在(2-1 + 2-1)= 2的碰撞。

这里是我的示例解决方案: 使用函数incCollision()和decCollision()创建一些碰撞计数器类,也许一些bool isCollison()会告诉你实际是否有碰撞。

编辑您的ContactListener类:

public void beginContact(Contact contact) 
{ 
... 
    if((userDataA == Tomb.UserData.GROUND || userDataB == Tomb.UserData.GROUND) 
     && (userDataA == Tomb.UserData.PLAYER_FEET || userDataB == Tomb.UserData.PLAYER_FEET)) 
     { 
      Gdx.app.log("collision", "start"); 
      counter.incCollision(); 
     } 
} 

public void endContact(Contact contact) 
{ 
... 
if((userDataA == Tomb.UserData.GROUND || userDataB == Tomb.UserData.GROUND) 
    && (userDataA == Tomb.UserData.PLAYER_FEET || userDataB == Tomb.UserData.PLAYER_FEET)) 
    { 
     Gdx.app.log("collision", "stop"); 
     counter.decCollision(); 
    } 
}