Last active
December 15, 2015 21:29
-
-
Save vrobel/5326294 to your computer and use it in GitHub Desktop.
Replicates bug in NAPE when 2 kinematic/static bodies collide with each other and only one begin contact listener is dispatched
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package | |
{ | |
import flash.display.Sprite; | |
import flash.events.Event; | |
import flash.geom.Rectangle; | |
import nape.util.ShapeDebug; | |
public class KinematicCollisionDetectionBug extends Sprite | |
{ | |
public function KinematicCollisionDetectionBug() { | |
addEventListener( Event.ENTER_FRAME, init ); | |
} | |
private var game : KinematicCollisionDetectionGame; | |
private var debug : ShapeDebug; | |
private function init( e : Event ) : void { | |
removeEventListener( Event.ENTER_FRAME, init ); | |
stage.frameRate = 60; | |
var viewport : Rectangle = new Rectangle( 0, 0, stage.stageWidth, stage.stageHeight ); | |
game = new KinematicCollisionDetectionGame( viewport ); | |
debug = new ShapeDebug( viewport.width, viewport.height, 0 ); | |
addChild( debug.display ); | |
addEventListener( Event.ENTER_FRAME, tick ); | |
} | |
private function tick( e : Event ) : void { | |
game.step( 1 / stage.frameRate ); | |
debug.clear(); | |
debug.draw( game.getSpace() ); | |
debug.flush(); | |
} | |
} | |
} | |
import flash.geom.Point; | |
import flash.geom.Rectangle; | |
import nape.callbacks.CbEvent; | |
import nape.callbacks.CbType; | |
import nape.callbacks.InteractionCallback; | |
import nape.callbacks.InteractionListener; | |
import nape.callbacks.InteractionType; | |
import nape.dynamics.InteractionFilter; | |
import nape.geom.Vec2; | |
import nape.phys.Body; | |
import nape.phys.BodyType; | |
import nape.shape.Circle; | |
import nape.shape.Polygon; | |
import nape.shape.Shape; | |
import nape.space.Space; | |
class KinematicCollisionDetectionGame | |
{ | |
private static const BALL_CB : CbType = new CbType(); | |
private static const BULLET_CB : CbType = new CbType(); | |
private static const BALL_FILTER : InteractionFilter = new InteractionFilter( 1, 0, 1, ~1 ); | |
private static const BULLET_FILTER : InteractionFilter = new InteractionFilter( 1, 0, 2, ~2 ); | |
public function KinematicCollisionDetectionGame( gameViewport : Rectangle ) { | |
viewportCenter = new Point( gameViewport.x + gameViewport.width >> 1, gameViewport.x + gameViewport.height >> 1 ); | |
this.space = new Space(); | |
createContent(); | |
} | |
private var circle1Movement : MoveCircleAroundBehavior; | |
private var circle2Movement : MoveCircleAroundBehavior; | |
private var space : Space; | |
private var viewportCenter : Point; | |
public function getSpace() : Space { | |
return space; | |
} | |
public function step( time : Number ) : void { | |
if ( time > 0 ) { | |
circle1Movement && circle1Movement.step( time ); | |
circle2Movement && circle2Movement.step( time ); | |
space.step( time ); | |
} | |
} | |
private function createContent() : void { | |
var circle1 : Body = createKinematicBall( 20 ); | |
var circle2 : Body = createKinematicBall( 20 ); | |
if ( circle1 ) circle1Movement = new MoveCircleAroundBehavior( circle1, viewportCenter, 100, Math.PI ); | |
if ( circle2 ) circle2Movement = new MoveCircleAroundBehavior( circle2, viewportCenter, 100, -Math.PI ); | |
createStaticBullet( 80, new Vec2( viewportCenter.x - 100, viewportCenter.y ) ); | |
createBulletListener(); | |
} | |
private function createBulletListener() : void { | |
var beginBulletBallListener : InteractionListener = new InteractionListener( CbEvent.BEGIN, InteractionType.ANY, BULLET_CB, BALL_CB, begin_bulletBallHandler ); | |
var endBulletBallListener : InteractionListener = new InteractionListener( CbEvent.END, InteractionType.ANY, BULLET_CB, BALL_CB, end_bulletBallHandler ); | |
if ( beginBulletBallListener ) beginBulletBallListener.space = space; | |
if ( endBulletBallListener ) endBulletBallListener.space = space; | |
} | |
private function begin_bulletBallHandler( cb : InteractionCallback ) : void { | |
trace( cb.toString() ); | |
} | |
private function end_bulletBallHandler( cb : InteractionCallback ) : void { | |
trace( cb.toString() ); | |
} | |
private function createStaticBullet( size : Number, position : Vec2 = null ) : Body { | |
var body : Body = new Body( BodyType.STATIC ); | |
body.cbTypes.add( BULLET_CB ); | |
var shape : Shape = new Polygon( Polygon.box( size, size ), null, BULLET_FILTER ); | |
shape.sensorEnabled = true; | |
body.shapes.add( shape ); | |
position && body.position.set( position ); | |
body.space = space; | |
return body | |
} | |
private function createKinematicBall( radius : Number ) : Body { | |
var body : Body = new Body( BodyType.KINEMATIC ); | |
body.cbTypes.add( BALL_CB ); | |
var shape : Shape = new Circle( radius, null, null, BALL_FILTER ); | |
shape.sensorEnabled = true; | |
body.shapes.add( shape ); | |
body.space = space; | |
return body; | |
} | |
} | |
class MoveCircleAroundBehavior | |
{ | |
private var body : Body; | |
private var centerPoint : Point; | |
private var movementRadius : Number; | |
private var angularSpeed : Number; | |
private var currentAngle : Number = 0; | |
public function MoveCircleAroundBehavior( body : Body, centerPoint : Point, movementRadius : Number, angularSpeed : Number ) { | |
this.body = body; | |
this.centerPoint = centerPoint; | |
this.movementRadius = movementRadius; | |
this.angularSpeed = angularSpeed; | |
step( 0 ); | |
} | |
public function step( t : Number ) : void { | |
currentAngle += angularSpeed * t; | |
var currentRelativePosition : Point = Point.polar( movementRadius, currentAngle ); | |
body.position.setxy( currentRelativePosition.x + centerPoint.x, currentRelativePosition.y + centerPoint.y ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment