Understanding NAPE collision detection
One of the features which highly contribute to the success of a physics engine is the collision detection.
NAPE has a robust collision detection, although you won’t find that much information around the web, that’s why this blog is a must read :)
To explain the basics of NAPE collision detection, I stripped the Hundreds game prototype and now I only have one ball running around the stage and bouncing off walls.
I will show you how to detect collision between the ball and the walls.
Look at the result:
Each time the balls bounce off the walls, the stage color changes.
This is the script:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
package { import flash.display.Sprite; import flash.events.Event; import nape.geom.Vec2; import nape.phys.Body; import nape.phys.BodyList; import nape.phys.BodyType; import nape.shape.Polygon; import nape.shape.Circle; import nape.space.Space; import nape.util.ShapeDebug; import nape.shape.ShapeList; import nape.callbacks.*; public class Main extends Sprite { private var napeWorld:Space=new Space(new Vec2(0,0)); private var debug:ShapeDebug=new ShapeDebug(640,480,0x00ff00); private var napeDebugSprite:Sprite=new Sprite(); private var circleSpeed:Number=150; private var interactionListener:InteractionListener; private var wallCollisionType:CbType=new CbType(); private var ballCollisionType:CbType=new CbType(); private var ball:Body; public function Main():void { interactionListener=new InteractionListener(CbEvent.BEGIN,InteractionType.COLLISION,wallCollisionType,ballCollisionType,ballToWall); napeWorld.listeners.add(interactionListener); addChild(napeDebugSprite); napeDebugSprite.addChild(debug.display); ball=addCircle(); addWall(320,0,640,10); addWall(320,480,640,10); addWall(0,240,10,480); addWall(640,240,10,480); addEventListener(Event.ENTER_FRAME,update); } private function ballToWall(collision:InteractionCallback):void { graphics.clear(); graphics.beginFill(Math.random()*0xFFFFFF,0.5); graphics.drawRect(0,0,stage.stageWidth, stage.stageHeight ); graphics.endFill(); } private function addCircle():Body { var napeBody:Body=new Body(BodyType.DYNAMIC,new Vec2(Math.round(Math.random()*600+20),Math.round(Math.random()*440+20))); napeBody.cbTypes.add(ballCollisionType); var circle:Circle=new Circle(10); circle.material.elasticity=0.5; circle.material.density=1; circle.material.staticFriction=0; napeBody.shapes.add(circle); napeBody.space=napeWorld; napeBody.userData.name="circle"; var randomAngle:Number=Math.random()*2*Math.PI; napeBody.velocity=new Vec2(circleSpeed*Math.cos(randomAngle),circleSpeed*Math.sin(randomAngle)); return napeBody; } private function addWall(pX:Number,pY:Number,w:Number,h:Number):void { var napeBody:Body=new Body(BodyType.STATIC,new Vec2(pX,pY)); napeBody.cbTypes.add(wallCollisionType); var polygon:Polygon=new Polygon(Polygon.box(w,h)); polygon.material.elasticity=0.5; polygon.material.density=1; polygon.material.staticFriction=0; napeBody.shapes.add(polygon); napeBody.space=napeWorld; } private function update(e:Event):void { napeWorld.step(1/30,10,10); var velocity:Vec2=ball.velocity; var speed:Number=velocity.length; var ratio:Number=circleSpeed/speed; ball.velocity.muleq(ratio); debug.clear(); debug.draw(napeWorld); debug.flush(); } } } |
Let’s comment line by line what’s involved in collision detection:
|
20 21 22 |
private var interactionListener:InteractionListener; private var wallCollisionType:CbType=new CbType(); private var ballCollisionType:CbType=new CbType(); |
Line 20: defining an interaction listener. Since a collision is an interaction, we need to define it at first.
Lines 21-22: these are Callback Types, and I am going to use them in a smart way to detect only some kind of collisions. Think about a Callback Type like a built-in Box2D collision filtering, if you are used to it.
|
25 26 |
interactionListener=new InteractionListener(CbEvent.BEGIN,InteractionType.COLLISION,wallCollisionType,ballCollisionType,ballToWall); napeWorld.listeners.add(interactionListener); |
Line 25: the core of the script: the Interaction Listener. You can handle any type of interaction with it, but since I am looking for collisions, here is the list of arguments:
CbEvent.BEGIN: the event type to listen for, in this example the begin of the event.
InteractionType.COLLISION: the interaction type to listen for, in this example a collision.
wallCollisionType: the OptionType to match first Interactor against, in this case the wall collision type
ballCollisionType: the OptionType to match second Interactor against, in this case the ball collision type
ballToWall: the callback function
Line 26: at this time, the newly created listeners is added to the NAPE world.
Line 44: this is how I add the ball to its Callback Type
Line 58: same thing for the wall.
And that’s it. No need to download any source code, just copy/paste it in the Hundreds game prototype source code.
They can be easily customized to meet the unique requirements of your project.





(6 votes, average: 4.50 out of 5)








This post has 2 comments
Understanding NAPE collision detection – Emanuele Feronato « eaflash
[...] on http://www.emanueleferonato.com Share this:TwitterFacebookLike this:LikeBe the first to like [...]
Walter Torres
Thank you, this helped! but I have a question for you, do you know how to add your own object to the “collision:InteractionCallback” in order to affect objects beyond the scope of nape? such as the hp of a character when it gets hit by a projectile.