Jump To …

circles_scene.js.coffee

@module scene Module for moving circles in a box

= require libs/raphael-min = require ./vec = require ./Math = require ./collisions = require ./Line = require ./Circle

NUM_GROUPED_CIRCLES = 4
NUM_FREE_CIRCLES    = 1
CIRCLE_RADIUS       = 20
CIRCLE_COLORS       = ['#00A308', '#FF0066', '#3366FF', '#CCCCCC', '#FFCCFF']
MAX_VELOCITY_X      = 200
MAX_VELOCITY_Y      = 50

scene = (opts) ->
  bw = opts.width
  bh = opts.height
  clearFunc = opts.clearFunc
  drawFunc = opts.drawFunc
  lastTime = 0
  circles = null
  walls = null
  ticks = 0
  animating = false
  changeY = false
  freeY   = false
  

setup

  setup = ->
    console.log "setting up objects"
    

Make walls = canvas border

    walls = [new Line(0, 0, 0, bh, {mass: Infinity}) # left
      ,new Line(bw, 0, 0, bh, {mass: Infinity}) # right
      ,new Line(0, 0, bw, 0, {mass: Infinity}) # bottom
      ,new Line(0, bh, bw, 0, {mass: Infinity}) # top
    ]
      
    circles = []
    cx = CIRCLE_RADIUS * 2
    cy = bh / 2
  

Make free circles

    for i in [0...NUM_FREE_CIRCLES]
      circles.push createFreeCircle(cx, cy, i)
      cx += CIRCLE_RADIUS * 3
      
    cx += CIRCLE_RADIUS * 2
  

Make fixed circles

    for i in [0...NUM_GROUPED_CIRCLES]
      circles.push new Circle(cx, cy, 0, {
        radius: CIRCLE_RADIUS,
        velocity: Vector.create([0, 0, 0])
        color: CIRCLE_COLORS[0]
      })
      cx += CIRCLE_RADIUS * 2 + 1

    console.log "Created circle " + c for c in circles
    drawScene()
    

Return a random circle color

  randomCircleColor = ->
    CIRCLE_COLORS[Math.getRandomInt(1, CIRCLE_COLORS.length)-1]
    

Return a y-value for a circle

  circleY = -> 
    if freeY then Math.getRandom(-MAX_VELOCITY_Y, MAX_VELOCITY_Y) else 0
      

Create and return a new (free) circle

  createFreeCircle = (x, y, i) ->
    velx = Math.getRandom(-MAX_VELOCITY_X, MAX_VELOCITY_X)
    new Circle(x, y, 0, {
      radius: CIRCLE_RADIUS
      velocity: Vector.create([velx, circleY(), 0])
      color: randomCircleColor()
    })
      

Assign new y-value to all circles

  updateCircleY = ->
    for c in circles
      vel = c.velocity
      c.velocity = $V([vel.e(1), circleY(), vel.e(3)])
    

Update number of balls on screen

  updateBallCount = (nballs) ->
    console.log "new ball count: " + nballs
    diff = nballs - circles.length
    if diff > 0

Add balls

      for i in [1..diff]
        circles.push createFreeCircle(Math.getRandom(0, bw), bh/2, i)
    else

remove balls

      circles.pop() for i in [1..(circles.length-nballs)]
      
    console.log "circles now: " + circles.length
    

toggle the animation on and off

  toggleAnimation = ->
    animating = !animating
    lastTime = 0
    tick()

toggle circles' y-freedom...only used to 'free' them right now

  toggleCirclesY = (checked) ->
    changeY = true
    freeY   = checked
      

draw all objects on the canvas

  drawScene = ->
    clearFunc.call() if clearFunc?

Draw circles

    drawFunc.call(this, c) for c in circles
    

animate all objects

  animate = ->

Pass latest timestep to the collision detection function

    timeNow = new Date().getTime()
    if lastTime != 0
      elapsed = timeNow - lastTime
      collisions.checkCollisions elapsed, circles, walls

change vertical velocity components if toggled

    if changeY
      updateCircleY() 
      changeY = false
      
    lastTime = timeNow

tick funtion

  tick = ->
    requestAnimFrame(tick) 
    drawScene()
    animate() if animating
    ticks += 1

Initialize

  setup()
  

Return public functions

  {toggleAnimation, toggleCirclesY, updateBallCount, randomCircleColor}

root = exports ? window
root.scene = scene