Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Last active May 17, 2017 22:41
Show Gist options
  • Save JoshCheek/bb707eebbd6b3d97a2920961d2c5d2f7 to your computer and use it in GitHub Desktop.
Save JoshCheek/bb707eebbd6b3d97a2920961d2c5d2f7 to your computer and use it in GitHub Desktop.
Melancholy animation
# https://vimeo.com/217760201
# can't remember if this is the version from the video or not
# that one might've been simpler (w/o the lambdas)
require 'graphics'
class Smth < Graphics::Simulation
def initialize
super 1000, 600, 24
self.color.default_proc = -> h, k { k }
@num_orbiters = 200
@orbiters = @num_orbiters.times.map { rand_orbiter }
@wells = [
Well.new(x: rand(w), y: rand(h), strength: 3),
Well.new(x: rand(w), y: rand(h), strength: 2),
Well.new(x: rand(w), y: rand(h), strength: 3),
Well.new(x: rand(w), y: rand(h), strength: 1),
]
end
def draw(n)
clear :black
n % 20 == 0 and
@wells.each { |well| well.x, well.y = rand(w), rand(h) }
@orbiters.reject! &:dead?
@orbiters << rand_orbiter while @orbiters.length < @num_orbiters
segments = @orbiters.flat_map do |orbiter|
orbiter.next_xy
orbiter.apply_rand_accel
@wells.each do |well|
orbiter.apply_gravity(well)
end
orbiter.apply_velocity
orbiter.drawers_for self
end
segments.sort_by(&:first).each do |_lumin, drawer|
drawer.call
end
end
def rand_orbiter
color = [
rand(255),
rand(255),
rand(255),
]
Orbiter.new x: rand(w), y: rand(h), vx: rand*5, vy: rand*5, color: color, length: rand(50)
end
class Point
attr_accessor :x, :y
def initialize(x:, y:)
self.x = x
self.y = y
end
end
class Well < Point
attr_accessor :strength
def initialize(strength:, **attrs)
super **attrs
self.strength = strength
end
end
class Orbiter < Point
attr_accessor :vx, :vy, :color, :locations, :length
def initialize(vx:, vy:, color:, length:, **attrs)
super **attrs
self.vx = vx
self.vy = vy
self.color = color
self.locations = []
self.length = length
end
def drawers_for(canvas)
locations.each_cons(2).with_index(1).map do |((x1, y1), (x2, y2)), i|
r, g, b = color
percent = i.to_f / locations.length
r *= percent
g *= percent
b *= percent
segment_color = [r, g, b]
drawer = lambda do
canvas.line x1, y1, x2, y2, segment_color
canvas.line x1+1, y1, x2+1, y2, segment_color
canvas.line x1, y1+1, x2, y2+1, segment_color
end
# http://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color
lumin = 0.2126*r + 0.7152*g + 0.0722+b
[lumin, drawer]
end
end
def next_xy
locations << [x, y]
end
def dead?
locations.length > length
end
def apply_gravity(well)
∆x = x - well.x
∆y = y - well.y
dist = Math.sqrt ∆x**2 + ∆y**2
self.vx -= (∆x/dist)*well.strength
self.vy -= (∆y/dist)*well.strength
end
def apply_rand_accel
self.vx += (rand-0.5)
self.vy += (rand-0.5)
end
def apply_velocity
self.x += vx
self.y += vy
end
end
end
Smth.new.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment