anim.lua 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. --[[ Animation library.
  2. This is an animation library.
  3. @name anim
  4. @release 2010-02-26 version 1
  5. @usage <pre>test</pre>
  6. ]]
  7. local anim = {}
  8. anim.animation = class('goo animation', StatefulObject)
  9. anim.style = require 'anim.style'
  10. anim.list = {}
  11. anim.lastTime = 0
  12. function anim:new(...)
  13. return self.animation:new(...)
  14. end
  15. --[[ Updates all animations, use inside love.update().
  16. @param dt delta time
  17. ]]
  18. function anim:update(dt)
  19. for k,v in pairs(self.list) do
  20. v:update(dt)
  21. end
  22. end
  23. function anim.animation:initialize(arg)
  24. super.initialize(self)
  25. table.insert(anim.list,self)
  26. self.table = arg.table or {}
  27. self.key = arg.key
  28. self.start = arg.start or self.table[self.key]
  29. self.finish = arg.finish or self.table[self.key]
  30. self.time = arg.time or 1
  31. self.delay = arg.delay or 0
  32. self.relative = arg.relative or false
  33. self.current = self.start
  34. self.startTime = nil
  35. self.style = anim.style[arg.style] or anim.style.linear
  36. self.styleargs = arg.styleargs or {}
  37. self:gotoState('pause')
  38. end
  39. function anim.animation:update(dt)
  40. end
  41. function anim.animation:getState()
  42. return self.state.name
  43. end
  44. --[[ Reverse the animation instance.
  45. <br/> Reverses the animation, going from finish to start.
  46. @name anim:reverse
  47. ]]
  48. function anim.animation:reverse()
  49. if self.start then
  50. self.start, self.finish = self.finish, self.start
  51. else
  52. local _tmp = self.table[self.key]
  53. self.table[self.key] = self.finish
  54. self.finish = _tmp
  55. end
  56. end
  57. -- PLAY STATE
  58. local play = anim.animation:addState('play')
  59. function play:enterState()
  60. if not self.startTime then
  61. self:startAnim()
  62. else
  63. self.playTime = love.timer.getMicroTime()
  64. self.startTime = self.startTime + (self.playTime-self.pauseTime)
  65. end
  66. end
  67. function play:startAnim()
  68. self.startTime = love.timer.getMicroTime()
  69. if not self.start then
  70. self.start = self.table[self.key]
  71. end
  72. if self.relative then
  73. self.start = self.table[self.key]
  74. self.finish = self.table[self.key] + self.finish
  75. end
  76. end
  77. function play:update(dt)
  78. local _timeElapsed = love.timer.getMicroTime() - self.startTime
  79. if _timeElapsed < self.time then
  80. self.current = self.style( _timeElapsed, self.start, self.finish - self.start, self.time, unpack(self.styleargs) )
  81. self.table[self.key] = self.current
  82. else
  83. self:gotoState('finished')
  84. end
  85. end
  86. --[[ Plays or resumes the animation instance.
  87. @name anim:play
  88. @usage <pre class="example">
  89. new_anim = anim:new{}
  90. new_anim:play()
  91. </pre>
  92. ]]
  93. function anim.animation:play()
  94. self:gotoState('delay')
  95. end
  96. -- DELAY STATE
  97. local delay = anim.animation:addState('delay')
  98. function delay:enterState()
  99. if self.delay and self.delay > 0 then
  100. self.startDelay = love.timer.getMicroTime()
  101. else
  102. self:gotoState('play')
  103. end
  104. end
  105. function delay:update(dt)
  106. local _delayElapsed = love.timer.getMicroTime() - self.startDelay
  107. if self.delay and _delayElapsed > self.delay then
  108. self:gotoState('play')
  109. end
  110. end
  111. -- PAUSE STATE
  112. local pause = anim.animation:addState('pause')
  113. function pause:enterState()
  114. self.pauseTime = love.timer.getMicroTime()
  115. end
  116. --[[ Pause the animation instance.
  117. @name anim:pause
  118. ]]
  119. function anim.animation:pause()
  120. self:gotoState('pause')
  121. end
  122. -- FINISHED STATE
  123. local finished = anim.animation:addState('finished')
  124. function finished:enterState()
  125. self.startTime = nil
  126. self.table[self.key] = self.finish
  127. if self.onFinish then self:onFinish() end
  128. if self.parentChain then self.parentChain:animFinished() end
  129. if self.parentGroup then self.parentGroup:animFinished() end
  130. end
  131. --[[ Finishes the animation instance, going instantly to the finish value.
  132. @name anim:finish
  133. ]]
  134. function anim.animation:finish()
  135. self:gotoState('finished')
  136. end
  137. -- ANIMATION GROUP
  138. anim.group = class('goo animation group', StatefulObject)
  139. local group = anim.group
  140. function group:initialize(...)
  141. super.initialize(self)
  142. self.anims = {}
  143. self.count = 0
  144. self.state = 'pause'
  145. for k,v in ipairs(arg) do
  146. if type(v) == 'table' then
  147. if instanceOf(anim,v) or instanceOf(group, v) then
  148. table.insert(self.anims, v)
  149. v.parentGroup = self
  150. end
  151. end
  152. end
  153. end
  154. function group:play()
  155. self.count = 0
  156. self.state = 'play'
  157. for k,v in pairs(self.anims) do
  158. v:play()
  159. end
  160. end
  161. function group:pause()
  162. self.state = 'pause'
  163. for k,v in pairs(self.anims) do
  164. v:pause()
  165. end
  166. end
  167. function group:reverse()
  168. for k,v in pairs(self.anims) do
  169. v:reverse()
  170. end
  171. end
  172. function group:animFinished( anim )
  173. self.count = self.count + 1
  174. if self.count >= #self.anims then
  175. self:finished()
  176. end
  177. end
  178. function group:finished()
  179. self.state = 'finished'
  180. log.print(self)
  181. if self.onFinish then self:onFinish() end
  182. if self.parentChain then self.parentChain:animFinished() end
  183. if self.parentGroup then self.parentGroup:animFinished() end
  184. end
  185. function group:setTime(time)
  186. for k,v in pairs(self.anims) do
  187. v.time = time
  188. end
  189. end
  190. function group:getState()
  191. return self.state
  192. end
  193. -- ANIMATION CHAIN
  194. anim.chain = class('goo animation chain')
  195. local chain = anim.chain
  196. function chain:initialize(...)
  197. super.initialize(self)
  198. self.anims = {}
  199. self.pos = 1
  200. self.state = 'pause'
  201. for k,v in ipairs(arg) do
  202. if type(v) == 'table' then
  203. if instanceOf(anim.animation,v) or instanceOf(group,v) or instanceOf(chain,v) then
  204. table.insert(self.anims,v)
  205. v.parentChain = self
  206. end
  207. end
  208. end
  209. end
  210. function chain:play()
  211. self.state = 'play'
  212. self.anims[self.pos]:play()
  213. end
  214. function chain:pause()
  215. self.state = 'pause'
  216. self.anims[self.pos]:pause()
  217. end
  218. function chain:reverse()
  219. local _fin
  220. local _lastFin = {}
  221. for k,v in ipairs(self.anims) do
  222. if instanceOf(group,v) then
  223. for k2,v2 in ipairs(v.anims) do
  224. self:reverseB(_lastFin,v2)
  225. end
  226. else
  227. self:reverseB(_lastFin,v)
  228. end
  229. end
  230. --self:reverseorder( self.anims )
  231. end
  232. function chain:reverseB(lastFin,anim)
  233. if not anim.start then
  234. if not lastFin[anim.key] then
  235. lastFin[anim.key] = anim.table[anim.key]
  236. else
  237. local _tmp = anim.finish
  238. anim.finish = lastFin[anim.key]
  239. lastFin[anim.key] = _tmp
  240. end
  241. anim.table[anim.key] = lastFin[anim.key]
  242. else
  243. anim:reverse()
  244. end
  245. anim.table[anim.key] = anim.start
  246. end
  247. function chain:animFinished(anim)
  248. self.pos = self.pos + 1
  249. if self.pos > #self.anims then
  250. self:finished()
  251. else
  252. self:play()
  253. end
  254. end
  255. function chain:finished()
  256. self.state = 'finished'
  257. if self.onFinish then self:onFinish() end
  258. end
  259. function chain:getState()
  260. return self.state
  261. end
  262. function chain:reverseorder(t)
  263. local tn = #t
  264. local count = math.floor((tn/2)-1)
  265. for i=0,count do
  266. t[1+i], t[tn-i] = t[tn-i], t[1+i]
  267. end
  268. end
  269. function anim:moveTo( object, x, y, time, style, delay )
  270. local time = time or 1
  271. local xAnim = self:new{
  272. table = object,
  273. key = 'x',
  274. finish = x,
  275. time = time,
  276. style = style,
  277. delay = delay
  278. }
  279. local yAnim = self:new{
  280. table = object,
  281. key = 'y',
  282. finish = y,
  283. time = time,
  284. style = style,
  285. delay = delay
  286. }
  287. local group = self.group:new(xAnim,yAnim)
  288. group:play()
  289. return group
  290. end
  291. function anim:easy( table, key, start, finish, time, style )
  292. local _anim = self.animation:new{
  293. table = table,
  294. key = key,
  295. start = start,
  296. finish = finish,
  297. time = time,
  298. style = style
  299. }
  300. _anim:play()
  301. return _anim
  302. end
  303. return anim