2017-07-08 105 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(); 
    } 
}