|
@@ -1,41 +1,54 @@
|
|
--- Saloon doors attached with hinge joint to frame, and with distance joint to each other
|
|
|
|
|
|
+-- Physics construct of saloon doors using the motorized hinge joint
|
|
|
|
|
|
local world
|
|
local world
|
|
-local door1, door2
|
|
|
|
|
|
+local doorR, doorL
|
|
|
|
+local passenger
|
|
|
|
|
|
function lovr.load()
|
|
function lovr.load()
|
|
world = lovr.physics.newWorld(0, -9.8, 0, false)
|
|
world = lovr.physics.newWorld(0, -9.8, 0, false)
|
|
-- a static geometry that functions as door frame
|
|
-- a static geometry that functions as door frame
|
|
- local frame = world:newBoxCollider(vec3(0, -0.1, -1), vec3(2.2, 0.05, 0.2))
|
|
|
|
- frame:setKinematic(true)
|
|
|
|
- door1 = world:newBoxCollider(vec3( 0.55, 0.5, -1), vec3(1, 1, 0.2))
|
|
|
|
- door2 = world:newBoxCollider(vec3(-0.55, 0.5, -1), vec3(1, 1, 0.2))
|
|
|
|
- door1:setAngularDamping(0.01)
|
|
|
|
- door2:setAngularDamping(0.01)
|
|
|
|
- -- attach doors to frame, with hinges being oriented vertically (up vector is 0,1,0)
|
|
|
|
- lovr.physics.newHingeJoint(frame, door1, vec3( 1, 0, -1), vec3(0,1,0))
|
|
|
|
- lovr.physics.newHingeJoint(frame, door2, vec3(-1, 0, -1), vec3(0,1,0))
|
|
|
|
- -- model door springiness by attaching loose distance joint between two doors
|
|
|
|
- local joint = lovr.physics.newDistanceJoint(door1, door2, vec3(door1:getPosition()), vec3(door2:getPosition()))
|
|
|
|
- joint:setTightness(0.2)
|
|
|
|
- joint:setResponseTime(10)
|
|
|
|
- lovr.graphics.setBackgroundColor(0.1, 0.1, 0.1)
|
|
|
|
|
|
+ doorR = world:newBoxCollider(vec3( 0.55, 0.5, -1), vec3(1, 1, 0.2))
|
|
|
|
+ doorL = world:newBoxCollider(vec3(-0.55, 0.5, -1), vec3(1, 1, 0.2))
|
|
|
|
+ -- attach doors with vertical hinges
|
|
|
|
+ local hingeR = lovr.physics.newHingeJoint(nil, doorR, vec3( 1, 0, -1), vec3(0,1,0))
|
|
|
|
+ local hingeL = lovr.physics.newHingeJoint(nil, doorL, vec3(-1, 0, -1), vec3(0,1,0))
|
|
|
|
+ -- set up motors to return the doors to their initial orientation
|
|
|
|
+ hingeR:setMotorMode('position')
|
|
|
|
+ hingeL:setMotorMode('position')
|
|
|
|
+ hingeR:setMotorTarget(0)
|
|
|
|
+ hingeL:setMotorTarget(0)
|
|
|
|
+ -- a controlled capsule that moves in and out pushing the door both ways
|
|
|
|
+ passenger = world:newCapsuleCollider(0, 0, 0, 0.4, 1)
|
|
|
|
+ passenger:getShape():setOffset(0, 0.5, 0, math.pi/2, 1, 0, 0)
|
|
|
|
+ passenger:setKinematic(true)
|
|
|
|
+ passenger:moveKinematic(vec3(0, 0, -4), nil, 3)
|
|
end
|
|
end
|
|
|
|
|
|
function lovr.draw(pass)
|
|
function lovr.draw(pass)
|
|
- for i, boxCollider in ipairs(world:getColliders()) do
|
|
|
|
|
|
+ for i, collider in ipairs(world:getColliders()) do
|
|
pass:setColor(i / 3, i / 3, i / 3)
|
|
pass:setColor(i / 3, i / 3, i / 3)
|
|
- local pose = mat4(boxCollider:getPose())
|
|
|
|
- local size = vec3(boxCollider:getShapes()[1]:getDimensions())
|
|
|
|
- pass:box(pose:scale(size))
|
|
|
|
|
|
+ local shape = collider:getShape()
|
|
|
|
+ local pose = mat4(collider:getPose()) * mat4(shape:getOffset())
|
|
|
|
+ local shape_type = shape:getType()
|
|
|
|
+ if shape_type == 'box' then
|
|
|
|
+ local size = vec3(collider:getShape():getDimensions())
|
|
|
|
+ pass:box(pose:scale(size))
|
|
|
|
+ elseif shape_type == 'capsule' then
|
|
|
|
+ local l, r = shape:getLength(), shape:getRadius()
|
|
|
|
+ pose:scale(r, r, l)
|
|
|
|
+ pass:capsule(pose, segments)
|
|
|
|
+ end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function lovr.update(dt)
|
|
function lovr.update(dt)
|
|
- world:update(dt)
|
|
|
|
- -- every few seconds simulate a push
|
|
|
|
- if lovr.timer.getTime() % 3 < dt then
|
|
|
|
- door1:applyForce(0, 0, -50)
|
|
|
|
- door2:applyForce(0, 0, -50)
|
|
|
|
|
|
+ local t = lovr.timer.getTime()
|
|
|
|
+ -- every 3 seconds change the moving direction of capsule collider
|
|
|
|
+ if t % 3 < dt then
|
|
|
|
+ local _, _, z = passenger:getPosition()
|
|
|
|
+ z = z > -1 and -4 or 2
|
|
|
|
+ -- moveKinematic is prefered over setPosition as it will correctly set the passenger's velocity
|
|
|
|
+ passenger:moveKinematic(vec3(0, 0, z), nil, 3)
|
|
end
|
|
end
|
|
|
|
+ world:update(dt)
|
|
end
|
|
end
|