组合法创Nape多边形刚体
看到题目有没有有想到Box2D多边形刚体里的组合法和原生法创建Box2D多边形刚体呢?没错Nape的组合法跟Box2D在原理上是一样的。今天我们来学习一下Nape中创建多边形刚体的组合法。
我们知道,Nape中的刚体结构比Box2D刚体结构要简单,没有b2FixtureDef、b2Fixture或b2ShapeDef、b2Shape等这些让人头疼的类和混乱的关系,Nape刚体的所有图形都在Body.shapes属性中,用组合法创建多边形刚体,我们需要做的就是把多个Shape对象或子对象添加到Body.shapes属性中就可以了。
打个比方来讲。我们都知道,在Flash中可以将一个MovieClip对象作为容器,将其他的MoviClip对象添加到其中,作为它的子对象,当我们旋转这个容器时,里面的子对象也会随着旋转。Body.shapes属性就相当于这个容器,要添加的Shape图形就是容器中的子对象,这样讲应该会比较好理解吧!
Body.shapes会返回一个ShapeList对象,然后我们可以通过调用ShapeList的push()方法将其他Shape图形添加进去,代码如下:
var circle:Shape=new Circle(5); body.shapes.push(circle);
图形添加进去之后,默认是在刚体的中心的,如下面图中的矩形。但是,有时候我们也会遇到下图中圆形Shape的情况,图形不在刚体的中心,
这时候就要用shape的localCOM(即local center of mass重心)属性设置图像的偏移量。
如上图圆形的圆心在(10,10)处,那么设置它的偏移量代码应该写成:
var circle:Shape = new Circle(5); //设置图形的偏移量 circle.localCOM.setxy(10,10); body.shapes.push(circle);
解决了图形偏移量的问题,新的问题又来了,像下图中添加图形后,刚体中心(也是重心)在图形之外,这在现实生活中是不大可能发生的,我们需要把刚体重心移动至合理的位置,比如下图中矩形和圆形之间。
怎么做呢?很简单,Body中有一个align()方法,可以自动纠正刚体的重心移动到图形中心位置。代码如下:
//纠正刚体的重心 body.align();
完成了这些工作之后,我们就可以创建出完美的组合式多边形刚体啦!
在下面的示例用,点击并拖动上面工具条中的矩形或圆形,可以创建一个图形,点击创建好的图形,可以进行角度调整,多创建几个并将它们进行组合后,点击create按钮创建刚体。试试看吧!
[swfobject]772[/swfobject]
很酷吧,是不是有点神奇的阿力的感觉?
完整的源代码如下,点击这里下载源文件。
代码的重点在71-98行,创建图形并添加到Body刚体中,我已经添加了详细的注释,就不再赘述了。
package { import com.bit101.components.PushButton; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import utils.LDEasyNape; import utils.TransformTool; import utils.Stats; import nape.phys.Body; import nape.phys.BodyType; import nape.phys.Material; import nape.shape.Circle; import nape.shape.Polygon; import nape.shape.Shape; [SWF( width="550", height="400", frameRate="60")] public class T12_CreatePolygonBodyWithShapes extends AbstractNapeTest { private var spriteList:Vector.<Sprite>; private var curShape:Sprite; //旋转工具类 private var transformTool:TransformTool; private var transformPara:Object; public function T12_CreatePolygonBodyWithShapes() { //创建多动变形工具 transformTool=new TransformTool(stage); transformPara={enScaleX:false, enScaleY:false, enSkewX:false, enSkewY:false, enSetMidPoint:false }; //创建存储图形的Vector数组 spriteList=new Vector.<Sprite>(); } override protected function onNapeWorldReady():void { //添加上方的工具条 var bg:Sprite=new Sprite(); addChild(bg); bg.graphics.beginFill(0,0.8); bg.graphics.drawRect(0,0,550,50); bg.graphics.endFill(); var shape1:Sprite=createRectShape(150,25,80,30); var shape2:Sprite=createCircleShape(250,25,15); shape1.name="rectBtn"; shape2.name="circleBtn"; //添加create按钮,并侦听按钮事件 var btn:PushButton = new PushButton(this, 400, 10, "createBody", function():void { //按钮按下后,遍历spriteList数组,根据数组里的元素创建Nape刚体 if (spriteList.length < 1) return; //创建Nape刚体 createBodyWidthShapes(); //删除Sprite图形 for (var i:int=0 ;i<spriteList.length;i++){ var sprite:Sprite=spriteList[i]; sprite.parent.removeChild(sprite); } //清空数组 spriteList=new Vector.<Sprite>(); }); } //创建刚体 private function createBodyWidthShapes():void{ var body:Body = new Body(); //遍历SpriteList数组里的每个元素 for each(var sprite:Sprite in spriteList) { //根据这些元素,创建图形,并添加到body.shapes属性中 body.shapes.push(createNapeShape(sprite)); } //纠正刚体重心 body.align(); body.space=napeWorld; } //创建Nape中的shape对象,准备添加到刚体中 private function createNapeShape(sprite:Sprite):Shape { var s:Shape; if(sprite.name=="circleBody"){ s = new Circle(15, null, Material.glass()); //设置刚体偏移量 s.localCOM.setxy(sprite.x,sprite.y); }else if(sprite.name=="rectBody"){ s = new Polygon(Polygon.box(80, 30), Material.glass()); //旋转图形 s.rotate((sprite.rotation) % 360 * Math.PI / 180); //设置刚体偏移量 s.localCOM.setxy(sprite.x,sprite.y); } return s; } //鼠标点击后,根据点击的对象不同,进行不同的操作 override protected function mouseEventHanlder(me:MouseEvent):void{ if(me.type==MouseEvent.MOUSE_DOWN){ switch(me.target.name) { //如果是工具条中的矩形或圆形,则新建相应的图形 case "circleBtn": { curShape=createCircleShape(mouseX,mouseY,15,0x339999); curShape.name="circleBody"; curShape.startDrag(); spriteList.push(curShape); break; } case "rectBtn": { curShape=createRectShape(mouseX,mouseY,80,30,0x339999); curShape.name="rectBody"; curShape.startDrag(); spriteList.push(curShape); break; } //如果是创建好的图形,则进行拖动或旋转 case "rectBody": case "circleBody": { curShape=me.target as Sprite; transformTool.AddControl(curShape); transformTool.SetStyle(curShape,transformPara); transformTool.Init(); break; } default: { break; } } }else if(me.type==MouseEvent.MOUSE_UP){ if(curShape!=null) curShape.stopDrag(); } } //创建图形的两个函数 private function createRectShape(x:Number,y:Number,w:Number,h:Number,color:uint=0xFFFFFF):Sprite{ var rect:Sprite=new Sprite(); rect.graphics.lineStyle(1); rect.graphics.beginFill(color,1); rect.graphics.drawRect(-w/2,-h/2,w,h); rect.graphics.endFill(); rect.x=x; rect.y=y; addChild(rect); rect.buttonMode=true; return rect; } private function createCircleShape(x:Number,y:Number,r:Number,color:uint=0xFFFFFF):Sprite{ var circle:Sprite=new Sprite(); circle.graphics.lineStyle(1); circle.graphics.beginFill(color,1); circle.graphics.drawCircle(0,0,r); circle.graphics.endFill(); circle.x=x; circle.y=y; addChild(circle); circle.buttonMode=true; return circle; } } }
联系作者
怎样贴图呢
谢谢关注,贴图教程请参考http://www.ladeng6666.com/blog/2013/01/17/nape2-0-3-nape-body-attach-picture/