Box2D joints: Distance Joint
- January 5, 2009 by Emanuele Feronato
- Filed under Actionscript 3, Box2D, Flash | 9 Comments
One of the most interesting Box2D features are joints.
Joints are used to constraint two bodies together in various ways and allow you to create very complex objects such as ragdolls and motors.
At the moment, Box2D features six different joint types: Distance, Gear, Mouse, Prismatic, Pulley and Revolute joint.
In this post, we’ll learn everything about Distance joints.
A distance joint constrains two points on two bodies to remain at a fixed distance from each other.
You can think about it as a massless, rigid rod.
In this example we are going to create a square and a circle with a distance joint connecting them, all in just four lines.
Here they are:
And this is the source:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | package { import flash.display.Sprite; import flash.events.Event; import Box2D.Dynamics.*; import Box2D.Collision.*; import Box2D.Collision.Shapes.*; import Box2D.Common.Math.*; import Box2D.Dynamics.Joints.*; import flash.events.MouseEvent; public class distance_joint extends Sprite { var mouseJoint:b2MouseJoint; var mousePVec:b2Vec2 = new b2Vec2(); var bd:b2BodyDef; var the_circle:b2CircleDef = new b2CircleDef(); var the_box:b2PolygonDef = new b2PolygonDef(); var the_joint:b2DistanceJointDef = new b2DistanceJointDef(); public function distance_joint() { // world setup 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,10.0); var doSleep:Boolean=true; m_world=new b2World(worldAABB,gravity,doSleep); // debug draw var m_sprite:Sprite; m_sprite = new Sprite(); addChild(m_sprite); var dbgDraw:b2DebugDraw = new b2DebugDraw(); var dbgSprite:Sprite = new Sprite(); m_sprite.addChild(dbgSprite); dbgDraw.m_sprite=m_sprite; dbgDraw.m_drawScale=30; dbgDraw.m_alpha = 1; dbgDraw.m_fillAlpha=0.5; dbgDraw.m_lineThickness=1; dbgDraw.m_drawFlags=b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit; m_world.SetDebugDraw(dbgDraw); // ground the_box.SetAsBox(9,0.5); the_box.density = 0; the_box.friction = 0.4; the_box.restitution = 0.1; bd = new b2BodyDef(); bd.position.Set(8.5, 13); var ground:b2Body = m_world.CreateBody(bd); ground.CreateShape(the_box); ground.SetMassFromShapes(); // circle the_circle.radius = 2; the_circle.density = 1.0; the_circle.friction = 0.4; the_circle.restitution = 0.3; bd = new b2BodyDef(); bd.position.Set(6, 2); var circle:b2Body = m_world.CreateBody(bd); circle.CreateShape(the_circle); circle.SetMassFromShapes(); // square the_box.SetAsBox(1.5,1.5); the_box.density = 1.0; the_box.friction = 0.4; the_box.restitution = 0.1; bd = new b2BodyDef(); bd.position.Set(2, 2); var box:b2Body = m_world.CreateBody(bd); box.CreateShape(the_box); box.SetMassFromShapes(); // joint the_joint.Initialize(circle, box, new b2Vec2(6,2),new b2Vec2(2,2)); the_joint.collideConnected = true; var joint:b2DistanceJoint = m_world.CreateJoint(the_joint)as b2DistanceJoint; // listeners stage.addEventListener(MouseEvent.MOUSE_DOWN, createMouse); stage.addEventListener(MouseEvent.MOUSE_UP, destroyMouse); addEventListener(Event.ENTER_FRAME, Update, false, 0, true); } public function createMouse(evt:MouseEvent):void { var body:b2Body=GetBodyAtMouse(); if (body) { var mouseJointDef:b2MouseJointDef=new b2MouseJointDef; mouseJointDef.body1=m_world.GetGroundBody(); mouseJointDef.body2=body; mouseJointDef.target.Set(mouseX/30, mouseY/30); mouseJointDef.maxForce=30000; mouseJointDef.timeStep=m_timeStep; mouseJoint=m_world.CreateJoint(mouseJointDef) as b2MouseJoint; } } public function destroyMouse(evt:MouseEvent):void { if (mouseJoint) { m_world.DestroyJoint(mouseJoint); mouseJoint=null; } } public function GetBodyAtMouse(includeStatic:Boolean=false):b2Body { var mouseXWorldPhys = (mouseX)/30; var mouseYWorldPhys = (mouseY)/30; mousePVec.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 k_maxCount:int=10; var shapes:Array = new Array(); var count:int=m_world.Query(aabb,shapes,k_maxCount); var body:b2Body=null; for (var i:int = 0; i < count; ++i) { if (shapes[i].GetBody().IsStatic()==false||includeStatic) { var tShape:b2Shape=shapes[i] as b2Shape; var inside:Boolean=tShape.TestPoint(tShape.GetBody().GetXForm(),mousePVec); if (inside) { body=tShape.GetBody(); break; } } } return body; } public function Update(e:Event):void { m_world.Step(m_timeStep, m_iterations); if (mouseJoint) { var mouseXWorldPhys=mouseX/30; var mouseYWorldPhys=mouseY/30; var p2:b2Vec2=new b2Vec2(mouseXWorldPhys,mouseYWorldPhys); mouseJoint.SetTarget(p2); } } public var m_world:b2World; public var m_iterations:int=10; public var m_timeStep:Number=1.0/30.0; } } |
Let’s see what’s interesting in this script:
Line 16: Declaring the distance joint variable called the_joint
Line 70: Initializing the joint. The Initialize() method accepts four arguments: the first body affected by the joint, the second one, the point in the first body where to attach the joint and the point in the second one.
A little note: these points are absolute… if you look at them you will notice they have the same coordinates as circle origin (line 55) and box origin (line 65)… so when you are about to create a joint, you must know where are your objects
Line 71: when collideConnected is set to true, the bodies tied by the joint can collide each other. Otherwise they will overlap.
Line 72: Now it’s time to add the joint to the world.
The rest of the script is the yada yada already explained in other Box2D tutorials.
They can be easily customized to meet the unique requirements of your project.
9 Responses
Leave a Reply
TUTORIAL SERIES:
- Una guida completa al gioco del poker online e una selezione dei migliori casino online.
- casino online
- migliori casino online
- BlackJack online
- casinò online

(8 votes, average: 4.75 out of 5)

Nice!!! I love this!!! This’ll help me make a physics game, that’s for sure…
One question: Is it possible to make a “Leash type joint? (Like two dogs leashed together, if one is stationary, it can move ANYWHERE in the circle of movement, not just the circumference)
You should probably try putting lots of little joints together to make a rope (search the box2d forums for more info and known problems)
Oh and btw this is only blank when I put it in the same folder with box2dfolder, how to fix…?
[...] introducing Distance Joints, it’s time to learn something about Revolute [...]
Can you do a tut on the joints used in the cranks and pulleys example given please
[...] bricks are hanging by distance joints attached to the body Ground, the paddle is fixed on the x axis by a prismatic joint attached also [...]
[...] used a distance joint, a revolute joint and a motor. The code does not need to be commented because there is nothing new, [...]
In the initialization of the joint, you can use GetPosition() of the two bodies to get their current position (in the form of a b2Vec2), so you dont have to go look for them.
Thanks for these tutorials!
[...] this example, we’ll use the same script we saw at Box2D joints: Distance Joint with some modifications and the concept saw at Creating a sling with Box2D using joints when we [...]