Here’s something I was playing with the last few days. It’s a locomotive demo using Revolute, Distance and Prismatic joints. The piston uses Prismatic, the wheels use Revolute, and the joints connecting the wheels and piston uses Distance. The only piece the gets any value to move is the piston. When the piston moves, it causes wheel number 3 to start rotating by the distance joint connecting them. Wheel 3 then rotates wheel 2 and wheel 4 with their connecting joints. When 2 rotates wheel 1 with their connecting joint. By increasing the pressure slider, the piston moves faster causing wheel 3 and the other wheels to move faster. You can slide the parameter “piston joint” to break the joint between the piston and wheel 3 causing them to slow down. Parameter “Joints 1_2, 2_3, and 3_4” breaks the joints between those wheels and they will slow down. Wheels 1, 2, and 3 have angularDamping, so they will slow down faster. Wheel 4 has no damping, so it will rotate for awhile.
PS. Run in landscape orientation.
viewer.mode=STANDARD
-- locomotive
function setup()
rectMode(CENTER)
parameter.integer("pressure",1,100,5)
parameter.boolean("piston joint",false)
parameter.boolean("joint1_2",false)
parameter.boolean("joint2_3",false)
parameter.boolean("joint3_4",false)
-- create wheels
w1=wheel(200,200,200,200,200,260)
w2=wheel(380,200,380,200,380,260)
w3=wheel(560,200,560,200,560,260)
w4=wheel(740,200,740,200,740,260)
createPiston()
createJoints()
end
function draw()
background(142, 95, 31)
fill(255)
text("Angular velocity (1) "..w1.wheel.angularVelocity//-1,WIDTH/2,HEIGHT-25)
text("Angular velocity (2) "..w2.wheel.angularVelocity//-1,WIDTH/2,HEIGHT-50)
text("Angular velocity (3) "..w3.wheel.angularVelocity//-1,WIDTH/2,HEIGHT-75)
text("Angular velocity (4) "..w4.wheel.angularVelocity//-1,WIDTH/2,HEIGHT-100)
w1:draw()
w2:draw()
w3:draw()
w4:draw()
drawPiston()
drawJoints()
if r1.linearVelocity.x>0 then
r1.linearVelocity=vec2(pressure*10,0)
else
r1.linearVelocity=vec2(pressure*-10,0)
end
if piston_joint and j5~=nil then
j5:destroy()
j5=nil
end
if joint1_2 and j61~=nil then
j61:destroy()
j61=nil
w1.wheel.angularDamping=1
end
if joint2_3 and j62~=nil then
j62:destroy()
j62=nil
w2.wheel.angularDamping=1
end
if joint3_4 and j63~=nil then
j63:destroy()
j63=nil
w3.wheel.angularDamping=1
end
end
function createPiston()
p1=physics.body(CIRCLE,0) -- anchor piston
p1.x=100
p1.y=350
p1.type=STATIC
r1=physics.body(CIRCLE,0) -- piston rect
r1.x=100
r1.y=350
end
function drawPiston()
if j5==nil then
return
end
pushStyle()
strokeWidth(8)
fill(255)
stroke(0)
rect(110,350,200,50) -- piston cylinder
fill(0)
rect(r1.x,r1.y,20,50) -- piston
strokeWidth(0)
rectMode(CORNER)
if pressure>0 then
if r1.linearVelocity.x>0 then
fill(255,0,0,pressure*2+55)
rect(p1.x-84,r1.y-20,r1.x-24,40) -- red pressure
elseif r1.linearVelocity.x<0 then
fill(255,0,0,pressure*2+55)
rect(r1.x+8,r1.y-20,p1.x-r1.x+96,40) -- red pressure
end
end
popStyle()
end
function drawJoints()
pushStyle()
stroke(172)
strokeWidth(4)
if j61~=nil then
line(j61.bodyA.x,j61.bodyA.y,j61.bodyB.x,j61.bodyB.y)
end
if j62~=nil then
line(j62.bodyA.x,j62.bodyA.y,j62.bodyB.x,j62.bodyB.y)
end
if j63~=nil then
line(j63.bodyA.x,j63.bodyA.y,j63.bodyB.x,j63.bodyB.y)
end
if j5~=nil then
line(j5.bodyA.x,j5.bodyA.y,j5.bodyB.x,j5.bodyB.y)
end
popStyle()
end
function createJoints()
j31=physics.joint(REVOLUTE,w1.anchor1,w1.wheel,vec2(w1.anchor1.x,w1.anchor1.y))
j32=physics.joint(REVOLUTE,w2.anchor1,w2.wheel,vec2(w2.anchor1.x,w2.anchor1.y))
j33=physics.joint(REVOLUTE,w3.anchor1,w3.wheel,vec2(w3.anchor1.x,w3.anchor1.y))
j34=physics.joint(REVOLUTE,w4.anchor1,w4.wheel,vec2(w4.anchor1.x,w4.anchor1.y))
j41=physics.joint(REVOLUTE,w1.wheel,w1.anchor2,vec2(w1.wheel.x,w1.wheel.y+60))
j42=physics.joint(REVOLUTE,w2.wheel,w2.anchor2,vec2(w2.wheel.x,w2.wheel.y+60))
j43=physics.joint(REVOLUTE,w3.wheel,w3.anchor2,vec2(w3.wheel.x,w3.wheel.y+60))
j44=physics.joint(REVOLUTE,w4.wheel,w4.anchor2,vec2(w4.wheel.x,w4.wheel.y+60))
j61=physics.joint(DISTANCE,w1.anchor2,w2.anchor2,
vec2(w1.anchor2.x,w1.anchor2.y),vec2(w2.anchor2.x,w2.anchor2.y))
j62=physics.joint(DISTANCE,w2.anchor2,w3.anchor2,
vec2(w2.anchor2.x,w2.anchor2.y),vec2(w3.anchor2.x,w3.anchor2.y))
j63=physics.joint(DISTANCE,w3.anchor2,w4.anchor2,
vec2(w3.anchor2.x,w3.anchor2.y),vec2(w4.anchor2.x,w4.anchor2.y))
j1=physics.joint(PRISMATIC,p1,r1,p1.position,vec2(1,0))
j5=physics.joint(DISTANCE,r1,w3.anchor2,r1.position,w3.anchor2.position)
end
wheel=class()
function wheel:init(a1x,a1y,wx,wy,a2x,a2y)
self.anchor1=physics.body(CIRCLE,0)
self.anchor1.x=a1x
self.anchor1.y=a1y
self.anchor1.type=STATIC
self.wheel=physics.body(CIRCLE,80)
self.wheel.x=wx
self.wheel.y=wy
self.anchor2=physics.body(CIRCLE,0)
self.anchor2.x=a2x
self.anchor2.y=a2y
end
function wheel:draw()
pushMatrix()
pushStyle()
stroke(255)
strokeWidth(6)
fill(46, 30, 29)
translate(self.anchor1.x,self.anchor1.y)
rotate(self.wheel.angle)
ellipse(0,0,self.wheel.radius*2) --large wheel
fill(255)
strokeWidth(3)
stroke(103, 66, 64)
for z=0,360,30 do
x=math.cos(math.rad(z))*72
y=math.sin(math.rad(z))*72
line(0,0,x,y)
end
ellipse(0,0,30) -- center circle
ellipse(0,60,20) -- outer circle
fill(0)
ellipse(0,0,10) -- small center circle
popStyle()
popMatrix()
end