自定义刚体与拖动
调用b2PolygonDef的setAsBox函数传入一个半宽和半高,即可以创建一个矩形刚体,设置b2CircleDef的radius属性,即可以创建一个圆形的刚体,如果现在要创建一个五边形,六边形的刚体呢,box2d并没有提供这样的方法来创建。
利用b2PolygonDef的两个属性vertexCount和vertices,可以创建自定义刚体。
vertexCount:刚体的顶点数。
vertices:一个数组,用来保存刚体的所有定点。
package { import Box2D.Collision.Shapes.b2PolygonDef; import Box2D.Common.Math.b2Vec2; import Box2D.Dynamics.b2Body; import Box2D.Dynamics.b2BodyDef; import Box2D.Dynamics.b2DebugDraw; import Box2D.Dynamics.b2World; import Box2D.Dynamics.Joints.b2MouseJoint; import Box2D.Dynamics.Joints.b2MouseJointDef; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Point; import myClass.box2d.PhyOption; import myClass.box2d.Floor; import myClass.box2d.Wall; /** * ... * @author ywxgod */ [SWF(backgroundColor="0x333333",frameRate="30")] public class CustomBody extends Sprite { private var _world:b2World; private var _mouseJoint:b2MouseJoint; public function CustomBody() { if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event=null):void { removeEventListener(Event.ADDED_TO_STAGE, init); _world = PhyOption.getInstance().world; new Floor(new MyFloor(), this); new Wall(new MyFloor(), this, Wall.LEFT); new Wall(new MyFloor(), this,Wall.RIGHT); createBodies(); showDebug(); addEventListener(Event.ENTER_FRAME, onFrame); stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown); stage.addEventListener(MouseEvent.MOUSE_UP, onUp); } private function setConvexVertex(shapeDef:b2PolygonDef,n:int,radius:Number):void { shapeDef.vertexCount = n; var angle:Number = Math.PI * 2 / n; var radius:Number = radius / PhyOption.PHYSCALE; for (var i:int = 0; i < n;i++ ) { var dx:Number = radius * Math.cos(angle * i); var dy:Number = radius * Math.sin(angle * i); shapeDef.vertices[i].Set(dx,dy); } shapeDef.friction = 0.3; shapeDef.restitution = 0.3; shapeDef.density = 2; } private function setRandomInt(a:int,b:int):int { return a + Math.floor(Math.random() * (b - a + 1)); } private function createBodies():void { for (var i:int = 3; i <= 7;i++ ) { var xpos:Number = 275 + setRandomInt( -20, 20); var ypos:Number = 0; var radius:Number = 30 + setRandomInt( -20, 20); createBody(xpos,ypos,i,radius); } } private function createBody(xpos:Number,ypos:Number,vertexCount:int,radius:Number):void { var boxShapeDef:b2PolygonDef = new b2PolygonDef(); setConvexVertex(boxShapeDef,vertexCount,radius); var bodyDef:b2BodyDef = new b2BodyDef(); bodyDef.angle = Math.random() * 360; bodyDef.position.Set(xpos/ PhyOption.PHYSCALE, ypos/PhyOption.PHYSCALE); var body:b2Body = _world.CreateBody(bodyDef); body.CreateShape(boxShapeDef); body.SetMassFromShapes(); } private function showDebug():void { var sp:Sprite = new Sprite(); this.addChild(sp); var dbg:b2DebugDraw = new b2DebugDraw(); dbg.m_sprite = sp; dbg.m_alpha = 0.5; dbg.m_drawScale = PhyOption.PHYSCALE; dbg.m_fillAlpha = 0.5; dbg.m_drawFlags = b2DebugDraw.e_shapeBit; dbg.m_lineThickness = 1; _world.SetDebugDraw(dbg); } private function onFrame(e:Event):void { PhyOption.getInstance().update(); if (_mouseJoint) { _mouseJoint.SetTarget(new b2Vec2(stage.mouseX/PhyOption.PHYSCALE,stage.mouseY/PhyOption.PHYSCALE)); } } private function onDown(e:MouseEvent):void { var body:b2Body = PhyOption.getInstance().GetBodyAtMouse(this.stage); if (body) { var mouseJointDef:b2MouseJointDef = new b2MouseJointDef(); mouseJointDef.body1 = _world.GetGroundBody(); mouseJointDef.body2 = body; mouseJointDef.maxForce = 40000; mouseJointDef.timeStep = PhyOption.STEP; mouseJointDef.target.Set(stage.mouseX / PhyOption.PHYSCALE, stage.mouseY / PhyOption.PHYSCALE); _mouseJoint = _world.CreateJoint(mouseJointDef) as b2MouseJoint; } } private function onUp(e:MouseEvent):void { if (_mouseJoint) { _world.DestroyJoint(_mouseJoint); _mouseJoint = null; } } } }
39-42行:PhyOption,Floor,Wall都是自定义类,分别用来初始化b2world,创建地面,墙壁等。
52-66行:函数setConvexVertex创建圆内切多边形,box2d中只对凸多边形起作用,凹多边形是box2d无法处理的。
73-83行:创建3,4,5。。。7边形。奇怪的是,如果创建九边形,就会报错,即:循环i从3到8没问题,一旦循环到9就会报错:
TypeError: Error #1010: 术语尚未定义,并且无任何属性。
at CustomBody/setConvexVertex()
at CustomBody/createBody()
at CustomBody/createBodies()
at CustomBody/init()
at CustomBody()
此处我用的flashDevelop创建的一个Flash IDE Project,用的是FlashCS4编译运行,不知道这个是不是一个bug呢?有遇到过此类问题的朋友还请不吝赐教。
97-109行:显示box2d的debug模式。
122行:寻找鼠标点击处的刚体。
125-131行:创建一个mouseJoint,用来拖动刚体。创建mouseJoint跟刚体一样,先要创建mouseJointDef的各个参数。
body1:值为_world.GetGroundBody(),_world.GetGroundBody()具体表示的是哪一个刚体,本人还未明白,看源代码注释不是很清楚,如果您明白还请不吝赐教啊!
body2:鼠标点击处的刚体。
maxForce:拖动刚体时铰链给刚体的最大力,box2d会根据这个力来计算刚体被拖动的最大速度及位移,使得刚体始终处于鼠标的控制之下,实际这里的拖动,并不像flash中拖动一个显示对象用startDrag()或者设置对象的坐标为鼠标的坐标,box2d中考虑了更多复杂的运动参数,有加速度,质量,动量,冲量等。
timeStep:box2d模拟屋里世界的时间片,一般取swf文件帧频的倒数。
target:目标位置,设置为鼠标位置。在EnterFrame事件中更新目标。
E-mail:给我发邮件
出处:http://ywxgod.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。