Skip to content

Instantly share code, notes, and snippets.

@andynu
Created September 28, 2011 12:31
Show Gist options
  • Save andynu/1247815 to your computer and use it in GitHub Desktop.
Save andynu/1247815 to your computer and use it in GitHub Desktop.
a coffeescript clone of the processing's bouncybubbles example
#
# a coffeescript port of http://processing.org/learning/topics/bouncybubbles.html
#
ids = 0
spring = 0.02
gravity = 0.01
friction = -0.2
force_field = 1.5
balls = []
ground = true
reap_age = 10000
width = 10
height = 800
t = (new Date()).getTime()
p = null
random = (max) ->
Math.random() * max
class Petri
constructor: (div) ->
$(div).html("<canvas></canvas>")
p = new Processing($('#petri canvas')[0])
this.setup()
this.draw()
run: ->
setInterval(this.draw, 10)
setInterval(this.reap, 1000)
setInterval(this.poll_events, 1000)
setup: ->
#d "setup()"
p.size(width, height)
p.noStroke()
p.smooth()
poll_events: =>
$this = this
# random events of each type
$this.add_event({ time: (new Date()).getTime(), type: 0 })
$this.add_event({ time: (new Date()).getTime(), type: 1 })
$this.add_event({ time: (new Date()).getTime(), type: 2 })
# events from a service
#$.ajax("/events", {
# data: { t }
# success: (data, textStatus, xhr) ->
# for event in data
# $this.add_event(event)
#})
add_event: (event) ->
#d "add_event()"
ids += 1
i = ids
#balls.push(new Ball(random(width), random(height), random(40), i, balls, event))
balls.push(new Ball(5, 0, 10, i, balls, event))
#d balls[i]
reap: ->
#d "reap()"
#balls = []
for i in [0...balls.length]
ball = balls[i]
if ball.event
age = t - ball.event.time
if !ball.event || age > reap_age
balls.splice(i,1)
#if (t - balls[i].event.created_at) > 1000
# d i
# i -= 1
draw: ->
#d "draw()"
p.background(0)
for i in [0...balls.length]
balls[i].collide()
balls[i].move()
balls[i].display()
t = (new Date()).getTime()
class Ball
# (float, float, float, int, Ball[])
constructor: (@x, @y, @diameter, @id, @others, @event) ->
@color = "#00ff00"
@vx = 0
@vy = 0
collide: ->
for ball in balls
dx = ball.x - @x
dy = ball.y - @y
distance = Math.sqrt(dx*dx + dy*dy)
minDist = (ball.diameter/2 + @diameter/2) * force_field
if (distance < minDist)
angle = Math.atan2(dy, dx)
targetX = @x + Math.cos(angle) * minDist
targetY = @y + Math.sin(angle) * minDist
ax = (targetX - ball.x) * spring
ay = (targetY - ball.y) * spring
@vx -= ax
@vy -= ay
ball.vx += ax
ball.vy += ay
move: ->
@vy += gravity
@x += @vx
@y += @vy
if ground
if (@x + @diameter/2 > width)
@x = width - @diameter/2
@vx *= friction
else if (@x - @diameter/2 < 0)
@x = @diameter/2
@vx *= friction
if (@y + @diameter/2 > height)
@y = height - @diameter/2
@vy *= friction
else if (@y - @diameter/2 < 0)
@y = @diameter/2
@vy *= friction
display: ->
#d([ @x, @y ])
#p.fill(255, 204)
#p.fill(@color)
max = reap_age - 1000
age = (t - @event.time)
age = max if age > max
alpha = (max - age) / max * 255
#alpha = 255
#d alpha
switch @event.type
when 0
p.fill(255,0,0, alpha)
when 1
p.fill(0,255,0, alpha)
when 2
p.fill(0,0,255, alpha)
if age >= reap_age
p.fill(255,255,0)
#p.fill(255,255,0)
p.ellipse(@x, @y, @diameter, @diameter)
d = (obj) ->
console.debug(obj)
$ ->
petri = new Petri('#petri')
petri.run()
# vim: ft=coffee
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment