mobile.lua 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. local controllers = require 'app/controllers'
  2. local vec3 = require('cpml').vec3
  3. local mat4 = require('cpml').mat4
  4. local mobile = {}
  5. function mobile:init()
  6. self.isEntered = false
  7. self.position = { 0, 11.8, 0 }
  8. self.size = 1
  9. self.rotateSpeed = .5
  10. self.angle = 3 * math.pi / 180
  11. self.model = lovr.graphics.newModel('art/mobile.obj')
  12. self.model:setMaterial(lovr.graphics.newMaterial('art/mobile_DIFF.png'))
  13. self.toys = {
  14. submarine = {
  15. scale = .5,
  16. position = { 0, 0, 0 },
  17. wonPosition = { -.75, .6, 2.2 },
  18. stringLength = 10,
  19. isEntered = false,
  20. angle = 0,
  21. angleNudge = -.59,
  22. model = lovr.graphics.newModel('art/mobile_submarine.obj'),
  23. color = { 200, 0, 0 }
  24. },
  25. plane = {
  26. scale = .5,
  27. position = { 0, self.position[2], 0 },
  28. wonPosition = { 0, .6, 2.2 },
  29. stringLength = 9.5,
  30. isEntered = false,
  31. angle = 0,
  32. angleNudge = .15,
  33. model = lovr.graphics.newModel('art/mobile_plane.obj'),
  34. color = { 200, 200, 0 }
  35. },
  36. balloon = {
  37. scale = .5,
  38. position = { 0, self.position[2], 0 },
  39. wonPosition = { .75, .6, 2.2 },
  40. stringLength = 9.8,
  41. isEntered = false,
  42. angle = 0,
  43. angleNudge = .25,
  44. model = lovr.graphics.newModel('art/mobile_balloon.obj'),
  45. color = { 0, 200, 200 }
  46. }
  47. }
  48. self.numToys = _.count(self.toys)
  49. self.toySize = .38 -- hitbox, in meters
  50. self.toyTranslateZ = .6
  51. self.toyRotate = 2 * math.pi / self.numToys
  52. _.each(self.toys, function(toy)
  53. toy.model:setMaterial(lovr.graphics.newMaterial('art/mobile_DIFF.png'))
  54. end)
  55. end
  56. function mobile:update(dt)
  57. self.angle = self.angle + dt * self.rotateSpeed
  58. self:handleToyInput(dt)
  59. local toyRotate = self.toyRotate
  60. _.each(self.toys, function(toy)
  61. -- Translate to parent, rotate according to mobile angle
  62. local m = mat4.identity()
  63. m:translate(m, vec3(unpack(self.position)))
  64. m:rotate(m, self.angle, vec3(0, 1, 0))
  65. -- Rotate so they are spread out evenly
  66. m:rotate(m, toyRotate + toy.angleNudge, vec3(0, 1, 0))
  67. -- Move down based on string length, shoot outwards a bit
  68. m:translate(m, vec3(0, -toy.stringLength, self.toyTranslateZ))
  69. toy.position = { m[13], m[14], m[15] }
  70. toyRotate = toyRotate + self.toyRotate
  71. end)
  72. end
  73. function mobile:draw()
  74. local x, y, z = unpack(self.position)
  75. lovr.graphics.setColor(1, 1, 1)
  76. self.model:draw(x, y, z, self.size * .01, self.angle, 0, 1, 0)
  77. self:drawToys()
  78. end
  79. function mobile:drawToys()
  80. _.each(self.toys, function(toy)
  81. local x, y, z = unpack(toy.position)
  82. lovr.graphics.setColor(unpack(toy.color))
  83. lovr.graphics.setColor(1, 1, 1)
  84. toy.model:draw(x, y, z, toy.scale * .01, toy.angle, 0, 1, 0)
  85. end)
  86. end
  87. function mobile.controllerInRange(basePos, size)
  88. local controller = controllers.list[1]
  89. if controller then
  90. local pos = vec3(controller:getPosition())
  91. local center = vec3(unpack(basePos))
  92. local distance = pos:dist(center)
  93. local radius = size
  94. return distance < radius and true or false
  95. end
  96. end
  97. function mobile:handleToyInput(dt)
  98. local controller = controllers.list[1]
  99. if not controller then return end
  100. local activeToy = nil
  101. _.each(self.toys, function(toy)
  102. local wasEntered = toy.isEntered
  103. toy.isEntered = self.controllerInRange(toy.position, self.toySize)
  104. if toy.isEntered then
  105. toy.scale = _.lerp(toy.scale, .625, 8 * dt)
  106. toy.angle = toy.angle + dt
  107. activeToy = toy
  108. else
  109. toy.scale = _.lerp(toy.scale, .5, 8 * dt)
  110. toy.angle = toy.angle + dt / 2
  111. end
  112. if wasEntered ~= toy.isEntered then
  113. controller:vibrate(.0035)
  114. end
  115. end)
  116. self.isEntered = activeToy ~= nil
  117. self.rotateSpeed = _.lerp(self.rotateSpeed, self.isEntered and 0 or .5, 4 * dt)
  118. end
  119. return mobile