Box2D joints: Distance Joint

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.

Download the source code.

Rate this post: 1 Star2 Stars3 Stars4 Stars5 Stars (4 votes, average: 4.5 out of 5)
Loading ... Loading ...
If you found this post useful, please consider a small donation.
» Flash Templates provided by Template Monster are pre-made web design products developed using Flash technology.
They can be easily customized to meet the unique requirements of your project.

8 Responses to “Box2D joints: Distance Joint”

  1. Tommy on January 6th, 2009 12:55 am

    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)

  2. Orion on January 6th, 2009 3:42 pm

    You should probably try putting lots of little joints together to make a rope (search the box2d forums for more info and known problems)

  3. Orion on January 6th, 2009 3:44 pm

    Oh and btw this is only blank when I put it in the same folder with box2dfolder, how to fix…?

  4. Colin Diam on January 29th, 2009 8:38 am

    Can you do a tut on the joints used in the cranks and pulleys example given please

  5. Simon ALtschuler on April 13th, 2009 9:41 pm

    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!

Leave a Reply




Trackbacks

  1. Box2D joints: Revolute Joint : Emanuele Feronato on January 13th, 2009 5:34 pm

    [...] introducing Distance Joints, it’s time to learn something about Revolute [...]

  2. Box2D breakout prototype : Emanuele Feronato on February 4th, 2009 2:27 pm

    [...] 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 [...]

  3. Creating a sling with Box2D using joints : Emanuele Feronato on February 7th, 2009 10:43 pm

    [...] used a distance joint, a revolute joint and a motor. The code does not need to be commented because there is nothing new, [...]

Posts