libGDX Box2D: Wie zerstören Körper nach dem Stoß?
Vielen Dank für Ihre Zeit.
Erstelle ich ein Pong-Klon mit Box2D über libGDX. Wenn Sie versuchen, löschen Sie den Ball-Körper als Ergebnis des Ball-Körper-Kontakt mit einer der beiden Ziel-Sensor-Körper (Bild unten), ich habe ein Knackpunkt, dass die Ergebnisse in eine Null-Zeiger-Ausnahme.
Möchte ich hinzufügen, dass die Kontaktaufnahme mit dem Ball Körper zu einer Liste, so dass ich später die Liste Durchlaufen, um zu löschen den Ball (Körper und Ball mehrere stellen in der Zukunft).
Den 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 meinem GameScreen-Klasse ist die Linie world.destroyBody(circleBody);
befindet sich innerhalb der if(scoredGoal1 == true){stuff}
bedingte Anweisung des public void render(float delta){stuff}
Methode unten dargestellt.
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*/
}
}
});
Meine Logik ist wie folgt auf den Kontakt zwischen einer Kugel-Körper und einen Ziel-Sensor-Körper:
- Innerhalb der ContactListener ist beginContact () - Methode, die Ball-Körper-Kontaktaufnahme mit dem EdgeShape Sensor-Körper Hinzugefügt werden, um die
ArrayList<Body> ballDeletionList = new ArrayList<Body>();
und diescoredGoal1 = true;
boolean-flag wird auf true gesetzt werden. - In der
render();
check fürscoredGoal1 = true
oderscoredGoal2 = true
dann löschen Sie die geltenden Body/Körper nach derworld.step()
Methode.
Gesucht hab ich in anderen code-Beispiele und tutorials im web nur, um Antworten zu finden, die mehrdeutig sind, weil entweder das war der code für den Fall spezielle oder ich verstehe nur Java, zumindest im moment.
Wäre es toll, wenn ein Java/libGDX-code-Beispiel-Lösung veröffentlicht werden.
InformationsquelleAutor HACKQ3R | 2013-08-05
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie nicht löschen Einrichtungen in Ihrem contactlistener, weil in Ihrer Welt Schritt, und die Welt ist gesperrt.
Ich habe genau die gleichen Sie versuchen zu tun, in deine render-Methode einfach:
Auch mit libgdx empfohlen wird die Verwendung von Array http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/utils/Array.html statt ArrayList, es entsteht weniger Müll und macht einige weitere Optimierungen.
InformationsquelleAutor Lestat