starlings

// Class which represents a starling 
class Starling(x: Float, y: Float, vx: Float, vy: Float) { 
  val m = .1f 
  val v = .999f 
  val h = 6.f 
  val w = 3.f 
  val r = 50.f; 
  val g = 50.f; 
  val b = 50.f; 
 
  // draw the starling 
  def draw(pg: processing.core.PGraphics) { 
    var dx = 1.f 
    var dy = 0.f 
    val l = Math.sqrt(vx*vx + vy*vy).asInstanceOf[Float] 
    if (l > 0) { 
      dx = vx / l 
      dy = vy / l 
    } 
 
    pg.noStroke() 
    pg.fill(r,g,b) 
    pg.beginShape(processing.core.PConstants.TRIANGLES) 
    pg.vertex(x+dx*h,y+dy*h) 
    pg.vertex(x-dy*w,y+dx*w) 
    pg.vertex(x+dy*w,y-dx*w) 
    pg.endShape() 
  } 
 
  // move the starling towards the point (mx,my) 
  def moveTowards(mx: Float, my: Float): Starling = { 
    var dx = mx - x 
    var dy = my - y 
    val l = Math.sqrt(dx*dx + dy*dy).asInstanceOf[Float] 
    if (l > 0) { 
      dx = m*dx/l 
      dy = m*dy/l 
    } 
    val nvx = v*(vx + dx) 
    val nvy = v*(vy + dy) 
    new Starling(x + nvx, y + nvy,  nvx, nvy) 
  } 
} 
 
// The starlings. Dummy initializer. Real initialization is in setup. 
var starlings = for (x <- List.range(1,1000)) yield new Starling(random(0,400),random(0,400), 0,0) 
 
// The background image 
val img = loadImage("http://farm3.static.flickr.com/2738/4087284997_4cca61cc94_o.jpg") 
 
size(400,400) 
 
// draw - called every frame 
def draw() { 
  image(img, 0, 0) 
  starlings = for (val x <- starlings) yield x.moveTowards(mouseX, mouseY) 
  starlings.foreach(b => b.draw(g)) 
}