简体   繁体   English

box2d碰撞无法按预期进行,libGDX And​​roid

[英]box2d collision doesn't work out as expected libGDX Android

public class WorldContactListener implements ContactListener {
    @Override
    public void beginContact(Contact contact) {
    //fixtures that participate in the collision
    Fixture fixA = contact.getFixtureA();
    Fixture fixB = contact.getFixtureB();

    //collision definition
    int cDef = fixA.getFilterData().categoryBits | fixB.getFilterData().categoryBits;

    //figure out what kind of the collision occures
    switch (cDef){
        //if the player jumps on the enemy
        case KuboGame.KUBO_BIT | KuboGame.ENEMY_HEAD_BIT:
            if(fixA.getFilterData().categoryBits == KuboGame.ENEMY_HEAD_BIT)
                ((Spider)fixA.getUserData()).hitOnHead();
            else ((Spider)fixB.getUserData()).hitOnHead();
            break;
        //if the character collides with the wall or the ground
        case KuboGame.ENEMY_BIT | KuboGame.DEFAULT_BIT:
            if(fixA.getFilterData().categoryBits == KuboGame.ENEMY_BIT)
                ((Enemy)fixA.getUserData()).reverseVelocity(true, false);
            else ((Enemy)fixB.getUserData()).reverseVelocity(true, false);
            break;
        //enemy collides with another enemy
        case KuboGame.ENEMY_BIT | KuboGame.ENEMY_BIT:
            ((Enemy)fixA.getUserData()).reverseVelocity(true, false);
            ((Enemy)fixB.getUserData()).reverseVelocity(true, false);
        break;
        //player collides with an enemy
        case KuboGame.KUBO_BIT | KuboGame.ENEMY_BIT:
            if(fixA.getFilterData().categoryBits == KuboGame.KUBO_BIT) {
                ((Kubo)fixA.getUserData()).hit();
                ((Enemy)fixB.getUserData()).reverseVelocity(true, false);
                } else{
                ((Kubo)fixA.getUserData()).hit();
                ((Enemy)fixA.getUserData()).reverseVelocity(true, false);
                }
            break;
        //player collides with an item
        case KuboGame.KUBO_BIT | KuboGame.COINS_BIT:
           if(fixA.getFilterData().categoryBits == KuboGame.COINS_BIT) {
               ((Coin)fixA.getUserData()).use();
            } else ((Coin)fixB.getUserData()).use();
            break;
    }
}

@Override
public void endContact(Contact contact) {

}

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

}

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

}
}

So the deal is that the class above that corrsponds for the collision of objects throws an error every time when Kubo_BIT will jump at Enemy_BIT.When this objects collide on the horizontal plane, it would be completely fine. 因此,问题是,每次Kubo_BIT跳到Enemy_BIT时,对应于对象碰撞的上述类都会引发错误。当该对象在水平面上碰撞时,将完全可以。 Below is the PlayScreen which renders both objects 下面是渲染两个对象的PlayScreen

