Having a level editor is a good start, but it’s not all. We need some kind of workflow to create models and textures and eventually get these to show up in the game. I started with the models.
Since I know my way around Blender and it’s free, I decided to use it for the in-game models. Because the game is shown in a top-down view, most small objects can be represented by flat sprites. Larger objects will still be pretty simple: a shopping cart, some shelves, walls, maybe some angular people.
Above is the model I created for the shopping cart. It has some solid areas that will be made mostly transparent by using alpha-blended textures. Note how I removed the bottom of the handle: because the game world is always shown from the top, nobody will ever see the underside anyway.
Blender can export to many different formats, the simplest and most universal being OBJ. It’s a plain-text format that looks something like this:
v 0.232701 0.403051 0.835455 v -0.000000 0.000000 0.506366 v -0.465403 0.000000 0.835455 ... vt 0.250000 0.500000 vt 0.500000 0.500000 vt 0.250001 0.750000 ... vn 0.408249 0.707107 0.577350 vn -0.816496 -0.000000 0.577351 vn -0.408249 -0.707107 -0.577350 ... f 5/1/1 1/2/1 8/3/1 f 1/2/1 4/4/1 8/3/1 f 3/5/2 7/6/2 8/7/2 ...
v are vertices,
vt are texture coordinates,
vn are normals, and
f are faces. There are some more directives, but these are the essential ones.
We don’t want to parse all this stuff on the Android side, so it seemed like a good idea to convert it to some binary form. Ideally, the binary data can directly be loaded into a vertex buffer in OpenGL. For this, I came up with the BOB (Binary OBj) file format, and wrote a program called
bobc to parse an OBJ file and compile it to the BOB format. The format is trivially simple: a 32-bit value indicating the number of vertices, followed by the vertex data, texture data, and normal data. This data is stored in OpenGL ES fixed-point format: 16 bits before the decimal point, 16 bits after it.
Here’s how it looks in the game:
I haven’t converted the cart model yet, but that little cube is no longer hard-coded: it’s loaded from a file called