Bull in a china shop – Behind the scenes in Android

DSC00032Here are the details about how I constructed the “Bull in a china shop” demo. For this demo I used Box2D physics engine and AndEngine to make the demo. I decided to use sprites for the china shop and picked up images of glasses, wine glasses, bottles etc from www.openclipart.org.

Be extremely careful when creating the TextureRegion using BitmapTextureAtlas. If you don’t get the co-ordinates right the display can be weird.

Here are 2 clips of Bull in a China Shop demo
1.Bull in a china shop in Moon’s gravity
2.Bull in a china shop in Earth’s gravity
The code for this can be cloned  from Github from Bulldozed

Here is a snippet of this

this.mBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 556, 246, TextureOptions.BILINEAR);
this.mTumblerTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "tumblr.png", 0, 0);
this.mBitmapTextureAtlas.load();
this.mBottleTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "bottle.png",20, 29);
this.mBitmapTextureAtlas.load();
this.mGlassTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "glass.png",36, 69);
this.mBitmapTextureAtlas.load();
this.mVaseTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "vase.png",56, 89);
this.mBitmapTextureAtlas.load();
...
...

This is very important to get right otherwise you are setting yourself for a lot of grief.

Superficially the demo looks real easy. It appears that creating a pyramid stack should be a breeze as long as you get the coordinates right. Wrong! Building a pyramid using Box2D with the effect of gravity can be a real challenge as I found out. I would build two stacks and the stack would become unstable and collapse.

Anyway here are the findings

  1. Each row is not placed directly over the object below. I leave a gap of 2 px between them The reason is the object below exerts a force ‘F’ upward. The object above exerts a force ‘mg” below and the physics engine tries to resolve this difference in forces and causes instability in the structure. So the key is a to leave a small gap in between
  2. Now that there is a gap between 2 rows the coefficient of restitution ‘e’ is made 0. Even a value as small as 0.1f can make the objects jitter and cause instability.
  3. The friction between the platform and the objects or the objects themselves is made maximum equal to 1.0f to prevent sliding of the objects.

// Add tumblers
for(int i=0; i < 21; i++) {
tumbler = new Sprite(80 + i * 25, 450, this.mTumblerTextureRegion, this.getVertexBufferObjectManager());
FIXTURE_DEF = PhysicsFactory.createFixtureDef(1f, 0.0f, 1f);
tumblerBody = PhysicsFactory.createBoxBody(this.mPhysicsWorld, tumbler, BodyType.DynamicBody, FIXTURE_DEF);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(tumbler, tumblerBody, true, true));
this.mScene.attachChild(tumbler);
}

// Add glasses
for(int i=0; i < 14; i++) {
glass = new Sprite(130 + i * 25, 428, this.mGlassTextureRegion, this.getVertexBufferObjectManager());
FIXTURE_DEF = PhysicsFactory.createFixtureDef(1f, 0.0f, 1f);
glassBody = PhysicsFactory.createBoxBody(this.mPhysicsWorld, glass, BodyType.DynamicBody, FIXTURE_DEF);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(glass, glassBody, true, true));
this.mScene.attachChild(glass);
...
...

Hopefully if you get everything right you should have a stable structure. I had to do this through trial and error before I got it finally right. Whew!

Once you get a stable structure with the proper sprites in place most of the problem is solved. For the last part I add a bull sprite and set it off at a velocity from the point of touch.

bull = new Sprite(pX, pY, this.mBullTextureRegion, this.getVertexBufferObjectManager());
FIXTURE_DEF = PhysicsFactory.createFixtureDef(25f, 0.0f, 1f);
Log.d("here","here");
bullBody = PhysicsFactory.createBoxBody(this.mPhysicsWorld, bull, BodyType.DynamicBody, FIXTURE_DEF);
if(pX > 360)
bullBody.setLinearVelocity(-5,-5);
else
bullBody.setLinearVelocity(5,5);

DSC00031

Note: Since the sprites are not regular shapes I had to use a box shape. So the collisions are not pixel perfect.
Make sure you set up your project properly in Eclipse. The important settings are
Project->Properties->Android->Android4.2
Project->Properties->Java Compiler: Check the “Enable project specific setting” and also set compiler compliance level to 1.6
Finally click Project->Properties->Android: Under Library click ‘Add’ and add AndEngine and AndEnginePhysicsBox2DExtension
and you are good to go.

Here are 2 clips of Bull in a China Shop demo

1.Bull in a china shop in Earth’s gravity

2.Bull in a china shop in Moon’s gravity

You can clone the project from Github from Bulldozed

Have fun …

Other cool simulations using AndEngine & Box2D
1. Simulating the domino effect using Box2D and AndEngine
2. The making of Total Control Android game
3. Simulating a Web Joint in Android
4. Modeling a Car in Android
5. A closer look at “Robot horse on a Trot! in Android”

Find me on Google+