Skip to content

Instantly share code, notes, and snippets.

@transat
Created March 20, 2016 05:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save transat/0c241d6a6a5207173e96 to your computer and use it in GitHub Desktop.
Save transat/0c241d6a6a5207173e96 to your computer and use it in GitHub Desktop.
Gravitational Field

Gravitational Field

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.

License.

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment