Monthly Archives: June 2010

Simple Java Tip: Checked Type Casting

This is quite a trivial trick but it is very useful at times and I do not remember seeing it in any of the game related code sample I have read so far, so here it is.
Sometimes you get an object from somewhere and you know what type it should be and what to do if it’s not of that type (and by the way, if this is a common occurrence in your code it may be a hint that you should review your OO design). The usual java idiom to handle the situation is something like this:

if (o instanceof Something) {
s = (Something) o;
} else {
s = null;
}

Simple enough but if you have to do it a lot becomes kind of annoying. Here is a solution:

public class Cast {
public static T as(Class type, Object o) {
if (type.isInstance(o))
return type.cast(o);
return null;
}
}


And you can now write:

Something s = Cast.as(Something.class, o);
if(s != null) {
...
}

Bonus: if you’re getting objects from a heterogeneous map, create a simple delegating map wrapper that adds a casting get operation. I use this fairly frequently in my game code where entities have heterogeneous maps to hold their properties.

public class CastingMap implements Map {
private final Map m;

public CastingMap(Map m) {
this.m = m;
}

public T get(Class type, K key) {
return Cast.as(type, get(key));
}
...

Mapping Box2D shapes from textures

Pretty soon after getting started with Box2D and having a ball bouncing on the screen the novelty wears off, playing with circles and boxes is not much fun. I wanted more complex shapes and it turns out that creating polygons by hand is boring and error prone and so is approximating a shape from primitives. I needed something that would trace an image and create a  polygon out of it, at run-time if possible. This lead to searching the internets high and low but I could not find anything other that other people asking for the same thing I was looking for.

Eventually I found a piece of code from the Farseer project (a 2d physics engine written in C#) that did exactly what I needed except, well, it was written in C#. The code was contributed by a user going by the alias Sickbattery, he is not listed as a project developer and there is nothing else about him but he deserves the credit for the original C# code.

An hour later I finished translating the C# source to Java, the code is not pretty and exhibits a bit of foreign language accent but it works  pretty well. I will not list the code here, scroll to the end of the article to download it.

There are few static functions that can be called, all of them returning a list of Vec2 vertices almost ready to be used to create Box2D polygons. Another hour and a hard to find post on the Box2D forums later and I finally got the thing working, here are the relevant bits of code.

ImageSprite shape = new ImageSprite("Shape.png", 0, 0);
//get the list of vertices approximating the image
List verts = TextureConverter.createPolygon(shape.getImage().getData(), shape.width.getAsInt(),
shape.height.getAsInt());
//scale the vertices to the world's scale
for (Vec2 v : verts) {
v.mulLocal(1 / scale);
}
//create a polygon from all these vertices
Polygon poly = new Polygon(verts.toArray(new Vec2[] {}));
Polygon tracedPoly = Polygon.traceEdge(poly);
BodyDef bd = new BodyDef();
bd.position.set(x, y);
Body body = world.createBody(bd);
//create a prototype polygon definition that will be used for the characteristics of all shapes
PolygonDef proto = new PolygonDef();
proto.friction = 0.2f;
proto.restitution = 0.8f;
proto.density = 2f;
//decompose the polygon in convex pieces and add them to the body
Polygon.decomposeConvexAndAddTo(tracedPoly, body, proto);
body.setMassFromShapes();

The sample uses the JBox2dD debug drawing classes from a previous post, so you can see the shapes that were generated. Press ‘D’ to toggle debug drawing, press ‘R’ to restart, click to add another shape.

Download the source code, PulpCore and JBox2D not included.

Debugging JBox2d with PulpCore

JBox2D is pretty easy to use until it isn’t, so when that happens it is quite helpful to get some details on what is going on in the physics world. The Box2D manual is somewhat cryptic and so is the JBox2D port, there is a DebugDraw class as promised in the docs but not much of a hint on how to use it. Luckily there is source code and it “explains” things well enough.

Scroll all the way to the end of this post to find out how things turned out or keep reading to see how I got there.

First step is indeed extending the org.jbox2d.dynamics.DebugDraw class and implementing its drawing methods, note that I will using the java.awt.Graphics2D instead of PulpCore’s CoreGraphics class, mostly because I did not wanted to implement circle drawing (Yes, I know it is simple enough, but why bother?)

public class PulpCoreDebugDraw extends DebugDraw {
private Graphics2D g;
private final float scale;

public PulpCoreDebugDraw(int width, int height, float scale) {
super(new OBBViewportTransform());
this.scale = scale;
viewportTransform.setCamera(width / 2 / scale, height / 2 / scale, scale);
viewportTransform.setExtents(width / 2, height / 2);
}

public void setGraphics(Graphics2D g) {
this.g = g;
}

@Override
public void drawCircle(Vec2 center, float radius, Color3f color) {
Color oldColor = g.getColor();
g.setColor(new Color(color.x / 255, color.y / 255, color.z / 255));
Vec2 v = new Vec2(center.x - radius, center.y - radius);
viewportTransform.getWorldToScreen(v, v);
int r = (int) (radius * scale);
g.drawArc((int) v.x, (int) v.y, 2 * r, 2 * r, 0, 360);
g.setColor(oldColor);
}

Now wrap the PulpCoreDebugDraw into a Sprite so that it can be added to Scene2D. The Java2DSprite class can be found in the contrib directory of the PulpCore distribution.

public class JBox2DDebugSprite extends Java2DSprite {
private final World world;
private PulpCoreDebugDraw debugDraw;

public JBox2DDebugSprite(World world, int x, int y, int w, int h, float scale) {
super(x, y, w, h);
this.world = world;
debugDraw = new PulpCoreDebugDraw(w, h, scale);
world.setDebugDraw(debugDraw);
}

@Override
protected void draw(Graphics2D g) {
debugDraw.setGraphics(g);
world.drawDebugData();
}

@Override
protected boolean needsRedraw() {
return true;
}
}

All the is left is adding the JBox2DDebugSprite to your scene and telling the JBox2D World to use it. The debug flags are explained in the DebugDraw source code.

world.setDrawDebugData(true);
add(new JBox2DDebugSprite(world, 0, 0, Stage.getWidth(), Stage.getHeight(), WORLD_TO_STAGE_SCALE));
world.getDebugDraw().setFlags(
DebugDraw.e_shapeBit | DebugDraw.e_coreShapeBit | DebugDraw.e_jointBit | DebugDraw.e_controllerBit);

Download the source code, PulpCore and JBox2D not included.