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

点击下载源文件

联系作者

公众号:拉小登 | 微博:拉登Dony | B站:拉小登Excel

文章分类 > Nape

One Reply to “BodyListener侦听刚体状态”

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注