1
\$\begingroup\$

I am making a clone for the BreakOut game. I'm using Box2D and Libgdx for it. In the game, one scenario is that there could be 2-3 balls at one time. Now the problem occurs when 2 or more balls collide with the same object at the same instant. I'm simulating this by creating 2 balls overlapping each other and having velocities in both directions same, so they move like one body. When they collide I get this error : AL lib: alc_cleanup: 1 device not closed. I searched a little and modified my code by putting the condition if (!world.isLocked()). Now it just gets stuck and I have to end the process using task manager. Here is my code inside collision listener :

if (contact.getFixtureA().getUserData() instanceof Ball) {

        Ball ballTemp = (Ball) contact.getFixtureA().getUserData();

        if (contact.getFixtureB().getUserData() instanceof Brick) {
            brickTemp = (Brick) contact.getFixtureB().getUserData();

            if (brickTemp.getPower() != null)
                brickTemp.getPower().update();

            if (ballTemp.getX() > brickTemp.getPosition().x
                    + brickTemp.getWidth()) { // collision on the right
                ballTemp.goRight();
            }
            if (ballTemp.getX() < brickTemp.getPosition().x
                    - brickTemp.getWidth()) { // collision on the left
                ballTemp.goLeft();
            }
            if (ballTemp.getY() > brickTemp.getPosition().y
                    + brickTemp.getHeight()) { // collision on the top
                ballTemp.goUp();
            }
            if (ballTemp.getY() < brickTemp.getPosition().y
                    + brickTemp.getHeight()) { // collision on the
                                                // bottom
                ballTemp.goDown();
            }
            bodiesToDestroy.add(contact.getFixtureB());
        }
    }

I have another if statement where fixtureB is Ball and fixtureA is Brick with similar code. And the part in MainScreen.java where I'm doing the cleaning up job is :

world.step(TIMESTEP, VELOCITYITERATIONS, POSITIONITERATIONS);

    if (!world.isLocked()) {
        destroy(MyContactListener.bodiesToDestroy);

        if (MyContactListener.removeBall != null) {
            balls.removeValue(MyContactListener.removeBall, true);
        }

        if (MyContactListener.power) {
            MyContactListener.powerBrick.applyPower(delta);
            powerStartTime = System.nanoTime();
        }           

    }
    public void destroy(Array<Fixture> bodiesToDestroy) {
    Array<Fixture> temp = new Array<Fixture>();
    for (Fixture bodyToDestroy : bodiesToDestroy) {
        if (bodyToDestroy.getBody() != null) {
            world.destroyBody(bodyToDestroy.getBody());
            temp.add(bodyToDestroy);
        }
    }
    MyContactListener.bodiesToDestroy.removeAll(temp, true);
    temp = null;
}

applyPower method just creates two new instances to Ball class with the same co-ordinates and velocities. bodiesToDestroy is defined as public static Array<Fixture> bodiesToDestroy = new Array<Fixture>();

It's unlikely that two balls collide with the same object just at the same instant, but nonetheless I have to take care of such an occurrence. Please suggest how this should be handled.

\$\endgroup\$
  • \$\begingroup\$ AL lib: alc_cleanup: 1 device not closed is something LibGDX seems to spit out nearly every time it exits. Does it kill your application when you run it without the isLocked guard? \$\endgroup\$ – ThorinII Jan 30 '14 at 22:46
  • \$\begingroup\$ Yes it kills the application when isLocked condition is removed. \$\endgroup\$ – Kartik Aysola Jan 31 '14 at 2:40
  • \$\begingroup\$ Ok the AL lib bit is just a side effect of the crash. Are there any exceptions? \$\endgroup\$ – ThorinII Jan 31 '14 at 3:10
  • \$\begingroup\$ No there are no exceptions. I put a try-catch block but it did not catch any exception or error. It just crashed and gave the above message along with "The crash happened outside the Java Virtual Machine in native code." Not sure what it means. \$\endgroup\$ – Kartik Aysola Jan 31 '14 at 4:42
  • \$\begingroup\$ So your JVM is really crashing (native code crash). You need to step through it in a debugger to find out where it's crashing. It's hard to know otherwise. \$\endgroup\$ – ThorinII Jan 31 '14 at 5:04
2
\$\begingroup\$

Ok, I found what was the problem. I was adding things to bodiestoDestroy without checking if they were already added. So they were being added twice since two collisions were taking place at once. When deleting from the Array, it removes the first instance while the second instance is still there pointing to something that is destroyed. Hence the problem.

\$\endgroup\$
1
\$\begingroup\$

Are you getting a ConcurrentModificationException? The Javadoc for LibGDX Array does not say it uses fail-fast iterators (then again it doesn't say it doesn't).

You are removing items from your array, while iterating over it. With regular Java collections this will cause an error.

Deleting the items once you've iterated over all of them might help:

for (Fixture bodyToDestroy : MyContactListener.bodiesToDestroy) {
    destroy(bodyToDestroy);
}
MyContactListener.clear();

...

public void destroy(Fixture fixtureToBeDestroyed) {
    if (fixtureToBeDestroyed != null
            && fixtureToBeDestroyed.getBody() != null) {
        world.destroyBody(fixtureToBeDestroyed.getBody());
    }
}
\$\endgroup\$
  • \$\begingroup\$ No, I do not get any such exception. Anyways I did change my code to accomodate the suggestion you gave. (Edited the original post). Still the error remains. \$\endgroup\$ – Kartik Aysola Jan 31 '14 at 5:05
  • \$\begingroup\$ But I noticed that the crash happens not necessarily at the instant of collision, but after a few seconds of creation of the two additional balls(joined). I wonder if this is because the two new balls are overlapping always and as they both are dynamic(sensors) bodies, box2D/application is unable to take the load. \$\endgroup\$ – Kartik Aysola Jan 31 '14 at 5:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.