• Jump To … +
    agentset.coffee animator.coffee color.coffee colormaps.coffee colormixin.coffee evented.coffee link.coffee links.coffee model.coffee patch.coffee patches.coffee shapes.coffee turtle.coffee turtles.coffee util.coffee
  • animator.coffee

  • ¶

    Animator

  • ¶

    Because not all models have the same amimator requirements, we build a class for customization by the programmer. See these URLs for more info:

    • JavaScript timers doc
    • Using timers & requestAnimationFrame together
    • John Resig on timers
    • jsFiddle setTimeout vs rAF
    • Timeout tutorial
    • Events and timing in depth
    class Animator
  • ¶

    Create 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 = null
  • ¶

    Internal utility: reset time instance variables

      resetTimes: ->
        @startMS = @now()
        @startTick = @ticks
        @startDraw = @draws
  • ¶

    Reset used by model.reset when resetting model.

      reset: -> @stop(); @ticks = @draws = 0
  • ¶

    Two 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()-@startMS
  • ¶

    Get 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