Using The Nape v2.0+ Physics Engine in ActionScript 3
Using The Nape v2.0+ Physics Engine in ActionScript 3
0+ Physics Engine in
ActionScript 3
Nape is a powerful 2D physics engine which compares favourably in many regards to the oft-used
Box2DFlashAS3. It is free and, more importantly, simple and quite intuitive to use. With the release of
version 2 in December 2012, some important changes to the API rendered my previous tutorial
obsolete. This new version now fully works with Napes latest version. So, if you are ready to upgrade,
read on!
Warning: you will need the latest version of Nape (2.0.3 at the time of this writing) in order for this
tutorial to work. If, for whatever reason, you still want to work with an older version, check out my
previous tutorial.
Nape is a lighter-weight 2D physics engine which will most likely satisfy all your needs while being
much easier to use than Box2D. It is also usually faster than Box2D. It does have a few drawbacks but,
overall, I highly recommend you try it out.
During this tutorial, you will learn how to create the following very simple physics world. It comprises
a floor (just below the bottom) and beach balls that bounce on it and each other. Click on the clip to
see how it works :
Before you begin the tutorial, be sure to grab the source code for this tutorial and open it in Flash Pro
as you will need it to follow along. Now, how can we use this Nape thing
Installation (download & linking)
Before we begin, there is one little thing about Nape that should be clarified. It has been written using
the Haxe language. Haxe is a language that can be cross-compiled into a variety of other languages
such as ActionScript 2/3, JavaScript, C++, C#, etc. This means we wont be able to download a package
containing a bunch of regular AS3 classes like we often do. Instead, we will download a .swc
(pronounced swic) file and link it to our project. This does not change anything for those who simply
want to use the library. But for those who want to hack the library code itself, you will have to do it in
Haxe. It also means the documentation is not quite what is being usually generated through tools such
as ASDoc but thats not really a problem
The source code package for this tutorial already includes the 2.0.3 development .swc file but if you
want to make sure you have the latest version, go to http://napephys.com/downloads.html and
download the latest development build. Luca Deltodesco (the creator of Nape) recommends to always
use the development version while developing and only use the release version for deployment (never
use the debugging version unless you want to debug Nape itself).
To be able to use the nape-dev.swc (or nape-release.swc) file, it needs to be to linked to your project.
It has already been done for you in the provided package. However, if you ever need to do it for
another project, just read my post titled Linking .swc files in your ActionScript Editor for all details.
Setup the Nape space
At this stage, you must follow along with the provided source code. The more obvious code has not
been repeated in this tutorial for brevitys sake.
Everything in the Nape world happens in one single object called the Space object. Lets start by
creating it :
space = new Space(new Vec2(0, 5000));
The Space object requires as a first parameter a Vec2 object which expresses the desired gravity. The
Vec2 is simply a vector with 2 entries : the movement on the x axis and the y axis. If you dont want
any gravity (such as in space), you can use Vec2(0, 0). In the example, gravity pulls down on the y axis.
If you wanted gravity to pull up, you could use a negative number.
Add a first physical body : the floor
Now, we need to add bodies into our world. Lets first create a Body object to represent the floor upon
which our smiley balls will bounce:
floorPhysicsBody = new Body(BodyType.STATIC);
As you can see, we need to specify the body type as a parameter. It can be STATIC, DYNAMIC or
KINEMATIC. Since our floor will not move or change, well define it as Body.STATIC.
Obviously, we now need to define our bodys shape. Actually, bodies can contain one or many shapes.
You can manually add shapes or use tools that will allow you to draw complex shapes such as Physics
Editor :
Physics Editor allows you to export your shapes as ready-to-use Nape-compatible AS3 classes. In our
case, we will simple use one of the basic shapes, the Polygon :
var p:Polygon = new Polygon (
Polygon.rect(
0, // x position
stage.stageHeight, // y position
stage.stageWidth, // width
100 // height
)
);
Then, we simply need to add our shape to the previously created body :
floorPhysicsBody.shapes.add(p);
As you can imagine, a single body can be created by compounding various shapes to create complex
arrangements. The next step is to add our newly created floor body to the Nape space:
space.bodies.add(floorPhysicsBody)
By the way, you can achieve the exact same thing by assigning Napes space to the bodys space
property :
floorPhysicsBody.space = space;
Add more bodies : the beach balls
The way the example works is that when you click, it generates a new ball, which then falls to the
ground. Im going to skip the obvious suff and go directly to the creation of the beach balls after the
user has clicked :
var ballPhysicsBody:Body = new Body(BodyType.DYNAMIC, new Vec2(stage.mouseX,
stage.mouseY));
var material:Material = new Material(1.5);
ballPhysicsBody.shapes.add(new Circle(s.width / 2, null, material));
space.bodies.add(ballPhysicsBody)
This time, the body type is DYNAMIC since the ball will be moving. It is positionned where the mouse
is clicked. Instead of a Polygon, we now use a circle. In order to control the bounciness of the ball,
we create a new material and use it to create the shape. Materials can have properties such as
elasticity, density, friction, etc.
The Nape Space vs Flashs Display List
Napes physics simulation is not meant to be directly seen. In order for us to see the behaviour and
movements of the bodies in the Nape space, we need to link them to something we can actually see :
DisplayObjects. The recommended way to do that is to assign a Sprite object (such as our s sprite) to
the userData property of the body. Because it is dynamic, we can create all sorts of member variables
inside the userData property. By convention, graphic is used (this is how it was named in the previous
implementation) :
ballPhysicsBody.userData.graphic = s;
What this does is store a reference to the bodys visual representation which we will use later on. As
of now, the visual will not move.
Get things moving
To make things move, we will have to constantly update our world to reflect its current state. You may
have seen that an event listener has been added to the ENTER_FRAME event. This listener fires the
loop() function which updates the Nape space via this line :
space.step(1 / stage.frameRate);
space.liveBodies.foreach(updateGraphics)
In our example, the frame rate is 60fps. Therefore, the physics simulation is being updated every
1/60th of a second. Once it has been updated, we need to sync our graphics to match the simulation.
To do that, we can use the BodyList class very convenient foreach() function. Basically, it goes through
all bodies in space.liveBodies and calls the updateGraphics() function on each of them. This allows us
to update the visual for each body according to the simulation.
The code that follows in the loop() function simply removes balls that are no longer visible in order to
preserve memory.
As you may have guessed, we now have to create the updateGraphics() function. This function
receives a reference to the body it is being called on as a parameter:
private function updateGraphics(b:Body):void {
var graphic:DisplayObject = b.userData.graphic;
graphic.x = b.position.x;
graphic.y = b.position.y;
graphic.rotation = (b.rotation * 180 / Math.PI) % 360;
}
The first line retrieves a reference to the DisplayObject that we stored earlier in the graphic property.
With that in hand, we simply update the position and rotation of the DisplayObject to match that of
the physics body.
Sidenote : Nape uses radians to express rotation while ActionScript uses degrees. This is why a little
conversion is needed between the two. Also, the modulo operator (%360) is used because AS3 does
not like big numbers for rotation.
Final notes
At this stage you might be wondering about the DEBUG constant that I used in the downloadable
source code of this tutorial. When DEBUG is set to true, a ShapeDebug object is being created. This is
optionnal and strictly for debugging purpose. The ShapeDebug object is a DisplayObject inside which
Nape draws outlines of the bodies in its physics world. This means that you can visualize the behaviour
of bodies even if no visuals have been assigned to them.
If you want to see only the output of ShapeDebug, simply comment out this line and recompile :
space.liveBodies.foreach(updateGraphics);
Thats it! Your questions and comments are, as usual, welcome. Hope this helps.