删除正文box2d

时间:2015-03-02 10:58:07

标签: java libgdx box2d jbox2d

有人能告诉我为什么这会返回错误

'AL lib:(EE)alc_cleanup:1个设备未关闭'

// mouseJoint碰撞回调

private QueryCallback queryCallback = new QueryCallback() {

    @Override
    public boolean reportFixture(Fixture fixture) {


        if(fixture.getBody() == chest){

            //add to remove list

            bodiesToRemove.add(chest);

        }

        if (fixture.testPoint(tmp.x, tmp.y)){


            reportFixture = fixture.getBody();
        }


        if (!fixture.testPoint(tmp.x, tmp.y))
            return false;

        //assigning bodyB to fixture 
        jointDef.bodyB = fixture.getBody();
        jointDef.target.set(fixture.getBody().getWorldCenter());

        //jointDef.target.set(tmp.x, tmp.y);// initial target point coincide with body anchor

        joint = (MouseJoint) world.createJoint(jointDef);// creating the join the physics world
        return false;
    }

};

//主渲染循环

public void render(float delta) {
    // TODO Auto-generated method stub
       //code clears the screen with the given RGB colour (black)
    Gdx.gl.glClearColor( 0f, 0f, 0f, 1f );
    Gdx.gl.glClear( GL20.GL_COLOR_BUFFER_BIT );


     stage.setCamera(camera);               
     stage.act(Gdx.graphics.getDeltaTime());




    camera.position.x= chest.getPosition().x;


    camera.update();

     stage.draw();



    world.step(1 / 60f, 8, 3);
    renderer.render(world, camera.combined);


/////////////////////////////////////////////////////////////////   

//这是我尝试删除正文时导致错误的代码

    if(bodiesToRemove != null){

    for(int i = 0; i <bodiesToRemove.size; i++){

        Body b = bodiesToRemove.get(i);

        if(b != null){
           world.destroyBody(b);
           b.setUserData(null);
           b = null;
        }
        bodiesToRemove.clear();
    }
    }

    ////////////////////////////////////////////////////////////
}

/////////////////////////////////////////////// ///////////////////////////// 如果有人想解释正确的方法,或者这是正确的方法,我已经改变了这个并且它的工作(粘贴在下面)。 我刚刚添加了一个布尔值来防止它破坏关节

// ////////////////// TOUCH EVENT ///////////////////////////////
//Called when a finger was lifted or a mouse button was released.
@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
    //If no mouseJoint do nothing

    System.out.println("touch" + (screenY*0.01f));
    System.out.println("touch" + (screenX*0.01f));



    if (joint == null)
        return false;


    //When user is not touching Screen destroy the
    //mouseJoint/set to null
    if(ran == false){

    world.destroyJoint(joint);
    joint = null;}


    ran = false;
    return true;
}



////////////////////////////////

/////////////////////////////////

    if(!world.isLocked() && world.getBodyCount() > 0 ){

        for(int i = 0; i <bodiesToRemove.size; i++){

            Body b = bodiesToRemove.get(i);

            if(b == null){
                bodiesToRemove.removeIndex(i);
                continue;
            }
            world.destroyBody(b);
            ran = true;
            bodiesToRemove.removeIndex(i);

        }

        }else{

            bodiesToRemove.clear();
        }

    ////////////////////////////////////////////////////////////

1 个答案:

答案 0 :(得分:2)

Box2D抛出一些奇怪的错误,这不是其中之一。

我假设您正在使用LibGDX,基本上发生的事情是由于Box2D导致的崩溃(我还假设它弹出说&#34; java或其他任何已停止响应&#34;),您看到的这个错误被抛出当应用程序退出而OpenAL正在关闭流并清理资源时。不要太担心这件事。

确保在销毁尸体前检查世界是否被锁定,它通常会抛出错误并打印出一条明确的消息,告诉您这一点,具体取决于您移除尸体的方式。

if(!world.isLocked())
    // do clean up code here

您不需要清理本地范围内的变量,或者清除正文中的用户数据,因为它将不再存在于引用中(除非您将其存储在其他位置)。

所以正确的代码是这样的:

if(!world.isLocked()){
    for(int i = bodiesToRemove.size - 1; i--){
        Body b = bodiesToRemove.get(i);
        if(b == null){
            bodiesToRemove.removeAt(i);
            continue;
        }
        world.destroyBody(b);
        bodiesToRemove.removeAt(i);
    }
}

您也在迭代期间清除列表,这不是一个好主意。

修改

我能想到的另一件事就是导致这个问题是试图删除一个实际上不在世界正文列表中的正文。

尝试以下方法:

// Ensure world is not locked AND that there is even bodies in the world
if(!world.isLocked() && world.getBodyCount() > 0){
    for(int i = bodiesToRemove.size - 1; i--){
        Body b = bodiesToRemove.get(i);
        if(b == null){
            bodiesToRemove.removeAt(i);
            continue;
        }
        world.destroyBody(b);
        bodiesToRemove.removeAt(i);
    }
}else{
    // There is no bodies in the world, so the bodies in our list are just
    // random memory hogs, leave them for the GC by clearing the list
    bodiesToRemove.clear();
}

修改

如OP所述,问题在于这段代码:

private QueryCallback queryCallback = new QueryCallback(){

@Override
public boolean reportFixture(Fixture fixture) {
    if(fixture.getBody() == chest){
        //add to remove list
        bodiesToRemove.add(chest);
    }
    if (fixture.testPoint(tmp.x, tmp.y)){
        reportFixture = fixture.getBody();
    }
    if (!fixture.testPoint(tmp.x, tmp.y))
        return false;
    //assigning bodyB to fixture 
    jointDef.bodyB = fixture.getBody();
    jointDef.target.set(fixture.getBody().getWorldCenter());
    //jointDef.target.set(tmp.x, tmp.y);
    joint = (MouseJoint) world.createJoint(jointDef);
    return false;
}

};

更具体地说,这一行:

    joint = (MouseJoint) world.createJoint(jointDef);

在世界步骤中触发查询回调。 在Box2D中,您无法在世界步骤中创建或销毁实体,固定装置和关节。

你必须在这个方法之外创建它,最简单的方法是通过一个标志。将标志设置为true并将夹具的实例存储在某处并使用所述标记和夹具在游戏循环中处理它。