[英]libGDX Box2D: How to destroy body after collision?
Thanks for your time.谢谢你的时间。
I am creating a Pong clone using Box2D via libGDX.我正在通过 libGDX 使用 Box2D 创建 Pong 克隆。 When trying to delete the Ball body as a result of the Ball body contacting with one of the two Goal Sensor Bodies (image below), I am having a sticking point that results in a Null Pointer Exception.当由于球体与两个目标传感器体之一接触而尝试删除球体时(下图),我遇到了一个导致 Null 指针异常的粘滞点。
I want to add the contacting Ball body to a list so that I can later iterate through the list to delete the Ball body (and multiple Ball bodies in the future).我想将接触球体添加到列表中,以便以后可以遍历列表以删除球体(以及将来的多个球体)。
The stack trace:堆栈跟踪:
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)
Line 484 in my GameScreen class is the line world.destroyBody(circleBody);
我的 GameScreen class 中的第 484 行是world.destroyBody(circleBody);
that resides within the if(scoredGoal1 == true){stuff}
conditional statement of the the public void render(float delta){stuff}
method shown below.它位于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*/
}
}
});
My logic is as follows on contact between a Ball body and a Goal Sensor body:关于球体和目标传感器体之间的接触,我的逻辑如下:
ArrayList<Body> ballDeletionList = new ArrayList<Body>();
在 ContactListener 的 beginContact() 方法中,与 EdgeShape 传感器主体接触的球体将被添加到ArrayList<Body> ballDeletionList = new ArrayList<Body>();
and the scoredGoal1 = true;
并且scoredGoal1 = true;
boolean flag will be set to true. boolean 标志将设置为真。render();
在render();
check for scoredGoal1 = true
or scoredGoal2 = true
then delete the applicable Body/Bodies after the world.step()
method.检查scoredGoal1 = true
或scoredGoal2 = true
然后在world.step()
方法之后删除适用的 Body/Body。I have searched other code examples and tutorials throughout the web only to find answers that are ambiguous because either the code was case specialized or I only understand Java at the moment.我在整个 web 中搜索了其他代码示例和教程,只是为了找到模棱两可的答案,因为代码是特殊的,或者我目前只了解 Java。
It would be great if a Java/libGDX code example solution could be posted.如果可以发布 Java/libGDX 代码示例解决方案,那就太好了。
You can't delete bodies in your contactlistener because that is inside your world step, and world is locked. 您无法删除联系人侦听器中的实体,因为它位于世界步骤中,并且世界已锁定。 I did exactly the same you are trying to do, in your render method just: 在您的render方法中,我所做的与您尝试做的完全相同:
if(ballDeletionList.size>0) ballDeletionList.clear();
Also, using libgdx it is recommended to use Array http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/utils/Array.html instead of ArrayList, it generates less garbage and makes some more optimizations. 另外,使用libgdx时,建议使用Array http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/utils/Array.html而不是ArrayList,这样可以减少垃圾并进行更多优化。
Please, do you have any simple example on how to destroy a body?请问,你有任何关于如何摧毁尸体的简单例子吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.