class AnimatorBecause not all models have the same amimator requirements, we build a class for customization by the programmer. See these URLs for more info:
class AnimatorCreate initial animator for the model, specifying default rate (fps) and multiStep. If multiStep, run the draw() and step() methods separately by draw() using requestAnimationFrame and step() using setTimeout.
constructor: (@model, @rate=30, @multiStep=false) -> @reset()Adjust animator. Call before model.start() in setup() to change default settings
setRate: (@rate, @multiStep=false) -> @resetTimes() # Change rate while running?start/stop model, often used for debugging and resetting model
start: ->
return unless @stopped # avoid multiple animates
@resetTimes()
@stopped = false
@animate()
stop: ->
@stopped = true
if @animHandle? then cancelAnimationFrame @animHandle
if @timeoutHandle? then clearTimeout @timeoutHandle
if @intervalHandle? then clearInterval @intervalHandle
@animHandle = @timerHandle = @intervalHandle = nullInternal utility: reset time instance variables
resetTimes: ->
@startMS = @now()
@startTick = @ticks
@startDraw = @drawsReset used by model.reset when resetting model.
reset: -> @stop(); @ticks = @draws = 0Two handlers used by animation loop
step: -> @ticks++; @model.stepAndEmit()
draw: -> @draws++; @model.draw()step and draw the model once, mainly debugging
once: -> @step(); @draw()Get current time, with high resolution timer if available
now: -> (performance ? Date).now()Time in ms since starting animator
ms: -> @now()-@startMSGet ticks/draws per second. They will differ if multiStep. The “if” is to avoid from ms=0
ticksPerSec: ->
if (dt = @ticks-@startTick) is 0 then 0 else Math.round dt*1000/@ms()
drawsPerSec: ->
if (dt = @draws-@startDraw) is 0 then 0 else Math.round dt*1000/@ms()Return a status string for debugging and logging performance
toString: ->
"ticks: #{@ticks}, draws: #{@draws}, rate: #{@rate}
tps/dps: #{@ticksPerSec()}/#{@drawsPerSec()}"Animation via setTimeout and requestAnimationFrame
animateSteps: =>
@step()
@timeoutHandle = setTimeout @animateSteps, 10 unless @stopped
animateDraws: =>
if @drawsPerSec() < @rate # throttle drawing to @rate
@step() unless @multiStep
@draw()
@animHandle = requestAnimationFrame @animateDraws unless @stopped
animate: ->
@animateSteps() if @multiStep
@animateDraws() # unless @isHeadless and @multiStep