Android libGDX-Box2D:碰撞后如何销毁尸体?

Android libGDX-Box2D:碰撞后如何销毁尸体?,android,box2d,libgdx,physics,game-physics,Android,Box2d,Libgdx,Physics,Game Physics,谢谢你抽出时间 我正在通过libGDX使用Box2D创建一个Pong克隆。当由于球体与两个目标传感器体(下图)中的一个接触而试图删除球体时,我遇到了一个导致空指针异常的粘滞点 我想将接触球体添加到列表中,以便以后可以在列表中迭代以删除球体(以及将来的多个球体) 堆栈跟踪: Exception in thread "LWJGL Application" java.lang.NullPointerException at com.badlogic.gdx.physics.box2d.World.d

谢谢你抽出时间

我正在通过libGDX使用Box2D创建一个Pong克隆。当由于球体与两个目标传感器体(下图)中的一个接触而试图删除球体时,我遇到了一个导致空指针异常的粘滞点

我想将接触球体添加到列表中,以便以后可以在列表中迭代以删除球体(以及将来的多个球体)

堆栈跟踪:

Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.badlogic.gdx.physics.box2d.World.destroyBody(World.java:311)
at com.ckq3r.Ponger.screens.GameScreen.update(GameScreen.java:484)
at com.ckq3r.Ponger.screens.GameScreen.render(GameScreen.java:114)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.ckq3r.Ponger.PongerGame.render(PongerGame.java:236)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:204)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:112)
我的GameScreen类中的第484行是行
world.destroyBody(circleBody)位于如下所示的
public void render(float delta){stuff}
方法的
if(scoredGoal1==true){stuff}
条件语句中

public class GameScreen implements Screen, InputProcessor{

/*----methods and variables omitted for readability------*/

private boolean scoredGoal1 = false, scoredGoal2 = false;
ArrayList<Body> ballDeletionList = new ArrayList<Body>();

/*==============Screen implementation methods============*/
    @Override
    public void show(){
        /*ball*/
        BodyDef circleDef = new BodyDef();      
        Body circleBody = world.createBody(circleDef);
        circleBody.setUserData(1);              
        CircleShape circleShape = new CircleShape();                
        FixtureDef circleFixture = new FixtureDef();
        circleFixture.shape = circleShape;              
        circleBody.createFixture(circleFixture);        
        circleShape.dispose();
    }

