Chapter 1. Hello Box2D World
If you want to create 2D physics-driven games and applications, Box2D is the best choice available. Box2D
is a 2D rigid body simulation library used in some of the most successful games, such as Angry Birds and Tiny Wings on iPhone or Totem Destroyer and Red Remover on Flash. Google them, and you'll see a lot of enthusiastic reviews.
Before we dive into the Box2D World, let me explain what is a rigid body
. It's a piece of matter that is so strong that it can't be bent in any way. There is no way to modify its shape, no matter how hard you hit it or throw it. In the real world, you can think about something as hard as a diamond, or even more. Matter coming from outer space that can't be deformed.
Box2D only manages rigid bodies, which will be called just "bodies" from now on, but don't worry, you will also be able to simulate stuff which normally is not rigid, such as bouncing balls.
Let's see what you are about to learn in this chapter:
Downloading and installing Box2D for Flash
Including required classes in your Flash projects
Creating your first Box2D World
Understanding gravity and sleeping bodies
Running your first empty simulation, handling time steps, and constraints
By the end of the chapter, you will be able to create an empty, yet running world where you can build your awesome physics games.
Downloading and installing Box2D for Flash
You can download the latest version of Box2D for Flash either from the official site (http://www.box2dflash.org/download) or from the SourceForge project page (http://sourceforge.net/projects/box2dflash/).
Once you have downloaded the zipped package, extract the Box2D
folder (you can find it inside the Source
folder) into the same folder you are using for your project. The following is how your awesome game folder should look before you start coding:
You can see the Box2D
folder, the FLA file that I am assuming has a document class called Main
and therefore Main.as
, which is the class we will work on.
I would suggest you work on a 640 x 480 Flash movie at 30 frames per second (fps). The document class should be called Main
and the examples will look better if you use a dark stage background color, such as #333333
. At least these are the settings I am using throughout the book. Obviously you can change them as you want, but in that case your final movies may look a bit different than the examples shown in the book.
Now let's import Box2D classes.
Box2D is free and open source, so you won't need to install components or deal with SWC files. All you need to do to include it in your projects is to include the required classes.
Open Main.as
and write the following code snippet:
Test the movie and you should see my awesome game starts here in your Output window. This means you have successfully imported the required classes.
There isn't that much to say about the code we just wrote, as we are just importing the classes needed to make our Box2D project work.
When I gave the Hello Box2D World title, I did not mean to create just another "Hello World" section, but I wanted to introduce the environment where all Box2D simulation and events take place: the world.
The world is the stage where the simulation happens. Everything you want to be ruled by the Box2D physics must be inside the world. Luckily, the Box2D World is always big enough to contain everything you need, so you don't have to worry about world boundaries. Just remember everything on a computer has limits in one way or another. So, the bigger the world, the heavier will be the work for your computer to manage it.
Like all worlds, the Box2D World has a gravity
, so the first thing you need to do is define world gravity.
In your Main
function, add the following line:
This introduces our first Box2D data type: b2Vec2
.
b2Vec2
is a 2D column vector that is a data type, which will store x and y components of a vector. As you can see, the constructor has two arguments, both numbers, representing the x and y components. This way we are defining the gravity
variable as a vector with x=0
(which means no horizontal gravity) and y=-9.81
(which approximates Earth gravity).
Physics says the speed of an object falling freely near the Earth's surface increases by about 9.81 meters per second squared, which might be thought of as "meters per second, per second". So assuming there isn't any air resistance, we are about to simulate a real-world environment. Explaining the whole theory of a falling body is beyond the scope of this book, but you can get more information by searching for "equations for a falling body" on Google or Wikipedia.
You can set your game on the move with the following line:
You can also simulate a no gravity environment with the arguments set at (0,0)
:
Note
Working with no gravity is also useful if you want to work in a top-down environment.
We also need to tell if bodies inside the world are allowed to sleep
when they come to rest, that is when they aren't affected by forces. A sleeping body does not require simulation, it just rests in its position as its presence does not affect anything in the world, allowing Box2D to ignore it, and thus speeding up the processing time and letting us achieve a better performance. So I always recommend to put bodies to sleep when possible.
Note
Sleeping bodies won't sleep forever and they'll wake up as soon as a collision occurs or a force is applied directly on them.
Add the following line, which is just a simple Boolean variable definition:
And finally, we are ready to create our first world:
Now we have a container to manage all the bodies and perform our dynamic simulation.
Time to make a small recap. At the moment, your code should look like the following:
Now you learned how to create and configure a Box2D World. Let's see how can you simulate physics in it.
You need to run the simulation at every frame, so first of all you need a listener to be triggered at every frame.
Let's make some simple changes to our class:
Nothing new, we just added an ENTER_FRAME
event, but we needed it in order to run the simulation inside the updateWorld
function. If you have doubts regarding event handling with AS3, refer to the official Adobe docs or get Flash Game Development by Example, Packt Publishing, which will guide you to a step-by-step creation of pure AS3 games.
Box2D simulation works by simulating the world at discrete steps of time. This means the world gets updated at every time step. It's up to us to decide which time step we are going to use for our simulation. Normally, physics in games have a time step of 1/60 seconds. Anyway, as I am running the Flash movie at 30 fps, I am going to set a time step of 1/30 seconds.
The first line into the updateWorld
function will be:
Just defining a time step, is not enough. At every step, every physic entity is updated according to the forces acting on it (unless it's sleeping). The algorithm which handles this task is called constraint solver. It basically loops through each constraint and solves it, one at a time. If you want to learn more about constraints, search for "constraint algorithm" on Google or Wikipedia.
Where's the catch? While a single constraint is solved perfectly, it can mess with other constraints that have already been solved.
Think about two balls moving: in the real world, each ball position is updated at the same time. In a computer simulation, we need to loop through the balls and update their position one at a time. Think about a for
loop that updates a ball at every iteration. Everything works as long as the balls do not interact with each other, but what happens if the second ball hits the first, whose position has already been updated? They would overlap, which is not possible in a rigid body simulation.
To solve this problem with a reasonable approximation, we need to loop over all the constraints more than once. Now the question is: how many times?
There are two constraint solvers: velocity constraint solver
and position constraint solver
. The velocity solver is used to move physic entities in the world according to their impulses. The position solver adjusts physic entities' positions to avoid overlap.
So it's obvious that the more iterations there are, the more accurate the simulation, and the lower will be the performance. I managed to handle more than 100 physic entities using 10 velocity and position iterations, although the author of Box2D recommends 8 for velocity and 3 for position.
It's up to you to play with these values. Meanwhile, I'll be using 10
iterations for both constraint solvers.
So here we go with two new variables:
Finally we are ready to call the Step
method on the world
variable to update the simulation.
To use world
inside the updateWorld
function, we need to declare world
as a class-level variable, shown as follows:
Now we have our world configured and running. Unfortunately, it's a very boring world, with nothing in it. So in the next chapter, we are going to populate the world with all kinds of physic entities.
Just one last thing, after each step you need to clear forces, to let the simulation start again at the next step.
You can do it by adding the following line right after the Step
method:
Tip
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
And now you are really ready to place some action in your Box2D World.
You have just learned how to install Box2D for Flash. Include it in your projects and create a running, gravity-ruled simulation managing time steps and constraint solvers.
You have an empty world ready to be the container where your awesome game will take place. Save it and use it in every future project!