public class PlayScreen implements Screen {

private KuboGame game;
private TextureAtlas atlas;
private Hud hud;
private OrthographicCamera gamecam;
private Viewport gamePort;
//here added 3
private TmxMapLoader maploader;
private TiledMap map;
private OrthogonalTiledMapRenderer renderer;

private World world;
private Box2DDebugRenderer b2dr;
private B2WorldCreator creator;

private Kubo player;
private MapProperties prop;
private int[] data;

int mapWidth;
int mapHeight;
int tilePixelWidth;
int tilePixelHeight;


int mapPixelWidth;
int mapPixelHeight;



String mapName;


private Controller controller;

public PlayScreen(KuboGame game, String mapName, int[] prevData){
    atlas = new TextureAtlas("kuboRunSmaller.pack");
    this.game = game;
    this.mapName = mapName;
    this.data = prevData;
    gamecam = new OrthographicCamera();
    gamePort = new FitViewport(KuboGame.V_WIDTH / KuboGame.PPM, 
KuboGame.V_HEIGHT / KuboGame.PPM , gamecam);

    hud = new Hud(game.batch);
    hud.addScore(prevData[0]);
    hud.addLife(prevData[1]);
    hud.addLevel(prevData[2]);

    //added here 3
    maploader = new TmxMapLoader();
    //map = maploader.load("l1.tmx");
    map = maploader.load(mapName);

    prop = map.getProperties();

    mapWidth = prop.get("width", Integer.class);
    mapHeight = prop.get("height", Integer.class);
    tilePixelWidth = prop.get("tilewidth", Integer.class);
    tilePixelHeight = prop.get("tileheight", Integer.class);

    mapPixelWidth = mapWidth * tilePixelWidth;
    mapPixelHeight = mapHeight * tilePixelHeight;

    renderer = new OrthogonalTiledMapRenderer(map, 1 / KuboGame.PPM);
    gamecam.position.set(gamePort.getWorldWidth()/ 2, 
    gamePort.getWorldHeight()/ 2, 0);

    world = new World(new Vector2(0,-10), true); //bodies are at rest

    b2dr = new Box2DDebugRenderer();

    creator = new B2WorldCreator(this);
    player = new Kubo(this);
    controller = new Controller(game.batch);


    world.setContactListener(new WorldContactListener());

}

public TextureAtlas getAtlas(){
    return atlas;
}

@Override
public void show() {
   // world.setContactListener(new WorldContactListener());
}

public boolean gameOver(){
    if(player.currentState == Kubo.State.DEAD){
        return true;
    }else if(player.b2body.getPosition().y <= 0){
        return true;
    }
    return false;
}

public void levelComplete(){
    Gdx.app.log("GAME STATE", " LEVEL COMPLETE!");
    game.updateMaxScore(Hud.getScore());
    data[0] = hud.getScore();
    data[1] = hud.getLives();
    data[2] = hud.getLevel();
    game.setScreen(new LevelCompleteScreen(game, data));
    dispose();

}

public void handleInput(float dt){

    if(player.currentState != Kubo.State.DEAD) {
        if (Gdx.input.isKeyJustPressed(Input.Keys.UP))
            player.b2body.applyLinearImpulse(new Vector2(0, 2.6f), 
player.b2body.getWorldCenter(), true);
        if (Gdx.input.isKeyPressed(Input.Keys.RIGHT) && 
player.b2body.getLinearVelocity().x <= 2)
            player.b2body.applyLinearImpulse(new Vector2(0.1f, 0), 
player.b2body.getWorldCenter(), true);
        if (Gdx.input.isKeyPressed(Input.Keys.LEFT) && 
player.b2body.getLinearVelocity().x >= -2)
            player.b2body.applyLinearImpulse(new Vector2(-0.1f, 0), 
player.b2body.getWorldCenter(), true);

    }

    if(player.currentState != Kubo.State.DEAD){
        if(controller.isUpPressed() && player.b2body.getLinearVelocity().y 
== 0)
            player.b2body.applyLinearImpulse(new Vector2(0, 2.6f), 
player.b2body.getWorldCenter(), true); //was 0.4
        if(controller.isRightPressed() && 
player.b2body.getLinearVelocity().x <= 2)
            player.b2body.applyLinearImpulse(new Vector2(0.1f, 0), 
player.b2body.getWorldCenter(), true);
        if(controller.isLeftPressed() && player.b2body.getLinearVelocity().x 
>= -2)
            player.b2body.applyLinearImpulse(new Vector2(-0.1f, 0), 
player.b2body.getWorldCenter(), true);

    }

}

public void update(float dt){


    handleInput(dt);

    world.step(1/80f, 6, 2);

    player.update(dt);
    hud.update(dt);


    for(Enemy enemy :creator.getSpiders()) {
        enemy.update(dt);
        if(enemy.getX() < player.getX() + 180/ KuboGame.PPM)
            enemy.b2body.setActive(true);
    }

    for(Item item :creator.getCoins()){
        item.update(dt);


    }

    if(player.currentState != Kubo.State.DEAD) {
        if (player.b2body.getPosition().x >= KuboGame.V_WIDTH / 2 / 
KuboGame.PPM &&
                (mapPixelWidth/ KuboGame.PPM - 
player.b2body.getPosition().x)>= KuboGame.V_WIDTH / 2 / KuboGame.PPM )  {
            gamecam.position.x = player.b2body.getPosition().x;
        }else if(player.b2body.getPosition().x < 0.1){
            player.b2body.setAwake(false);
        }else if(mapPixelWidth/ KuboGame.PPM - player.b2body.getPosition().x 
<= 0.1)
        {levelComplete();}

    }
    gamecam.update();

    renderer.setView(gamecam);
}

public TiledMap getMap(){
    return map;
}

public World getWorld(){
    return world;
}
@Override
public void render(float delta) {


    update(delta);
    Gdx.gl.glClearColor(0,0,0,1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    renderer.render();

    //Next statement draws box2Dbodies to the screen
    //b2dr.render(world, gamecam.combined);
    game.batch.setProjectionMatrix(gamecam.combined);
    game.batch.begin();
    player.draw(game.batch);

   //draw all spiders
    for(Enemy enemy :creator.getSpiders())
        enemy.draw(game.batch);
    //draw all coins
    for(Item item :creator.getCoins())
        item.draw(game.batch);

    game.batch.end();

    game.batch.setProjectionMatrix(hud.stage.getCamera().combined);
    hud.stage.draw();

    controller.draw();

    if(gameOver()){
        game.updateMaxScore(Hud.getScore());
        game.setScreen(new GameOverScreen(game, mapName));
        dispose();
    }
}

@Override
public void resize(int width, int height) {

    gamePort.update(width, height);
    controller.resize(width,height);
}

@Override
public void pause() {

}

@Override
public void resume() {

}

@Override
public void hide() {

}

@Override
public void dispose() {
    map.dispose();
    renderer.dispose();
    world.dispose();
    b2dr.dispose();
    hud.dispose();
}
}

And HERE is the error log for Android Studio: 这里是Android Studio的错误日志:

05-02 16:16:37.485 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: JNI 
CallVoidMethodV called with pending exception 'java.lang.ClassCastException' 
thrown in unknown throw location
05-02 16:16:37.486 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]     in call to CallVoidMethodV
05-02 16:16:37.486 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]     from void 
com.badlogic.gdx.physics.box2d.World.jniStep(long, float, int, int)
05-02 16:16:37.486 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65] "GLThread 239" prio=5 tid=13 Runnable
05-02 16:16:37.486 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]   | group="main" sCount=0 dsCount=0 
obj=0x12c22640 self=0xb4033800
05-02 16:16:37.486 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]   | sysTid=8656 nice=0 cgrp=default sched=0/0 
handle=0xb4054a00
05-02 16:16:37.486 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]   | state=R schedstat=( 0 0 0 ) utm=1460 
stm=1139 core=1 HZ=100
05-02 16:16:37.486 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]   | stack=0xa4da6000-0xa4da8000 
stackSize=1036KB
05-02 16:16:37.486 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]   | held mutexes= "mutator lock"(shared held)
05-02 16:16:37.486 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]   native: #00 pc 00005d03  
/system/lib/libbacktrace_libc++.so (UnwindCurrent::Unwind(unsigned int, 
ucontext*)+83)
at com.badlogic.gdx.physics.box2d.World.jniStep(Native method)
05-02 16:16:37.487 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]   at 
com.badlogic.gdx.physics.box2d.World.step(World.java:689)
05-02 16:16:37.487 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]   at 
com.ana7tasys.kubo.Screens.PlayScreen.update(PlayScreen.java:188)
05-02 16:16:37.487 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]   at 
com.ana7tasys.kubo.Screens.PlayScreen.render(PlayScreen.java:232)
05-02 16:16:37.487 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]   at com.badlogic.gdx.Game.render(Game.java:46)
05-02 16:16:37.487 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]   at 
com.ana7tasys.kubo.KuboGame.render(KuboGame.java:50)
05-02 16:16:37.487 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]   at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:459)

