Tuesday, July 31, 2012

Tutorial 11 - Physics 101

   Webcomic Courtesy of Ethanol & Entropy

11.1 Dropping Things

We are constantly amazed by the capability of Codea. An example of this is the integration of the Box2D physics engine. The talented folks at Two Lives Left have made incorporating physics into your App absurdly easy.

The included Physics Lab example project provides a good overview of the techniques available. However, if you are starting out, sometimes it isn't obvious how you can integrate similar functionality into your program. This tutorial will show you which bits you need to include in your project and how you can attach a sprite to a physics object.

11.2 The Setup

In our Minesweeper game we wanted to add a bit of bling to the Menu screen. To this end we thought about dropping some mines from the top of the screen. Initially we had them bouncing off the ground but this didn't seem like a sensible thing to do with a mine so we removed the ground. We have left the code for the ground in the example below in case you need it. In your Main class, we start off by reading the sprite image into the img variable. You want to do this in setup() to ensure you only read the sprite into memory once, doing it in draw() can cause your App to crash due to running out of memory.
The next step is to create an instance of the PhysicsDebugDraw() class which we copied from the Physics Lab example project (and modified a bit). We will cover this class in section 11.4 below.
We then assign the sprite image we read to the associated spriteImage parameter in PhysicsDebugDraw() and set staticVisible to false. The only static physics object we create is the ground so setting this to false means that the ground will be invisible (but there nonetheless).
Finally we create the physics objects, the ground (createGround), a box (createBox), a circle (createCircle) and a random sized polygon (createRandPoly). The interesting one is the circle which we will attach our sprite to. Note that the radius of the circle is the same size (32 pixels) as half the width of the sprite (64 pixels). To make this more general you could use img.width/2 in place of the 32 (assuming your sprite looks roughly circular).

11.3 Physics Functions

We have also extracted the following physic object creation functions from the Physics Lab example project:
  • createCircle(x,y,r)
  • createBox(x,y,w,h)
  • createGround() - note you could change the dimensions of this by altering the physics.body polygon.
  • createRandPoly(x,y) - creates a random polygon at screen co-ordinates (x,y) with between 3 and 10 sides
  • cleanup() - will delete all of the physic objects that you added to the PhysicsDebugDraw rendering class. In Minesweeper we call this after creating 50 objects to ensure that we don't run out of memory. Remember that if you call this you will need to re-create any physics objects that you want to model.

11.4 The Engine Room - PhysicsDebugDraw Class

This class renders the physics objects that you have added to it. We have made two minor modifications to the class. We added the staticVisible flag to allow you to choose whether your static objects were visible or not. Note that static bodies don't collide with other static bodies and are immovable, so they are usually used to represent the ground. 

The other thing we added was the spriteImage parameter. If this is not nil then we draw the sprite image instead of a circle. And that's all there is to it. In future tutorials we will examine some of the other capabilities enabled by the physics engine.