Nape Game Dynamics Logo

Using the Nape Physics Engine in ActionScript 3

If you have been pulling your hair out trying to figure out how Box2DFlash (aka Box2DAS3) works, you are not alone. The problem is that, until recently, there were very few simple, free and solid alternatives. And then came the Nape Physics Engine…

Update : this tutorial does not work with Nape 2.0 or higher. Check out my updated tutorial if you are working with Nape’s latest version.

Nape is a lighter-weight 2D physics engine which will most likely satisfy all your needs while being much easier to use than Box2DFlash. It is also usually faster than Box2DFlash. It does have a few drawbacks but, overall, I highly recommend you try it out. For a more detailed comparison between the two, check out this post by Trent Sterling.

During this tutorial, we will create the following very simple physics world. It comprises a floor (just below the bottom) and smiley 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 and open it in Flash Pro as you will need it to follow along. Now, how can we use this Nape thing…

1. 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 won’t 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 that’s not really a problem…

With that out of the way, 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.

To be able to use the library, you now need to link Nape to your project. This is done by linking the nape_debug.swc (or nape_release.swc) file to your .fla file. If you don’t know how to do that, just read my post titled Linking .swc files in your ActionScript Editor for all details.

2. Setup the Nape space

At this stage, you must follow along with the provided source code. The more obvious code has not been repeated here for brevity’s sake.

Everything in the Nape world happens in one single object called the Space object. Let’s 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 don’t 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.

3. Add a first physical body : the floor

Now, we need to add bodies into our world. Let’s 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, we’ll define it as Body.STATIC.

Obviously, we now need to define our body’s 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

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);

You would expect the next step to be to add the body to our space. However, it works the other way around. I think this is a bit counter-intuitive but you need to tell the body which space it belongs to :

floorPhysicsBody.space = space;

4. Add more bodies : the smiley balls

The way the example works is that when you click, it generates a new smiley, which then falls to the ground. I’m going to skip the obvious suff and go directly to the creation of the smiley balls after the user has clicked :

var smileyPhysicsBody:Body = new Body(BodyType.DYNAMIC, new Vec2(stage.mouseX, stage.mouseY));
var material:Material = new Material(1.5);
smileyPhysicsBody.shapes.add(new Circle(s.width >> 1, null, material));
smileyPhysicsBody.space = space;

This time, the body type is DYNAMIC since the smiley 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 smiley, we create a new material and use it to create the shape. Materials can have properties such as elasticity, density, friction, etc.

5. The Nape Space vs Flash’s Display List

The next two lines are very important to understand. Basically they tie together Flash’s display list and Nape’s physics world. You have to understand that the physics simulation happens in its own separate world invisible to us. In order for the user to witness any of it, we need to link physics bodies to DisplayObjects we can actually see :

smileyPhysicsBody.graphic = s;
smileyPhysicsBody.graphicUpdate = updateGraphics;

Here, we assign the smiley Sprite (s) to be the graphic linked to the smiley body. All this does is create a link between them. Then we specify a function that should be called when the graphic is updated. Notice that updateGraphics is indeed a function. I would have preferred a less JavaScript-like way of doing things but, hey, it works.

As you may have guessed, we now have to create the updateGraphics function :

private function updateGraphics(b:Body):void {
    b.graphic.rotation = (b.rotation * 180 / Math.PI) % 360;
    b.graphic.x = b.position.x ;
    b.graphic.y = b.position.y ;
}

All it does is copy the position and rotation of the body to the DisplayObject linked to it. There’s one little thing to notice : Nape uses radians to express rotation while ActionScript uses degrees. This is why a little conversion is needed between the two.

6. Get things moving

We are almost done. The only thing left is to keep recalculating our world to reflect its current status. 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 space via this line :

space.step(1 / stage.frameRate);

In our example, the frame rate is 60fps. Therefore, the Space is being updated every 1/60th of a second. The code that follows simply removes smileys that are no longer visible in order to preserve memory.

Final notes

At this stage you might be wondering about the DEBUG constant. 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 graphic have been assigned to them.

If you want to see the output of ShapeDebug, simply comment those to two lines and recompile :

smileyPhysicsBody.graphic = s;
smileyPhysicsBody.graphicUpdate = updateGraphics;

That’s it! Your questions and comments are, as usual, welcome. Hope this helps.

Comments

  1. Is the circle necessary? Is there anyway to build a graphic and have only the graphic used inside the physics?

    Also, I liked the tutorial too. Good work.

      1. Yes, I saw that class, but have had trouble figuring out how to work with it on a simple graphic in my library in Flash. I made a ball and a circle, and tried passing them into the BodyFromGraphic class. This ended up showing nothing on the stage. It is doing something with the polys that is weird. Essentially what I need is a MovieClip – that will eventually be made up of a circle and a box (the box will be description of the contents of the circle). When the graphic is clicked on, it can be dragged and needs to bump other graphics that are the same. I do not need any gravity on the items, but finding a library that handles the odd shape of my circle/rectangle has been hard. Nape seems like a solution, but I cannot figure out how to get my interactions to work with a much more complex shape.

        1. You can build a body by passing any DisplayObject (MovieClip, Shape, Bitmap, etc.) to the BodyFromGraphic.graphicToBody() function. This will add a body to the Nape physics space. If you want to see something on the Stage, you still need to attach a regular DisplayObject to the object’s graphic property (as explained in this tutorial). An easy way, to see if it works is to enable DEBUG mode.

          Another way is to use external tools (such as Physics Editor) to transform bitmaps into ready-to-use Nape objects (see above).

      2. Sorry for the multiple comments, I appreciate your time in answering. I think what I need is to add multiple shapes into the body to get what I need. It might just be as easy as putting in a circle and a square and position the square in the proper place. But how can I get the shapes to show up as visible false? I do not want them to show up in the scene. I just want them there as a guide as to what to respond to?

        1. The bodies added to the Nape space are NOT visible (they are not in the display list). The only way to see the objects’ behaviour is to attach a DisplayObject to them (via their graphic property) or to enable DEBUG mode.

  2. Where are you getting the “graphic”, like in “smileyPhysicsBody.graphic = s;”? Whenever I try, it tells me it doesn’t know what that is.
    I’ve made sure to import everything.

    1. If the graphic property is not available, it’s probably because you are using Nape v2.0 or greater. Starting in version 2, the API changed and the graphic property no longer exists (same goes for graphicUpdate). If that’s the case, look at the updated version of this tutorial that works with Nape version 2.0+

  3. Thanks for tutorial i am new in Nape and Starling. I am confused about Template Class imported in this source code. could you please explain.

    Thanks
    Manpreet Singh

    1. I don’t know what you mean by Template Class, can you please clarify ? By the way, this tutorial uses ActionScript’s standard display list, not Starling.

  4. thanks Jean-Philippe , for this great framework . I am facing a bit difficulty to have a dice throw effect , where the image of dice to be updated on each mouse down in addition to that when i add a rectangle by Polygon.rect() the rolling effect is centered on the starting point of rectangle creation

    thanks in advance.

Leave a Reply

Your email address will not be published. Required fields are marked *