Box2D joints: Distance Jointby Emanuele Feronato
Box2D中的关节有6种类型:
1.距离关节
距离关节是最简单的关节之一,它描述了两个物体上的两个点之间的距离应该是常量。当你指定一个距离关节时,两个物体必须已在应有的位置上。随后,你指定两个世界坐标中的锚点。第一个锚点连接到物体 1,第二个锚点连接到物体 2。这些点隐含了距离约束的长度。
var jointDef:b2DistanceJointDef = new b2DistanceJointDef();
jointDef.Initialize(bA:b2Body, bB:b2Body, anchorA:b2Vec2, anchorB:b2Vec2);
jointDef.collideConnected = true;
2.旋转关节
3.移动关节
4.滑轮关节
5.齿轮关节
6.鼠标关节
这节研究学习下距离关节。我们可以把距离关节看成是一个无质量的刚性棒。
package { import Box2D.Collision.b2AABB; import Box2D.Collision.Shapes.b2CircleShape; import Box2D.Collision.Shapes.b2PolygonShape; import Box2D.Common.Math.b2Vec2; import Box2D.Collision.Shapes.b2Shape; import Box2D.Dynamics.b2DebugDraw; import Box2D.Dynamics.b2World; import Box2D.Dynamics.b2Body; import Box2D.Dynamics.b2BodyDef; import Box2D.Dynamics.b2FixtureDef; import Box2D.Dynamics.b2Fixture; import Box2D.Dynamics.Joints.b2DistanceJoint; import Box2D.Dynamics.Joints.b2DistanceJointDef; import Box2D.Dynamics.Joints.b2MouseJoint; import Box2D.Dynamics.Joints.b2MouseJointDef; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; /** * ... * @author Childhood */ public class Main extends Sprite { private var world:b2World; private var worldScale:uint = 30; private var mouseJoint:b2MouseJoint; private var mousePVec2:b2Vec2 = new b2Vec2(); private var mouseXWorldPhys:Number; //鼠标在物理世界中的x坐标 private var mouseYWorldPhys:Number; //鼠标在物理世界中的y坐标 public function Main():void { if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); getStarted(); } private function getStarted():void { //world setup world = new b2World(new b2Vec2(0, 10), true); //debugDraw debugDraw(); //addStuff addStuff(); addEventListener(Event.ENTER_FRAME, update, false, 0, true); stage.addEventListener(MouseEvent.MOUSE_DOWN, creatMouseJoint); stage.addEventListener(MouseEvent.MOUSE_UP, destroyMouseJoint); } private function creatMouseJoint(e:MouseEvent):void { var body:b2Body = GetBodyAtMouse(); if (body) { var mouseJointDef:b2MouseJointDef = new b2MouseJointDef(); mouseJointDef.bodyA = world.GetGroundBody(); mouseJointDef.bodyB = body; mouseJointDef.target.Set(mouseXWorldPhys, mouseYWorldPhys); mouseJointDef.maxForce = 100 * body.GetMass(); mouseJointDef.collideConnected = true; mouseJoint = world.CreateJoint(mouseJointDef) as b2MouseJoint; } } private function GetBodyAtMouse(includeStatic:Boolean = false):b2Body { mousePVec2.Set(mouseXWorldPhys, mouseYWorldPhys); var aabb:b2AABB = new b2AABB(); aabb.lowerBound.Set(mouseXWorldPhys - 0.001, mouseYWorldPhys - 0.001); aabb.upperBound.Set(mouseXWorldPhys + 0.001, mouseYWorldPhys + 0.001); var body:b2Body; function getBodyCallback(fixture:b2Fixture):Boolean { var shape:b2Shape = fixture.GetShape(); if (fixture.GetBody().GetType() != b2Body.b2_staticBody||includeStatic) { var inside:Boolean = shape.TestPoint(fixture.GetBody().GetTransform(), mousePVec2); if (inside) { body = fixture.GetBody(); return false; } } return true; } world.QueryAABB(getBodyCallback, aabb); return body; } private function destroyMouseJoint(e:MouseEvent):void { if (mouseJoint) { world.DestroyJoint(mouseJoint); mouseJoint = null; } } private function addStuff():void { //创建地板 var groundBodyDef:b2BodyDef = new b2BodyDef(); groundBodyDef.type = b2Body.b2_staticBody; groundBodyDef.position.Set(0, (stage.stageHeight-10)/ worldScale); var groundBody:b2Body = world.CreateBody(groundBodyDef); var groundShape:b2PolygonShape = new b2PolygonShape(); groundShape.SetAsBox(stage.stageWidth/worldScale, 10/worldScale); var groundFixtureDef:b2FixtureDef = new b2FixtureDef(); groundFixtureDef.shape = groundShape; var groundFixture:b2Fixture = new b2Fixture(); groundFixture = groundBody.CreateFixture(groundFixtureDef); //创建矩形 var squareBodyDef:b2BodyDef = new b2BodyDef(); squareBodyDef.type = b2Body.b2_dynamicBody; squareBodyDef.position.Set(100 / worldScale, 100 / worldScale); var squareBody:b2Body = world.CreateBody(squareBodyDef); var squareShape:b2PolygonShape = new b2PolygonShape(); squareShape.SetAsBox(50 / worldScale, 50 / worldScale); var squareFixtureDef:b2FixtureDef = new b2FixtureDef(); squareFixtureDef.shape = squareShape; squareFixtureDef.density = 1; squareFixtureDef.friction = 0.4; squareFixtureDef.restitution = 0.1; var squareFixture:b2Fixture = squareBody.CreateFixture(squareFixtureDef); //创建圆形 var circleBodyDef:b2BodyDef = new b2BodyDef(); circleBodyDef.type = b2Body.b2_dynamicBody; circleBodyDef.position.Set(210 / worldScale, 100 / worldScale); var circleBody:b2Body = world.CreateBody(circleBodyDef); var circleShape:b2CircleShape = new b2CircleShape(30 / worldScale); var circleFixtureDef:b2FixtureDef = new b2FixtureDef(); circleFixtureDef.shape = circleShape; circleFixtureDef.density = 1; circleFixtureDef.friction = 0.4; circleFixtureDef.restitution = 0.8; var circleFixture:b2Fixture = circleBody.CreateFixture(circleFixtureDef); //创建距离关节 var distanceJointDef:b2DistanceJointDef = new b2DistanceJointDef(); distanceJointDef.Initialize(circleBody, squareBody, new b2Vec2(210 / worldScale,100 / worldScale), new b2Vec2(100 / worldScale,100 / worldScale)); distanceJointDef.collideConnected = true; var distanceJoint:b2DistanceJoint = world.CreateJoint(distanceJointDef) as b2DistanceJoint; } private function update(e:Event):void { world.Step(1 / 30, 10, 10); world.DrawDebugData(); world.ClearForces(); updateMouseWorldPhy(); //更新鼠标在物理世界中的位置信息 if (mouseJoint) { var p2:b2Vec2 = new b2Vec2(mouseXWorldPhys, mouseYWorldPhys); mouseJoint.SetTarget(p2); } } private function updateMouseWorldPhy():void { mouseXWorldPhys = mouseX / worldScale; mouseYWorldPhys = mouseY / worldScale; } private function debugDraw():void { var debugDraw:b2DebugDraw = new b2DebugDraw(); var debugSprite:Sprite = new Sprite(); addChild(debugSprite); debugDraw.SetSprite(debugSprite); debugDraw.SetLineThickness(1.0); debugDraw.SetDrawScale(worldScale); debugDraw.SetFillAlpha(0.8); debugDraw.SetFlags(b2DebugDraw.e_jointBit | b2DebugDraw.e_shapeBit); world.SetDebugDraw(debugDraw); } } }
其实这篇代码中,也用到了鼠标关节。而距离关节的建立非常简单,集中在代码149-153行中。