Particles in a gravitational field, randomly inverting charge to create interesting behaviors. Uses sketch.js to manage the 2d context and power animation.
A Pen by Justin Windle on CodePen.
Particles in a gravitational field, randomly inverting charge to create interesting behaviors. Uses sketch.js to manage the 2d context and power animation.
A Pen by Justin Windle on CodePen.
NUM_PARTICLES = 250 | |
TAIL_LENGTH = 12 | |
MAX_FORCE = 8 | |
FRICTION = 0.75 | |
GRAVITY = 9.81 | |
COLORS = [ | |
'#FF4746' | |
'#E8DA5E' | |
'#92B55F' | |
'#487D76' | |
] | |
class Particle | |
constructor: ( @x = 0.0, @y = 0.0, @mass = 1.0 ) -> | |
@tail = [] | |
@radius = @mass * 0.15 | |
@charge = random [ -1, 1 ] | |
@color = random COLORS | |
@fx = @fy = 0.0 | |
@vx = @vy = 0.0 | |
Sketch.create | |
particles: [] | |
setup: -> | |
for i in [0..NUM_PARTICLES] by 1 | |
x = random @width | |
y = random @height | |
m = random 0.5, 8.0 | |
@particles.push new Particle x, y, m | |
draw: -> | |
@lineCap = @lineJoin = 'round' | |
for i in [0..NUM_PARTICLES] by 1 | |
a = @particles[i] | |
# invert charge | |
if random() < 0.08 then a.charge = -a.charge | |
for j in [i+1..NUM_PARTICLES] by 1 | |
b = @particles[j] | |
# delta vector | |
dx = b.x - a.x | |
dy = b.y - a.y | |
# distance | |
dst = sqrt dSq = ( dx * dx + dy * dy ) + 0.1 | |
rad = a.radius + b.radius | |
if dst >= rad | |
# derivative of unit length for normalisation | |
len = 1.0 / dst | |
fx = dx * len | |
fy = dy * len | |
# gravitational force | |
f = min MAX_FORCE, ( GRAVITY * a.mass * b.mass ) / dSq | |
a.fx += f * fx * b.charge | |
a.fy += f * fy * b.charge | |
b.fx += -f * fx * a.charge | |
b.fy += -f * fy * a.charge | |
# integrate | |
a.vx += a.fx | |
a.vy += a.fy | |
a.vx *= FRICTION | |
a.vy *= FRICTION | |
a.tail.unshift x: a.x, y: a.y | |
a.tail.pop() if a.tail.length > TAIL_LENGTH | |
a.x += a.vx | |
a.y += a.vy | |
# reset force | |
a.fx = a.fy = 0.0 | |
# wrap | |
if a.x > @width + a.radius | |
a.x = -a.radius | |
a.tail = [] | |
else if a.x < -a.radius | |
a.x = @width + a.radius | |
a.tail = [] | |
if a.y > @height + a.radius | |
a.y = -a.radius | |
a.tail = [] | |
else if a.y < -a.radius | |
a.y = @height + a.radius | |
a.tail = [] | |
# draw | |
@strokeStyle = a.color | |
@lineWidth = a.radius * 2.0 | |
@beginPath() | |
@moveTo a.x, a.y | |
@lineTo p.x, p.y for p in a.tail | |
@stroke() |
<script src="http://soulwire.github.io/sketch.js/js/sketch.min.js"></script> |
@import compass | |
html, body | |
background: #1b1b1b |