Box2D joints: Prismatic Joints
Time to learn something about Box2D prismatic joints.
A prismatic joint provides one degree of freedom: translation along an axis fixed relative to the first body. Relative rotation is prevented.
In other words, prismatic joints can be used to represent pistons and other sliding objects.
In this tutorial I am going to show how to create a prismatic joint, and later I’ll show you some real-world examples.
The script is the one you can find at Box2D joints: Revolute Joint – Building motors with some modifications in order to create prismatic joints.
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 | 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 prismatic_joint extends Sprite { var mouseJoint:b2MouseJoint; var mousePVec:b2Vec2 = new b2Vec2(); var bd:b2BodyDef; var the_box:b2PolygonDef = new b2PolygonDef(); var the_prism_joint:b2PrismaticJointDef = new b2PrismaticJointDef(); public function prismatic_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); // box for the prismatic joint the_box.SetAsBox(0.5,0.5); the_box.density=0.01; the_box.friction=1; the_box.restitution=0.1; bd = new b2BodyDef(); bd.position.Set(8.5,5); var prism_box:b2Body=m_world.CreateBody(bd); prism_box.CreateShape(the_box); prism_box.SetMassFromShapes(); // prismatic joint the_prism_joint.Initialize(m_world.GetGroundBody(), prism_box, new b2Vec2(8.5,5),new b2Vec2(1,0)); the_prism_joint.lowerTranslation=-6; the_prism_joint.upperTranslation=6 the_prism_joint.enableLimit=true; the_prism_joint.maxMotorForce=100; the_prism_joint.motorSpeed=4.0; the_prism_joint.enableMotor=true; var joint_added:b2PrismaticJoint=m_world.CreateJoint(the_prism_joint) as b2PrismaticJoint; // 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; } } |
Line 15: Declaring the_prism_joint variable, b2PrismaticJointDef type. This is how I define prismatic joints.
Line 49: Initializing the prismatic joint. This is the most difficult and unclear part of the process. The first two parameters represent the objects tied by the joint, the third one is the point where to tie the joint and the fourth is a vector representing the movement allowed. In this case, being an horizontal vector, the movement allowed is horizontal
Notice about this 4th parameter that values inside b2Vec2() cannot be greater than 1 or you may experience strange results.
All in all, there is no need to write (100,0) to represent an horizontal vector, when you can just use (1,0)
Lines 50-51: upperTranslation and lowerTranslation represent the upper and lower translation limits, in meters. To avoid strange results, try to keep
lowerTranslation <= 0 <= upperTranslation
Line 52: Enabling the limits for upper and lower translations. If you don't set enableLimit to true, limits won't be considered.
Lines 53-55: Adding a simple motor. For a brief introduction about motors, refer to Box2D joints: Revolute Joint - Building motors.
Line 56: Adding the joint.
And this is the result. Try to drag the box
And this is the source code ready to be downloaded.
They can be easily customized to meet the unique requirements of your project.















(9 votes, average: 4.56 out of 5)









This post has 7 comments
Gawd
First! :D
Xavi
noooooooo
!first
:_(
RedRail
In unrelated news: ‘My works’ page is still empty. Seems like a good place to showcase your games(I don’t see them listed anywhere else on the site).
Now on topic, I’m sure those will be usefull when I’ll finally start makeing something box2d
Ben
Is there a way to have it “spring” back with force instead of just a constant speed? Would that be the motor settings?
LunaDrift
Enjoyed reading your blog in general… I forget what bought me here in the first place… searching for something or other.
Best of luck with your games :)
Box2D breakout prototype : Emanuele Feronato
[...] are hanging by distance joints attached to the body Ground, the paddle is fixed on the x axis by a prismatic joint attached also to the [...]
Dinkyfish
Just wanted to stop by and say a massive thank you for all your tutorials. You’ve clearly put a huge amount of work into them and they’ve helped me out on many occasions. Keep up the good work!