2017-07-08 1 views
0

libgdxを使用して2Dのサイドスクロールプラットフォームゲームを開発中です。主な問題は、明らかに必要なときにbeginContact(Contact contact)が呼び出されないということです。ここでは簡単な概要を与えるためにいくつかの単純化されたコードスニペットは、次のとおりです。センサーと地面との間のすべての連絡先を記録しますLibgdx box2d ContactListenerは非常にglitchyです

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ログをコンソール日食最後に、自己説明写真:

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(); 
    } 
} 
関連する問題