In Part 2 of this series, we look at the Body component for AGE.
The primary purpose for this GO is to handle the box2d bookkeeping for Body instances, map that information to its drawable resources, and provide an abstract base class for more complicated objects.
public abstract class Box2DBody extends DrawableGameObject {
protected Body body;
protected BodyDef bd;
protected boolean passive;
public int filterFlags;
public Box2DBody(String name, Geometry model, int depth) {
super(name, true, model, depth);
set(Constants.Property.TRANSFORM, new Transform());
}
protected abstract void configureBodyDef(BodyDef bd);
protected abstract void configureBody(Body bd);
public boolean isPassive() { return passive; }
public void setPassive(boolean passive) { this.passive = passive; }
public boolean isBody(Body bd) { return bd == body; }
public float getInertia() { return body == null ? 0f : body.getInertia(); }
The sync method handles setting up the Transform property with the current values computed by the World update (see Part 1).
public void sync() {
if (body != null) {
final Vec2 wc = body.getWorldCenter();
final Transform tx = getAs(Constants.Property.TRANSFORM);
tx.tx = wc.x;
tx.ty = wc.y;
tx.rz = (float) Math.toDegrees(body.getAngle());
set(Constants.Property.TRANSFORM, tx);
}
}
The unload method handles the bookkeeping associated with removing an object from box2d. The bodymap is a parameter, because it is possible that a GO can have composite geometry in box2d.
The World calls this method during its BoundaryListener.violated method. The World does not call this during UnloadCallback because it is possible to recycle these GOs.
public void unload(Box2DWorld world, HashMap<Body, Box2DBody> bodymap) {
final Body prev = this.body;
if (prev != null) {
prev.setUserData(null);
world.destroyBody(prev);
body = null;
bodymap.remove(prev);
}
}
The reload method handles re-initializing box2d resources for the GO. This requires less work than initial loading, since BodyDefs were already set up.
public void reload(Box2DWorld world, HashMap<Body, Box2DBody> bodymap) {
final Body prev = this.body;
if(prev != null) {
prev.setUserData(null);
world.destroyBody(prev);
this.body = null;
bodymap.remove(prev);
}
final Body bx = world.createBody(bd);
if (bx != null) {
// createBody() can fail!
configureBody(bx);
bx.setUserData(this);
bodymap.put(bx, this);
}
this.body = bx;
}
The load method handles the initial loading of box2d resources.
The World calls this method during its LoadedCallback.
public void load(Box2DWorld world, HashMap<Body, Box2DBody> bodymap) {
bd = new BodyDef();
configureBodyDef(bd);
final Body bx = world.createBody(bd);
if(bx != null) {
// createBody() can fail!
configureBody(bx);
bx.setUserData(this);
bodymap.put(bx, this);
}
this.body = bx;
}
}