JBox2d. Step function crashes when destroying a body

Hi every one!

I’m starting with JBox2d, with the help of the book Nature of Code, by Daniel Shiffman.

Currently I´m making a sketch where boxes appear on the screen when you click the mouse an they just fall. The thing is, it never stop calculating the position of the boxex wich are outside the screen. So, I intruduces a function (killBox) in order to destroy the body object so the calculation will stop… in the future I will get it remove from the Array list too.

The real problem is; when it have to destroy de body object de proces call box2d.step() crash, somthing called “AssertionError”.

Any suggestion?

import shiffman.box2d.*;
import org.jbox2d.collision.shapes.*;
import org.jbox2d.common.*;
import org.jbox2d.dynamics.*;

Box2DProcessing box2d;

ArrayList<Box> boxes;

void setup() {
  size(800, 800);

  boxes = new ArrayList<Box>();

  box2d = new Box2DProcessing(this);
  box2d.createWorld();
}

void draw() {
  background(0);
  
  //here, in this function (box2d.step()) is were the error happen
  box2d.step();

  if (mousePressed) {
    Box p = new Box(mouseX, mouseY);
    boxes.add(p);
    
  }

  for (Box b : boxes) {
    b.display();
    b.killBox();
  }
}

//Here starts the code for the Box class which is refered above

class Box {

  float w;
  float h;

  Body body;
  BodyDef bd= new BodyDef();

  Box(float x, float y) {

    w = random(5, 16);
    h = random(5, 16);


    bd.type = BodyType.DYNAMIC;
    bd.position.set(box2d.coordPixelsToWorld(x, y));
    body = box2d.createBody(bd);

    PolygonShape ps= new PolygonShape();

    float box2dW= box2d.scalarPixelsToWorld(w/2);
    float box2dH= box2d.scalarPixelsToWorld(h/2);

    ps.setAsBox(box2dW, box2dH);

    FixtureDef fd = new FixtureDef();
    fd.shape = ps;
    fd.density = 1;
    fd.friction = 0.3;
    fd.restitution = 0.5;

    body.createFixture(fd);
  }

  void display() {

    Vec2 pos=box2d.getBodyPixelCoord(body);
    float a = body.getAngle();

    noFill();
    strokeWeight(1);
    stroke(255);
    rectMode(CENTER);

    pushMatrix();
    translate(pos.x, pos.y);
    rotate(-a);
    rect(0, 0, w, h);
    popMatrix();
  }
  
  
  //here is de killing function
  void killBox() {
    
    //we ask for the position of the body 
    Vec2 pos=box2d.getBodyPixelCoord(body);
    
    //if the position of the body is 100 pixels outside the screen we call box2d to kill it
    if (pos.y > (height+100)) {
      box2d.destroyBody(body);
    }
  }
}

Not a native english user, sorry for any mistake I could have comited. Also First post… yay!

Hi every one!

I solved my own proble.

Aparently, you can not kill the body in the loop draw(), you have to do it inside de class definition. But not like, having a function inside de class definition (killBody()) that invoque the funcion destroyBody(body), more like de function that will be in charge of killing the body (killBody()) should ve invoque inside another function.

I will share the solution! yay!

import shiffman.box2d.*;
import org.jbox2d.collision.shapes.*;
import org.jbox2d.common.*;
import org.jbox2d.dynamics.*;


Box2DProcessing box2d;
ArrayList<Box> boxes;



void setup() {
  size(800, 800);

  boxes=new ArrayList<Box>();

  box2d = new Box2DProcessing(this);
  box2d.createWorld();
  box2d.setGravity(0,-20);

}


void draw() {
  background(0);

  if (mousePressed) {
    Box p = new Box(mouseX, mouseY);
    boxes.add(p);
  }
  box2d.step();

  for (int i = boxes.size()-1; i>=0; i--) {
    Box b = boxes.get(i);
    b.display();
  }

  for (int i = boxes.size()-1; i>=0; i--) {
    Box b = boxes.get(i);
    if (b.killBox()) {
      boxes.remove(i);
    }
  }
}


//Here come the Box class!!
class Box {

  float w;
  float h;

  Body body;

  Box(float x, float y) {

    w = 16;
    h = 16;

    makeBody(x, y, w, h);
  }
//See! we have our kilBody() function who is in charge of killing the body objects in the box2dworld
  void killBody() {
    box2d.destroyBody(body);
  }

//And here we set a boolean function that will tell us if the body is inside the screen, 
//and is in this funtion were we kill the body, the boolean value that return is used to delet the object from the ArrayList too.
  boolean killBox() {
    Vec2 pos = box2d.getBodyPixelCoord(body);

    if (pos.y > height+100) {
      killBody();
      return true;
    } 
    return false;
  }

  void display() {

    Vec2 pos=box2d.getBodyPixelCoord(body);
    float a = body.getAngle();

    noFill();
    strokeWeight(1);
    stroke(255);
    rectMode(CENTER);

    pushMatrix();
    translate(pos.x, pos.y);
    rotate(-a);
    rect(0, 0, w, h);
    popMatrix();
  }

  void makeBody(float x, float y, float w, float h) {
    
    BodyDef bd= new BodyDef();
    bd.type = BodyType.DYNAMIC;
    bd.position = (box2d.coordPixelsToWorld(x, y));
    body = box2d.createBody(bd);

    PolygonShape ps= new PolygonShape();
    float box2dW= box2d.scalarPixelsToWorld(w/2);
    float box2dH= box2d.scalarPixelsToWorld(h/2);
    ps.setAsBox(box2dW, box2dH);

    FixtureDef fd = new FixtureDef();
    fd.shape = ps;
    fd.density = 1;
    fd.friction=0.3;
    fd.restitution=0.5;

    body.createFixture(fd);
  }
}

If anyone could give an explanation of why this should be written in this specific way, rhater than how I did it first time; in order to understand which are the reassons behind this beheaviour and make sure I’m not just copying something blindly…I would much appreciate it.

1 Like