05-02 16:16:37.487 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]   at 
android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1522)
05-02 16:16:37.487 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65]   at 
android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1239)
05-02 16:16:37.487 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/check_jni.cc:65] 
05-02 16:16:37.551 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/runtime.cc:289] Runtime aborting...
05-02 16:16:37.551 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/runtime.cc:289] Aborting thread:
05-02 16:16:37.551 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/runtime.cc:289] "GLThread 239" prio=5 tid=13 Native
05-02 16:16:37.551 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/runtime.cc:289]   | group="" sCount=0 dsCount=0 obj=0x12c22640 
self=0xb4033800
05-02 16:16:37.551 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/runtime.cc:289]   | sysTid=8656 nice=0 cgrp=default sched=0/0 
handle=0xb4054a00
05-02 16:16:37.551 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/runtime.cc:289]   | state=R schedstat=( 0 0 0 ) utm=1460 
stm=1139 
core=1 HZ=100
05-02 16:16:37.551 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/runtime.cc:289]   | stack=0xa4da6000-0xa4da8000 stackSize=1036KB
05-02 16:16:37.551 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/runtime.cc:289]   | held mutexes= "abort lock" "mutator lock"
(shared held)
05-02 16:16:37.551 8627-8656/com.ana7tasys.kubo A/art: 
art/runtime/runtime.cc:289]   native: #00 pc 00005d03  
/system/lib/libbacktrace_libc++.so (UnwindCurrent::Unwind(unsigned int, 
ucontext*)+83)

In your code you are casting the fixA userdata to both enemy and kubo. 在您的代码中,您正在将fixA用户数据投向敌人和久保。 You need to change it so one is fixA and the other is fixB. 您需要更改它,所以一个是fixA,另一个是fixB。

    case KuboGame.KUBO_BIT | KuboGame.ENEMY_BIT:
        if(fixA.getFilterData().categoryBits == KuboGame.KUBO_BIT) {
            ((Kubo)fixA.getUserData()).hit();
            ((Enemy)fixB.getUserData()).reverseVelocity(true, false);
            } else{
            ((Kubo)fixB.getUserData()).hit(); // here
            ((Enemy)fixA.getUserData()).reverseVelocity(true, false);
            }
        break;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM