Advertisement

Introduction to QuickBox2D: Part 1

by

This Cyber Monday Tuts+ courses will be reduced to just $3 (usually $15). Don't miss out.

This tutorial will teach you the basics of the QuickBox2D library. After reading through the following steps, you'll be able to create a wide variety of physics simulation effects. Over the course of this tutorial we'll create a few small demos to familiarize you with QuickBox2D's basic functionality.

Step 1: A Little Background

If you aren't already aware, Box2D is a great physics library created by Erin Catto.
It was ported to AS3 by Matthew Bush and John Nesky.

QuickBox2D is a mini-library I created to work with Box2DFlashAS3. The main purpose of this library is to significantly simplify instantiation of rigid bodies and provide a simple way to them bodies with custom graphics.

Step 2: Download the Libraries

In order to follow this tutorial you'll need Box2DFlashAS3 version 2.0.2. You can download it at sourceforge.net.

Be sure not to download 2.1a as it is still very much in an alpha state. Box2D 2.1 is still not out and the API is still undergoing
significant changes. When 2.1 is out of alpha, QuickBox2D will support it, but for the time being it will not work properly with QuickBox2D.

Next you need to download the latest version of QuickBox2D from actionsnippet.com.

This tutorial will function with QuickBox2D 1.1 or greater.

Step 3 : Set up the File

Open Flash and create a new ActionScript 3.0 file.

Save your file and make sure that Box2D and QuickBox2D are either in your classpath, or directly next to your fla file.

Step 4 : Create Your First Rigid Bodies

We'll be placing all our code on the first frame of the timeline, so open up your actions (option + F9) and paste the following code snippet:

[SWF(width = 800, height = 600, frameRate = 60)]

import com.actionsnippet.qbox.*;

var sim:QuickBox2D = new QuickBox2D(this);

sim.createStageWalls();

sim.addBox({x:3, y:3, width:1, height:1});
sim.addCircle({x:4, y:6, radius:1});

sim.start();
sim.mouseDrag()

Step 5 : Understanding the Code

Go ahead and test your movie (command + enter). You should end up with a box and a circle rigid body that you can drag and throw around the stage.

After importing the library, we instantiate an instance of QuickBox2D. We pass a reference to the timeline into the QuickBox2D constructor, this causes all rigid bodies to be drawn to the main timeline. You can pass any MovieClip into the QuickBox2D constructor. We store our QuickBox2D instance in a variable called sim (short for simulation).

Next we call the createStageWalls() method. This draws boxes around the edges of the stage so that rigid bodies don't fall off the screen.

On line 9 we create our first rigid body using the addBox() creation method. addBox() takes an Object
as its argument. This works like popular tweening engines, allowing you to enter a variable number of arguments in any order with easy to read syntax. In this case, we create a box with an x and y position of 3 meters and a width and height of 1 meter. Those values may seem strange, but I'll explain them shortly.

Next, we create a circle using the addCircle() method. This works pretty much the same way as the addBox() method. We use the params Object to tell QuickBox2D to position the circle at point (4,6) and we give the circle a radius of 1 meter.

To start the simulation we call start() and to allow dragging for the rigid bodies we call mouseDrag().

The only tricky part with this code snippet is the coordinate system. It's pretty obvious that our x and y values aren't in pixels. Box2D uses meters instead of pixels. This takes a little getting used to, but after an hour or two you'll have no trouble thinking in meters instead of pixels. It's important to note that 1 meter is 30 pixels. We'll see a little more about this later on when we get to skinning.

Step 6 : Adding Density

Let's make this a little more interesting. Replace your previous addBox() and addCircle() calls with these:

sim.addBox({x:4, y:3, width:1, height:1});
sim.addBox({x:3, y:6, width:4, height:0.25, density:0, angle:0.1});

sim.addCircle({x:3, y:10, radius:1});
sim.addCircle({x:8, y:10, radius:0.5});

Go ahead and test your movie. We're already familiar with x, y, width, height and radius, but we added two more params:
density and angle. Setting density to 0 causes Box2D to create a static rigid body. Static bodies don't
fall down or react to collisions with other rigid bodies. Setting density to other values controls how the mass of the rigid body is calculated. Try changing density to 100 and you'll notice that the rectangle becomes very heavy.

Setting angle changes the starting rotation value for a rigid body. This value is in radians instead of degrees. I prefer working directly in radians, but if you don't want to do that you can create a helper function to convert:

// takes a degree value and converts it to radians
function radians(degs:Number):Number{
	return degs * Math.PI / 180;
}

Step 7 : Take a Few Minutes to Create Something

At this point I highly recommend taking five or ten minutes to create something simple. You already have a enough knowledge to create some pretty nice simulations… If you create something interesting, be sure to save it.

Step 8 : Using What We've Learned

Now that you're beginning to get a feel for things, clear your timeline code and replace it with this:

[SWF(width = 800, height = 600, frameRate = 60)]
import com.actionsnippet.qbox.*;
var sim:QuickBox2D = new QuickBox2D(this);
sim.createStageWalls();
// make a heavy circle
sim.addCircle({x:3, y:3, radius:0.5, density:5});
// create a few platforms
sim.addBox({x:4, y:4, width:6, height:0.35, angle:0.1, density:0});
sim.addBox({x:9, y:6, width:6, height:0.35, angle:0.1, density:0});
sim.addBox({x:14, y:9, width:12, height:0.35, angle:-0.2, density:0});
sim.addBox({x:4, y:12, width:0.35, height:4, angle:-0.1, density:0});
sim.addBox({x:10, y:14, width:14, height:0.35, density:0});
// make 26 dominoes
for (var i:int = 0; i<13; i++){
 sim.addBox({x:7 + i * 0.8, y:13, width:0.25, height:1.6});
 sim.addBox({x:8 + i * 0.8, y:18.7, width:0.25, height:1.6})
}
sim.start();
sim.mouseDrag();

Go ahead and test your movie.

There's nothing new happening in this example. We're simply making use of x, y, width, height, radius and density.
These few params will take you pretty far. We're going to cover more params related to the behavior or rigid bodies in the second part of this tutorial, but if you feel like skipping ahead, a full list can be found in the QuickBox2D Docs.
The params for addBox() can be found here.

Step 9 : Grouping Rigid Bodies

Box2D allows you to create compound shapes. This means taking circles, boxes and polygons and grouping them together to make more complex shapes.
QuickBox2D vastly simplifies what you need to do to create compound shapes:

[SWF(width = 800, height = 600, frameRate = 60)]
import com.actionsnippet.qbox.*;
var sim:QuickBox2D = new QuickBox2D(this);
sim.createStageWalls();
// store references to each part of the group
var circleA:QuickObject = sim.addCircle({x:0, y:0, radius:0.5});
var circleB:QuickObject = sim.addCircle({x:2, y:0, radius:0.5});
var middleBox:QuickObject = sim.addBox({x:1, y:0, width:1.5, height:0.5});
// create the group using the addGroup() method
sim.addGroup({objects:[circleA, circleB, middleBox], x:6, y:6});
sim.start();
sim.mouseDrag();

Clear out your timeline code and replace it with what's above. Go ahead and test your movie.

All of the QuickBox2D creation methods (like addBox() and addCircle()) return QuickObject instances. QuickObjects are wrappers for the Box2D class instances that are necessary to create rigid bodies. When creating group objects, the first thing we need to do is store references to a few QuickObjects. We call these QuickObjects circleA, circleB and middleBox. Notice that x and y
coordinates for these are relative to (0,0) - this requirement is intended to simplify any positioning logic you need to do when placing the different parts of a group.

Now that we have our references, we can pass them as an array to the objects param of the addGroup() creation method. We then move the entire group to point (6,6).

Step 10 : A More Complex Group

With boxes and circles alone you can construct some pretty complicated group shapes. Clear out your timeline code and replace it with this:

[SWF(width = 800, height = 600, frameRate = 60)]
import com.actionsnippet.qbox.*;
var sim:QuickBox2D = new QuickBox2D(this);
sim.createStageWalls();
// create a circle
sim.addCircle({x:16, y:3, radius:1, density:0.2});
// create a bunch of boxes
var boxes:Array = [];
for (var i:int = 0; i<20; i++){
	var h:Number = 1 - i / 20;
	boxes.push(sim.addBox({x:i, y:i * h, width:1, height:h}));
}
// group all the boxes together
sim.addGroup({objects:boxes, x:3, y:3});
sim.start();
sim.mouseDrag();

Go ahead and test your movie.

Step 11 : Coloring Rigid Bodies and Using setDefault()

There are a few params that you can use to change the colors and render style of QuickObjects. These are fillColor, fillAlpha, lineColor, lineAlpha and lineThickness. They should be pretty self-explanatory. Take a look at this:

[SWF(width = 800, height = 600, frameRate = 60)]
import com.actionsnippet.qbox.*;
var sim:QuickBox2D = new QuickBox2D(this);
sim.createStageWalls();
sim.addCircle({x:3, y:3, radius:1,
			   fillColor:0xFF0000,
			   lineThickness:10,
			   lineColor:0xFFFF00});
sim.addCircle({x:6, y:3, radius:1,
			   fillColor:0xFF0000,
			   lineThickness:10,
			   lineColor:0xFFFF00});
sim.addCircle({x:9, y:3, radius:1,
			   fillColor:0x000022,
			   lineThickness:5,
			   lineColor:0x6666FF});
sim.addBox({x:12, y:4, width:2, height:2,
			   fillColor:0xFF0000,
			   lineThickness:10,
			   lineColor:0x00FF00});
sim.start();
sim.mouseDrag();

Try this out on your timeline.

While this is easy to understand, you can see how dealing with these params can quickly become cumbersome. In the next step we'll look at a way to get rid of some of this repetitive code.

Step 12 : The setDefault() Method

To get rid of repetitive looking code, QuickBox2D has a method called setDefault(). This method forces default values for all calls to creation methods. So you could simplify the previous example to look like this:

[SWF(width = 800, height = 600, frameRate = 60)]
import com.actionsnippet.qbox.*;
var sim:QuickBox2D = new QuickBox2D(this);
sim.createStageWalls();
sim.setDefault({fillColor:0xFF0000, lineThickness:10, lineColor:0xFFFF00});
sim.addCircle({x:3, y:3, radius:1});
sim.addCircle({x:6, y:3, radius:1});
sim.addCircle({x:9, y:3, radius:1,
			   fillColor:0x000022,
			   lineThickness:5,
			   lineColor:0x6666FF});
sim.addBox({x:12, y:4, width:2, height:2, lineColor:0x00FF00});
sim.start();
sim.mouseDrag();

Go ahead and try this out in your timeline.

The setDefault() method isn't limited to working with things like fillColor and lineThickness. It can be used in conjunction with any param. While I mostly find myself making use of setDefault() for render style and certain params related to joints, you could do something like this:

sim.setDefault({fillColor:0xFF0000, lineThickness:10,
			   lineColor:0xFFFF00, y:3, radius:1});
sim.addCircle({x:3});
sim.addCircle({x:6});
sim.addCircle({x:9,
		   fillColor:0x000022,
		   lineThickness:5,
		   lineColor:0x6666FF});

This could quickly get confusing, so be careful when deciding to use setDefault() in this way.

Step 13 : Skinning Rigid Bodies

One of the main features of QuickBox2D is easy skinning of rigid bodies. Because skinning generally requires use of library assets, you'll need to download this source file.

There are three MovieClips in the library, CircleFace, OddPizza and Mail. Each clip is exported for use with ActionScript. On the timeline you'll find the following code:

[SWF(width = 800, height = 600, frameRate = 60)]
import com.actionsnippet.qbox.*;
var sim:QuickBox2D = new QuickBox2D(this);
sim.createStageWalls();
sim.addCircle({x:3, y:3, radius: 45 / 30, skin:CircleFace, scaleSkin:false});
sim.addCircle({x:6, y:3, radius:1, skin:OddPizza});
sim.addCircle({x:6, y:6, radius:0.5, skin:OddPizza});
sim.addCircle({x:6, y:10, radius:2, skin:OddPizza});
sim.addBox({x:12, y:3, width:3, height: 50 / 30, skin:Mail});
sim.addBox({x:18, y:3, width:3, height: 3, skin:Mail});
sim.start();
sim.mouseDrag();

Go ahead and test the movie.

In order to create custom skins, we make use of the skin param. In this example, we set all of our skin params to linkage classes from our library. By default, QuickBox2D will create an instance of this class and attempt to scale it to fit the rigid body. This is useful for simple shapes like circles and boxes, but for more complex skins, you may want to turn this feature off using the scaleSkin param. We do this on line 8 so that the CircleFace skin is used properly.

You'll notice that for the radius we put 45 / 30 instead of 1.5. As mentioned earlier in this tutorial, 1 meter is 30 pixels, so to convert from pixels to meters we divide by 30. The circle in the CircleFace skin has a radius of 45 pixels so we've left the hard coded conversion in for clarity rather than writing 1.5.

Lines 10-12 create circles that make use of the OddPizza skin. The scaleSkin param is true by default, so each skin is automatically scaled
according to the radius param. Lines 14 and 15 create boxes that are skinned with the Mail clip.

Over the past few months, more skinning features have been added at the request of developers making use of QuickBox2D. I use the techniques described above exclusively, but if you're interested in seeing a few additional skinning techniques, have a look at this post on actionsnippet.

Step 14 : Further Reading

ActionSnippet QuickBox2D Posts - There are a whole bunch of QuickBox2D examples on actionsnippet.com in the form of posts. The earlier posts are significantly simpler than the newer ones. For that reason, I recommend going back a few pages and working your way up to some of the later posts. Nearly every aspect of QuickBox2D is covered in these examples.

QuickBox2D Docs - This is just the documentation for QuickBox2D. In some places it assumes basic Box2D knowledge.

Box2D Manual - An excellent resource that covers all aspects of Box2D. The C++
syntax might scare you away... but if you replace arrows like this -> with dot syntax and ignore asterisks *… you'll find that you understand a good deal.

Box2D Docs - Docs for all the C++ classes. I find this very useful for some of the techniques discussed in part 2 of this tutorial.

Step 15 : What Next?

We've covered a lot of ground and we've only really scratched the surface. Below are summaries of the upcoming QuickBox2D tutorials:

QuickBox2D Part 2

In the second part of this tutorial we will explore some of the more intermediate level features of QuickBox2D. We'll look at how to create polygon rigid bodies. We'll learn how to fine tune our simulation using additional param values such as restitution, linearDamping and angularDamping. We'll discuss some powerful Box2D methods that are exposed by QuickBox2D and we'll talk about FRIM (framerate independent motion).

QuickBox2D Part 3

In the third part of this tutorial we will cover some advanced techniques. We'll look at how QuickBox2D handles all of the different types of Box2D joints. We'll also go over contact points and special types of collisions.

I hope you enjoyed reading this first part!

Advertisement