    @Override
    public void render(float delta) {           
        world.step(Gdx.app.getGraphics().getDeltaTime(), 8, 3);
        Gdx.gl.glClearColor(0, 0, 0, 1); 
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        camera.update();
        debugRenderer.render(world, camera.combined);

        /*-------ball deletion experiment-------*/          
        if(scoredGoal1 == true){

            //iterate through ballDeletionList somehow?

            world.destroyBody(circleBody);                            
            circleBody.setUserData(null);
            circleBody = null;                              
            scoredGoal1 = false;
            //clear ballDeletionList

        }else if(scoredGoal2 == true){

            //iterate through ballDeletionList somehow?

            world.destroyBody(circleBody);
            circleBody.setUserData(null);
            circleBody = null;              
            scoredGoal2 = false;
            //clear ballDeletionList
        }
        /*-----end ball deletion experiment------*/
}   

/*===========Box2D contact listener=============*/
    private void createContactListener() {
        world.setContactListener(new ContactListener() {

        @Override
        public void beginContact(Contact contact) {
            Fixture fixtureA = contact.getFixtureA();
            Fixture fixtureB = contact.getFixtureB();
            Gdx.app.log("beginContact", "between " + fixtureA.toString() + " and " + fixtureB.toString());

            if(fixtureA.getBody().getUserData().equals(1) && fixtureB.getBody().getUserData().equals(2) || fixtureA.getBody().getUserData().equals(2) && fixtureB.getBody().getUserData().equals(1)){
                Gdx.app.log("HIT", "goal1 contact");

                /*ball deletion experiment*/
                ballDeletionList.add(circleBody);
                Gdx.app.log("Ball", "circleBody added to deletion list");
                scoredGoal1 = true;
                /*ball deletion experiment*/
            }         

            if(fixtureA.getBody().getUserData().equals(1) && fixtureB.getBody().getUserData().equals(3) || fixtureA.getBody().getUserData().equals(3) && fixtureB.getBody().getUserData().equals(1)){
                Gdx.app.log("HIT", "goal2 contact");

                /*ball deletion experiment*/
                ballDeletionList.add(circleBody);
                Gdx.app.log("Ball", "circleBody added to deletion list");
                scoredGoal2 = true;
                /*ball deletion experiment*/
            }
        }                

        });
公共类GameScreen实现屏幕、输入处理器{
/*----为了可读性,省略了方法和变量------*/
私有布尔值scoredGoal1=false,scoredGoal2=false;
ArrayList ballDeletionList=新建ArrayList();
/*================屏幕实现方法============*/
@凌驾
公开展览({
/*球*/
BodyDef circleDef=新的BodyDef();
Body circleBody=world.createBody(circleDef);
circleBody.setUserData(1);
CircleShape CircleShape=新的CircleShape();
FixtureDef circleFixture=新的FixtureDef();
circleFixture.shape=圆形;
circleBody.createFixture(circleFixture);
圆形。dispose();
}
@凌驾
公共无效渲染(浮动增量){
步骤(Gdx.app.getGraphics().getDeltaTime(),8,3);
glClearColor(0,0,0,1);
Gdx.gl.glClear(GL10.gl\u颜色\u缓冲\u位);
camera.update();
debugRenderer.render(世界、摄影机、组合);
/*-------球删除实验------*/
if(scoredGoal1==true){
//以某种方式遍历ballDeletionList?
世界。毁灭体(圆形体);
circleBody.setUserData(空);
圆圈体=空;
scoredGoal1=假;
//清除删除列表
}else if(scoredGoal2==true){
//以某种方式遍历ballDeletionList?
世界。毁灭体(圆形体);
circleBody.setUserData(空);
圆圈体=空;
scoredGoal2=false;
//清除删除列表
}
/*-----端球删除实验------*/
}   
/*=============Box2D联系人侦听器=============*/
私有void createContactListener(){
setContactListener(新的ContactListener(){
@凌驾
public void beginContact(联系人){
Fixture fixtureA=contact.getFixtureA();
Fixture fixtureB=contact.getFixtureB();
Gdx.app.log(“beginContact”,“介于”+fixtureA.toString()+”和“+fixtureB.toString()之间”);
如果(fixtureA.getBody().getUserData().equals(1)和&fixtureB.getBody().getUserData().equals(2)| | fixtureA.getBody().getUserData().equals(2)和&fixtureB.getBody().getUserData().equals(1)){
Gdx.app.log(“命中”,“目标接触”);
/*球删除实验*/
ballDeletionList.add(圆圈体);
Gdx.app.log(“添加到删除列表中的球”、“圆环体”);
scoredGoal1=真;
/*球删除实验*/
}         
如果(fixtureA.getBody().getUserData().equals(1)和&fixtureB.getBody().getUserData().equals(3)| | fixtureA.getBody().getUserData().equals(3)和&fixtureB.getBody().getUserData().equals(1)){
Gdx.app.log(“命中”,“目标2联系人”);
/*球删除实验*/
ballDeletionList.add(圆圈体);
Gdx.app.log(“添加到删除列表中的球”、“圆环体”);
scoredGoal2=真;
/*球删除实验*/
}
}                
});
我的逻辑如下:球体和目标传感器体之间的接触:

  • 在ContactListener的beginContact()方法中,与EdgeShape传感器体接触的球体将被添加到
    ArrayList ballDeletionList=new ArrayList();
    ,并且
    scoredGoal1=true;
    布尔标志将设置为true
  • render();
    中检查
    scoredGoal1=true
    scoredGoal2=true
    然后在
    world.step()方法之后删除适用的正文
  • 我在网上搜索了其他代码示例和教程,却发现答案模棱两可,因为要么代码是专门针对大小写的,要么我现在只懂Java


    如果可以发布Java/libGDX代码示例解决方案,那就太好了。

    您不能删除contactlistener中的主体,因为这在您的世界步骤中,并且世界被锁定。 我做了与您尝试做的完全相同的事情,在渲染方法中只是:

    if(ballDeletionList.size>0) ballDeletionList.clear();
    
    另外,使用libgdx时,建议使用Array而不是ArrayList,这样会产生更少的垃圾并进行更多的优化