LDEasyNape vs LDEasyBox2D
大家都知道LDEasyBox2D可以帮我们简化Box2D应用的创建过程。近期拉登大叔也在研究Nape,虽说Nape的用法比Box2D要简单不少,但是用惯了LDEasyBox2D,还是觉得有点繁杂,所以拉登大叔也写了一个LDEasyNape。
与此同时也对LDEasyBox2D做了一些修改,统一了LDEasyNape和LDEasyBox2D的函数,可以用相同的方法创建Nape或Box2D方法。闲话少说,我们来看看具体的用法。
大体的步骤如下:
- 用initialize(stage:Stage,napeFps:uint=60)方法设置LDEasyNape引用的Flash舞台对象,以及模拟帧频(默认为60)。
- 用createDebug()方法创建模拟视图,同时将返回的BitmapDebug对象的display属性添加到舞台上。
- 利用createCircle、createBox、createRegular等等方法快速创建刚体
- 在EnterFrame事件处理函数中调用updateWorld()更新Nape空间模拟。
另外和以前的LDEasyBox2D一样,我们还可以用getBodyAtMouse()方法获取鼠标位置处的刚体,用startDragBody和stopDragBody方法开始或停止拖动刚体。
依然很简单,不过在使用时不用再设置stage等其他属性了,接口更加简化了,相同的方法可以用在LDEasyBox2D和LDEasyNape上,同一了两个物理引擎的用法。下面是LDEasyBox2D和LDEasyNape在Google Code上是地址,你可以在这里获得的最新的LDEasy类。
LDEasyBox2D:http://code.google.com/p/ldeasybox2d/
LDEasyNape:http://code.google.com/p/ldeasynape/
除了统一了这两个类之外,我还自定义了一个LDEasyUserData类,同样都适用于LDEasyBox2D和LDEasyNape。LDEasyUserData中有两个公共方法setGraphicAuotmatically和setGraphic,它们的用法如下:
- setGraphicAuotmatically:通过这个方法的参数可以快速设置由单色填充的自定义刚体视图
- setGraphic:设置开发者自定义的刚体视图
然后在创建刚体的createCircle、createBox、createRegular等方法的最后一个参数中设置LDEasyUserData对象,快速创建自定义视图。
同时LDEasyUserData也是一个动态类,使用时你可以随意添加新的属性。下面是Nape贴图里的示例用LDEasyNape和LDEasyUserData实现的代码,看,是不是简单了许多?
下面的示例中,同时Box2D和Nape创建了刚体,红色刚体是Box2D的,蓝色是Nape的,鼠标点击可以拖动刚体。
[swfobject]796[/swfobject]
代码中,我定了createNapeWorld()和createBox2DWorld()两个方法,分别创建Nape和Box2D的应用,对比一样,基本都是一样的,代码很简单,我就不逐一解释了,大家直接看代码吧!
package { import flash.display.Sprite; import Box2D.Dynamics.b2World; import flash.events.Event; import flash.events.MouseEvent; import nape.space.Space; import ldEasyBox2D.LDEasyBox2D; import ldEasyBox2D.LDEasyUserData; import ldEasyNape.LDEasyNape; import ldEasyNape.LDEasyUserData; /** * ... * @author ... */ public class LDEasyPhysicEngine extends Sprite { private var napeWorld:Space; private var box2DWorld:b2World; public function LDEasyPhysicEngine() { createNapeWorld(); createBox2DWorld(); stage.addEventListener(Event.ENTER_FRAME, loop); stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler); stage.addEventListener(MouseEvent.MOUSE_UP, mouseEventHandler); } private function createBox2DWorld():void { LDEasyBox2D.initialize(stage, 60); LDEasyBox2D.createWorld(0,0); addChild(LDEasyBox2D.createDebug().GetSprite()); LDEasyBox2D.createWrapWall(); var ud:ldEasyBox2D.LDEasyUserData = new ldEasyBox2D.LDEasyUserData(); ud.setGraphicAuotmatically(0xff0000); for(var i:int=0; i<10; i++){ var randomseed:Number=Math.random(); var posX:Number = Math.random()*500 + 25; var posY:Number = Math.random()*300 + 50; if(randomseed<0.25){ LDEasyBox2D.createBox(posX, posY, 30, 30,false,false,ud.clone()); }else if(randomseed<0.5){ LDEasyBox2D.createRegular(posX, posY, 30,5, 0,false, false, ud.clone()); }else if(randomseed<0.75){ LDEasyBox2D.createRegular(posX, posY, 30,3, 0,false, false, ud.clone()); }else{ LDEasyBox2D.createCircle(posX, posY, 30,false,false,ud.clone()); } } } private function createNapeWorld():void { LDEasyNape.initialize(stage, 60); LDEasyNape.createWorld(0,0); addChild(LDEasyNape.createDebug().display); LDEasyNape.createWrapWall(); var ud:ldEasyNape.LDEasyUserData = new ldEasyNape.LDEasyUserData; ud.setGraphicAuotmatically(0x0000ff); for(var i:int=0; i<10; i++){ var randomseed:Number=Math.random(); var posX:Number = Math.random()*500 + 25; var posY:Number = Math.random()*300 + 50; if(randomseed<0.25){ LDEasyNape.createBox(posX, posY, 30, 30,false,false,ud.clone()); }else if(randomseed<0.5){ LDEasyNape.createRegular(posX, posY, 30,5, 0,false, false, ud.clone()); }else if(randomseed<0.75){ LDEasyNape.createRegular(posX, posY, 30,3, 0,false, false, ud.clone()); }else{ LDEasyNape.createCircle(posX, posY, 30,false,false,ud.clone()); } } } private function mouseEventHandler(event : MouseEvent) : void { switch(event.type){ case MouseEvent.MOUSE_DOWN: LDEasyNape.startDragBody(LDEasyNape.getBodyAtMouse()); LDEasyBox2D.startDragBody(LDEasyBox2D.getBodyAtMouse()); break; case MouseEvent.MOUSE_UP: LDEasyNape.stopDragBody(); LDEasyBox2D.stopDragBody(); break; default: } } private function loop(event : Event) : void { LDEasyNape.updateWorld(); LDEasyBox2D.updateWorld(); } } }
联系作者
拉登叔,在您的这个DEMO中,拖动NAPE物体时,debugdraw的边框与贴图会出现不同步的情况。
在LDEASYNAPE.AS 中154行
public static function updateWorld():void{
for(var i:int=0; i<world.liveBodies.length;i++){
var body:Body=world.liveBodies.at(i);
var graphic:DisplayObject=body.userData.graphic;
var position:Vec2=body.position;
if(graphic!=null){
graphic.x=position.x;
graphic.y=position.y;
graphic.rotation=(body.rotation*180/Math.PI)%360;
}
}
world.step(1/LDEasyNape.napeFps);
if(napeDebug!=null){
napeDebug.clear();
napeDebug.draw(world);
napeDebug.flush();
}
if(hand!=null){
if(hand.active) hand.anchor1.setxy(stage.mouseX,stage.mouseY);
}
}
nape的贴图部分与debug部分被 world.step(1/LDEasyNape.napeFps); 隔开了,导致贴图总比debug慢一帧。
实际游戏中,不显示调试视图就可以了!