main.lua 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. --[[ A zipline made of
  2. Capsule is suspended from trolley using distance joint. Trolley is attached to hanger
  3. using slider joint. Beware that slider joint loses its accuracy/stability when attached
  4. objects are too far away. Increasing object mass of helps with stability. --]]
  5. local world
  6. function lovr.load()
  7. world = lovr.physics.newWorld(0, -3, 0, false)
  8. local hanger = world:newBoxCollider(vec3(1, 1.9, -1), vec3(0.1, 0.1, 0.3))
  9. hanger:setKinematic(true)
  10. local trolley = world:newBoxCollider(vec3(-1, 2, -1), vec3(0.2, 0.2, 0.5))
  11. trolley:setRestitution(0.7)
  12. -- calculate axis that passes through centers of hanger and trolley
  13. local sliderAxis = vec3(hanger:getPosition()) - vec3(trolley:getPosition())
  14. -- constraint the trolley so that it can only slide along specified axis without any rotation
  15. joint = lovr.physics.newSliderJoint(hanger, trolley, sliderAxis)
  16. -- hang a weight from trolley
  17. local weight = world:newCapsuleCollider(vec3(-1, 1.5, -1), 0.1, 0.4)
  18. weight:setOrientation(math.pi/2, 1,0,0)
  19. weight:setLinearDamping(0.005)
  20. weight:setAngularDamping(0.01)
  21. local joint = lovr.physics.newDistanceJoint(trolley, weight, vec3(trolley:getPosition()), vec3(weight:getPosition()) + vec3(0, 0.3, 0))
  22. joint:setResponseTime(10) -- make the hanging rope streachable
  23. lovr.graphics.setBackgroundColor(0.1, 0.1, 0.1)
  24. end
  25. function lovr.update(dt)
  26. world:update(1 / 72)
  27. end
  28. function lovr.draw()
  29. for i, collider in ipairs(world:getColliders()) do
  30. lovr.graphics.setColor(0.6, 0.6, 0.6)
  31. local shape = collider:getShapes()[1]
  32. local shapeType = shape:getType()
  33. local x,y,z, angle, ax,ay,az = collider:getPose()
  34. if shapeType == 'box' then
  35. local sx, sy, sz = shape:getDimensions()
  36. lovr.graphics.box('fill', x,y,z, sx,sy,sz, angle, ax,ay,az)
  37. elseif shapeType == 'capsule' then
  38. lovr.graphics.setColor(0.4, 0, 0)
  39. local l, r = shape:getLength(), shape:getRadius()
  40. local x,y,z, angle, ax,ay,az = collider:getPose()
  41. local m = mat4(x,y,z, 1,1,1, angle, ax,ay,az)
  42. lovr.graphics.cylinder(x,y,z, l, angle, ax,ay,az, r, r, false)
  43. lovr.graphics.sphere(vec3(m:mul(0, 0, l/2)), r)
  44. lovr.graphics.sphere(vec3(m:mul(0, 0, -l/2)), r)
  45. end
  46. end
  47. end
  48. function makeRope(origin, destination, thickness, elements)
  49. local length = (destination - origin):length()
  50. thickness = thickness or length / 100
  51. elements = elements or 30
  52. elementSize = length / elements
  53. local orientation = vec3(destination - origin):normalize()
  54. local first, last, prev
  55. for i = 1, elements do
  56. local position = vec3(origin):lerp(destination, (i - 0.5) / elements)
  57. local anchor = vec3(origin):lerp(destination, (i - 1.0) / elements)
  58. element = world:newBoxCollider(position, vec3(thickness, thickness, elementSize * 0.95))
  59. element:setRestitution(0.1)
  60. element:setGravityIgnored(true)
  61. element:setOrientation(quat(orientation))
  62. element:setLinearDamping(0.01)
  63. element:setAngularDamping(0.01)
  64. element:setMass(0.001)
  65. if prev then
  66. local joint = lovr.physics.newBallJoint(prev, element, anchor)
  67. joint:setResponseTime(10)
  68. joint:setTightness(1)
  69. else
  70. first = element
  71. end
  72. prev = element
  73. end
  74. last = prev
  75. return first, last
  76. end