简体   繁体   中英

CRASH: com.badlogic.gdx.physics.box2d.World.jniCreateBody

I get a EXCEPTION_ACCESS_VIOLATION crash from the java runtime enviroment when trying out my game. It is written with LibGdx (and uses box2d). It is running on desktop mode from android studio.

I added a "fireball" function to my supermario game, and get this error when jumping into air and shooting fireballs. Here is the crash log:

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code) j com.badlogic.gdx.physics.box2d.World.jniCreateBody(JIFFFFFFFFZZZZZF)J+0 j com.badlogic.gdx.physics.box2d.World.createBody(Lcom/badlogic/gdx/physics/box2d/BodyDef;)Lcom/badlogic/gdx/physics/box2d/Body;+80 j com.mygdx.game.sprite.Fireball.define()V+68 j com.mygdx.game.sprite.Fireball.(Lcom/mygdx/game/screen/PlayScreen;FFZ)V+135 j com.mygdx.game.sprite.Mario.shootFire()V+36 J 1115 C1 com.mygdx.game.screen.PlayScreen.handleInput(F)V (221 bytes) @ 0x000000000320f90c [0x000000000320e960+0xfac] J 1073 C1 com.mygdx.game.screen.PlayScreen.update(F)V (188 bytes) @ 0x00000000031e14ec [0x00000000031e1440+0xac] J 1074 C1 com.mygdx.game.screen.PlayScreen.render(F)V (252 bytes) @ 0x00000000031e493c [0x00000000031e3f20+0xa1c] J 1223 C1 com.mygdx.game.MarioBros.render()V (5 bytes) @ 0x0000000003263ae4 [0x0000000003263920+0x1c4] j com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop()V+698 j com.badlogic.gdx.backends.lwjgl.LwjglApplic ation$1.run()V+27 v ~StubRoutines::call_stub

Here is my Fireball class:

public class Fireball extends Sprite {

private PlayScreen playScreen;
private World world;
private Array<TextureRegion> frames;
private Animation<TextureRegion> animation;
private float stateTimer;
private boolean destroyed;
private boolean destroy;
private boolean fireToRight;
private Body body;

public Fireball(PlayScreen playScreen, float x, float y, boolean fireToRight){
    this.playScreen = playScreen;
    this.fireToRight = fireToRight;
    this.world = playScreen.getWorld();
    destroy = false;
    destroyed = false;
    frames = new Array<TextureRegion>();
    for(int i = 0; i < 4; i++)
        frames.add(new TextureRegion(playScreen.getAtlas().findRegion("fireball"),i*8,0,8,8));
    animation = new Animation<TextureRegion>(0.2f, frames);
    setRegion(animation.getKeyFrame(0));
    setBounds(x, y, 6/ C.PIXEL_PER_METER, 6/C.PIXEL_PER_METER);
    define();
}

private void define(){
    BodyDef bodyDef = new BodyDef();
    bodyDef.position.set(fireToRight ? getX() + 12 /C.PIXEL_PER_METER : getX() - 12 /C.PIXEL_PER_METER, getY());
    bodyDef.type = BodyDef.BodyType.DynamicBody;
    if(world.isLocked())
        return;
    body = world.createBody(bodyDef);
    FixtureDef fixtureDef = new FixtureDef();
    CircleShape shape = new CircleShape();
    shape.setRadius(3 / C.PIXEL_PER_METER);
    fixtureDef.filter.categoryBits = C.FIREBALL_BIT;
    fixtureDef.filter.maskBits = C.GROUND_BIT |
            C.COIN_BIT |
            C.BRICK_BIT |
            C.ENEMY_BIT |
            C.OBJECT_BIT;
    fixtureDef.shape = shape;
    fixtureDef.restitution = 1;
    fixtureDef.friction = 0;
    body.createFixture(fixtureDef).setUserData(this);
    body.setLinearVelocity(new Vector2(fireToRight ? 2 : -2, 2.5f));
}

public void update(float deltaTime){
    if((stateTimer > 3 || destroy) && !destroyed){
        world.destroyBody(body);
        destroyed = true;
        body = null;
        return;
    }

    stateTimer += deltaTime;
    setRegion(animation.getKeyFrame(stateTimer, true));
    setPosition(body.getPosition().x - getWidth()/2, body.getPosition().y - getHeight()/2);

    if(body.getLinearVelocity().y > 2f)
        body.setLinearVelocity(body.getLinearVelocity().x,2f);
    if((fireToRight && body.getLinearVelocity().x < 0 ) || (!fireToRight && body.getLinearVelocity().x > 0))
        destroy();
}

public void destroy(){
    destroy = true;
}

public boolean isDestroyed(){
    return destroyed;
}

}

I call mario.shootFire() from PlayScreen class.

This is how "mario shoots fireballs":

private Array<Fireball> fireballs;

fireballs = new Array<Fireball>();

 public void shootFire(){
        fireballs.add(new Fireball(playScreen, body.getPosition().x, body.getPosition().y, runRight));
    }

    @Override
    public void draw(Batch batch) {
        super.draw(batch);
        for (Fireball fireball: fireballs)
            fireball.draw(batch);
    }

Any ideas on why i get this error?

EDIT: It seems like it crashes at this line body = world.createBody(bodyDef) in define() method in Fireball.

com.badlogic.gdx.physics.box2d.World.jniCreateBody

You are trying to access memory that is no longer available. There are several tutorials about how to create and destroy bodies in box2d. You have to do it at the right time with regards to updating the physics world (step()).

Since you only get JNI debug info it is quite hard to know exactly where the bug is (been there many times) A good way to get a better exception is to set the body to null (right after world.destroyBody(body);)

world.destroyBody(body);
body = null;
destroyed = true;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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