Do you like my tutorials?

Then consider supporting me on Ko-fi

Talking about Actionscript 3, Box2D and Flash.

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:

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.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.