BodyListener侦听刚体状态
在《碰撞检测》一节中,我们简单的认识了Nape中的4个碰撞侦听,这一节我们来一起深入了解一下BodyListener侦听器的用法。
与《PreListener》不同,BodyListener和刚体的碰撞没有任何的关系,它的作用是侦听刚体的状态变化。
我们知道,为了提升引擎的运行效率,静止不同的刚体,Nape会将其设置为sleep状态,来避免无谓的模拟计算,当刚体再次运动起来的时候,Nape会将其重新设置为wake状态。BodyListener的作用就是侦听刚体在两个状态之间的变换。
你可能会问啦,侦听这个效果有什么用啊?
你肯定玩过愤怒的小鸟吧,在小鸟发射后,需要等到停止之后,才可以继续发射下一只小鸟。这时候,我们可以通过BodyListener来侦听第一个小鸟是否已经停止运动,然后再发射下一个小鸟。
下面我们来看一下BodyListener的具体用法,其结构如下:
public function BodyListener( event:CbEvent, options:OptionType, handler:BodyCallback, precedence:Int = 0 )
各个参数说明如下
- cbEvent:和PreListener中的cbEvent参数一样,不过对于BodyListener只有SLEEP和WAKE属性才适用,分别对应刚体的两个状态。
- cbOption:要侦听的刚体类型描述
- handler:BodyListener事件处理函数,开发者在定义该函数时应遵循以下结构
public function hanlder(cb:BodyCallback){ //处理代码 }
- precedence:当不同的事件侦听器同时侦听相同的刚体之间相同的碰撞事件时,触发侦听器的优先权。
其中参数cb是一个BodyCallback对象,该对象只有一个属性body,表示状态发生变化的刚体
BodyListener的使用方法与PreListener类似,如以下代码所示:
var sleepListener:BodyListener = new BodyListener(CbEvent.SLEEP,birdFlying,onBodySleep); space.listeners.add(sleepListener);
在下面的示例中,你可以点击并拖动左侧圆形刚体,来模拟小鸟的弹射。当弹射出去的刚体停止运动后,出发BodyListener侦听器,添加下一个小鸟。点击图片查看动态效果。
[swfobject]1347[/swfobject]
完整的源代码如下:
package { import flash.events.Event; import flash.events.MouseEvent; import ldEasyNape.LDEasyBody; import ldEasyNape.LDEasySpace; import nape.callbacks.BodyCallback; import nape.callbacks.BodyListener; import nape.callbacks.CbEvent; import nape.callbacks.CbType; import nape.geom.Vec2; import nape.phys.Body; import nape.phys.BodyList; import nape.phys.BodyType; public class WhatisBodyListener extends AbstractNapeTest { public function WhatisBodyListener(gravity:Number=600) { super(gravity); } private var birdFlying:CbType; private var areaPos:Vec2 = new Vec2(150,200); private var areaRadius:Number = 50; private var dragBody:Body; private var mousePoint:Vec2 = new Vec2(); override protected function onNapeAppReady():void { LDEasyBody.createRectangle(0,0,stage.stageWidth,stage.stageHeight); var rope:Body = LDEasyBody.createBox(400,150,20,200); LDEasySpace.fixBodyAt(rope,400,100); birdFlying = new CbType(); createBirdBody(); var sleepListener:BodyListener = new BodyListener(CbEvent.SLEEP,birdFlying,onBodySleep); space.listeners.add(sleepListener); } private function onBodySleep(cb:BodyCallback):void { cb.body.cbTypes.remove(birdFlying); createBirdBody(); } private function createBirdBody():void{ var body:Body = LDEasyBody.createRegular(areaPos.x,areaPos.y,20,Math.floor(Math.random()*4+3)); body.type = BodyType.KINEMATIC; body.cbTypes.add(birdFlying); } override protected function mouseEventHanlder(event:MouseEvent):void { mousePoint.x = mouseX; mousePoint.y = mouseY; switch(event.type) { case MouseEvent.MOUSE_DOWN: { var bodyList:BodyList = space.bodiesUnderPoint(mousePoint); if(bodyList.length>0){ dragBody = bodyList.at(0); if(Vec2.distance(dragBody.position,areaPos) > areaRadius){ dragBody=null; } } break; } case MouseEvent.MOUSE_UP: { if(dragBody!=null){ throwBird(); dragBody=null; } break; } case MouseEvent.MOUSE_MOVE: { if(dragBody!=null){ dragBird(); } break; } } } private function dragBird():void{ var distance:Vec2 = mousePoint.sub(areaPos); var pos:Vec2 = mousePoint.copy(); if(distance.length >= areaRadius) { distance.normalise(); pos = areaPos.addMul(distance,areaRadius); } dragBody.position = pos.copy(); dragBody.rotation = distance.angle; } private function throwBird():void { var distance:Vec2 = areaPos.sub(mousePoint); var impulse:Vec2 = distance.copy().normalise(); impulse.muleq(distance.length/areaRadius * 600*dragBody.mass); dragBody.type = BodyType.DYNAMIC; dragBody.applyImpulse(impulse); } override protected function loop(event:Event):void { super.loop(event); debug.drawCircle(areaPos,areaRadius,0); if(dragBody!=null){ debug.drawSpring(dragBody.position,areaPos,0xff0000); } } } }
联系作者
大叔的东西很实用