思路:在鼠标单击事件中判断鼠标是否在物体上单击了,如果是在某一个物体上单击,则得到鼠标单击的物体,并创建一个跟鼠标进行相连的 mouseJoint(b2MouseJoint),mouseJoint中的body1设为没有形状的刚体,即由 world.GetGroundBody()创建,body2设为单击处的物体。再世界更新过程中不断更新mouseJoint的目标为鼠标位置,则看上去物体就被鼠标拖动了~
具体代码:
package { import flash.display.Sprite; import flash.display.StageScaleMode; import flash.display.StageAlign; import flash.events.Event; import flash.events.MouseEvent; import flash.filters.DropShadowFilter; import flash.text.TextField; import Box2D.Collision.Shapes.*; import Box2D.Collision.*; import Box2D.Common.Math.*; import Box2D.Common.*; import Box2D.Dynamics.*; import Box2D.Dynamics.Joints.*; [SWF(backgroundColor="0x333333",width="800",height="600",frameRate="30")] public class MouseJointTest extends Sprite { private var world:b2World; private var physScale:Number = 30.0; private var m_timeStep:Number = 1.0 / physScale; private var m_iteration:int = 10; private var mouseVec:b2Vec2; private var mouseJoint:b2MouseJoint private var body:b2Body; private var bodyDef:b2BodyDef; private var shapeDef:b2PolygonDef; private var bodys:Array; private var numBody:int = 10; private var boxWidth:Number = 50; private var boxHeight:Number = 50; private var space:Number = 20; public function MouseJointTest() { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; init(); } private function init():void { addEventListener(Event.ENTER_FRAME, onFrame); stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown); stage.addEventListener(MouseEvent.MOUSE_UP, onUp); var txt:TextField = new TextField(); txt.x = 15; txt.y = 5; txt.selectable = false; txt.autoSize = "left"; txt.text = "Try to drag and try to throw the boxes!"; txt.textColor = 0xffff00; addChild(txt); bodys = new Array(); var worldAABB:b2AABB = new b2AABB(); worldAABB.lowerBound.Set( -100.0, -100.0); worldAABB.upperBound.Set(100.0, 100.0); var gravity:b2Vec2 = new b2Vec2(0.0, 20.0); var doSleep:Boolean = true; world = new b2World(worldAABB, gravity, doSleep); //create Ground createBox(400, 585, 400, 15,0xffff00, true); //create left and right ground createBox(5, 300, 5, 300, 0xffff00, true); createBox(795, 300, 5, 300, 0xffff00, true); for (var i:int = 0; i < numBody;i++ ) { var c:uint = 0xffffff * Math.random(); var body:b2Body = createBox(40+boxWidth/2 + i * (boxWidth + space), 0, boxWidth/2, boxHeight/2, c, false); bodys.push(body); } } private function onFrame(e:Event):void { world.Step(m_timeStep, m_iteration); if (mouseJoint) { var tempMouseX:Number = stage.mouseX / physScale; var tempMouseY:Number = stage.mouseY / physScale; var mouseVec:b2Vec2 = new b2Vec2(tempMouseX, tempMouseY); mouseJoint.SetTarget(mouseVec); } for (var b:b2Body = world.m_bodyList; b;b=b.m_next ) { if (b.m_userData is Sprite) { b.m_userData.x = b.GetPosition().x * physScale; b.m_userData.y = b.GetPosition().y * physScale; b.m_userData.rotation = b.GetAngle() * 180 / Math.PI; } } } private function onDown(e:MouseEvent):void { var body:b2Body = getBodyAtMouse(); if (body) { var mouseJointDef:b2MouseJointDef = new b2MouseJointDef(); mouseJointDef.body1 = world.GetGroundBody(); mouseJointDef.body2 = body; mouseJointDef.target.Set(mouseVec.x, mouseVec.y); mouseJointDef.maxForce = 4500 * body.m_mass; mouseJointDef.timeStep = m_timeStep; mouseJoint = world.CreateJoint(mouseJointDef) as b2MouseJoint; body.WakeUp(); } } private function onUp(e:MouseEvent):void { if (mouseJoint) { world.DestroyJoint(mouseJoint); mouseJoint = null; } } private function createBox(xpos:Number,ypos:Number,hw:Number,hh:Number,color:uint,isStatic:Boolean):b2Body { var shapeDef:b2PolygonDef = new b2PolygonDef(); shapeDef.SetAsBox(hw / physScale, hh / physScale); shapeDef.friction = 0.3; shapeDef.restitution = 0.4; shapeDef.density = isStatic ? 0.0 : 2.0; var bodyDef:b2BodyDef = new b2BodyDef(); bodyDef.userData = new Box(hw * 2, hh * 2, color); //var sp:Sprite = bodyDef.userData as Sprite; //sp.filters = isStatic?null:[new DropShadowFilter()]; bodyDef.position.Set(xpos / physScale, ypos / physScale); addChild(bodyDef.userData); var body:b2Body = world.CreateBody(bodyDef); body.CreateShape(shapeDef); body.SetMassFromShapes(); return body; } private function getBodyAtMouse(includeStatic:Boolean = false):b2Body { mouseVec = new b2Vec2(stage.mouseX / physScale, stage.mouseY / physScale); var aabb:b2AABB = new b2AABB(); aabb.lowerBound.Set(mouseVec.x - 0.001, mouseVec.y - 0.001); aabb.upperBound.Set(mouseVec.x + 0.001, mouseVec.y + 0.001); var maxCount:int = 10; var shapes:Array = new Array(maxCount); var count:int = world.Query(aabb, shapes, maxCount); var body:b2Body = null; for (var i:int = 0; i < count;i++ ) { if (!shapes[i].m_body.IsStatic()||includeStatic) { var tShape:b2Shape = shapes[i] as b2Shape; var inside:Boolean = tShape.TestPoint(tShape.m_body.GetXForm(), mouseVec); if (inside) { body = tShape.m_body; break; } } } return body; } } }
原文地址:http://space.flash8.net/space/?628770/viewspace-432264.html