I'm working on my first smartphone game, a simple 2D platformer built with libgdx. Game maps use the Tiled level format, so a map is just a bunch of blocks. I recently started using box2d to implement character collision and movement.
So this is probably naive, but what I did is for a level consisting of 64x50 (= 3200) blocks, I added a static body for every block to represent the physics for this geometry. I set these blocks to sleep, which I thought would be a hint for box2d to disregard these blocks when stepping the simulation unless they're actually interacting with the player (the only dynamic body), so this shouldn't hinder performance very much? I recall reading in the box2d manual that it employs a spatial algorithm to only even look at the bodies relevant to render the current frame.
Yet having these 3500 sleeping static bodies degrades performance to such a degree that even when running the game on my MacBook Pro 2012 in a Genymotion emulator, I get about 5 FPS.
I suppose I'm doing something terribly wrong. My questions would be:
- when dealing with bodies in the thousands, am I supposed to remove/add box2d bodies for my level geometry dynamically to improve performance, e.g. based on a fixed box around the player? that sounds painful and I'm wondering why the library wouldn't be able to figure out itself
- maybe I've just made a mistake mapping map tiles to box2d bodies? I've posted my setup code below
Any help appreciated.
Here's how I attach the static bodies to the level geometry; it just walks the map and creates a static body for every block:
private void addB2Bodies(World b2World) {
for (int row = 0; row < blocksLayer.getHeight(); row++) {
for (int col = 0; col < blocksLayer.getWidth(); col++) {
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.StaticBody;
bodyDef.awake = false;
bodyDef.position.set(col + 0.5F, row + 0.5F);
final PolygonShape shape = new PolygonShape();
shape.setAsBox(0.5F, 0.5F);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.friction = 0;
final Body body = b2World.createBody(bodyDef);
body.createFixture(fixtureDef);
blocks[col][row] = body;
}
}
}
I only have one dynamic body, the player. As for the simulation, I step it at 1 / 60, with the default/recommended iteration counts of 6 and 2.