Last active
September 8, 2017 20:10
-
-
Save JoshCheek/1e2824f1270da94fe50881d4f39ef98a to your computer and use it in GitHub Desktop.
Coffee and Cream
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Video: https://twitter.com/josh_cheek/status/832215561841033216 | |
# Related: https://gist.github.com/JoshCheek/445fb5cda04b579305c59350fe0c1ca7 | |
# | |
# You might need to already understand how bezier curves work to understand this. | |
# This one is probably a reasonable way to explore it: | |
# https://gist.github.com/JoshCheek/9139ff5f2764493a69675268e5e9556d | |
require "graphics" | |
class CoffeeAndCream < Graphics::Simulation | |
# I should soooo make one called "fruit flies ponder a pond where the bg is | |
# like [10, 21, 36], and there is a circle at the end of the bezier | |
CLEAR_COLOR = [36, 30, 10] | |
def initialize | |
super 800, 450, 24 | |
@points = 200.times.map { rand_point } | |
@delayed_draw = [] | |
color.default_proc = -> h, k { k } # so we don't have to rely on named colours | |
end | |
def draw(ticks) | |
# return if ticks % 2 == 0 # slow it down a bit | |
clear | |
# randomly swap out some of the points so the lines change across frames | |
rand(20).times do | |
idx = rand(@points.length) | |
@points[idx] = rand_point | |
end | |
end_clip = (@points.length*0.4).to_i | |
num_frames = @points.length-end_clip | |
color = [rand(255), rand(255), rand(255)] | |
color = [255, 255, 255] | |
if ticks % 40 == 1 | |
points = @points | |
num_frames.times do |i| | |
(i.zero? ? end_clip : 1).times do | |
points = percentages_between points, 0.5 | |
end | |
# since `points` changes across iterations | |
crnt_points = points | |
# place it backwards since each iteration we run it through another time | |
# each time through will cause it to lose one point, so by the time we | |
# get to the beginning, it's just 1 point long, then as it goes forwards | |
# it gets longer and longer | |
(@delayed_draw[num_frames-i] ||= []) << lambda do | |
# invert the percentage since we're drawing them backwards | |
crnt_clr = dim(color, 1-i.to_f/num_frames) | |
draw_lines_between crnt_points, crnt_clr | |
draw_lines_between crnt_points.map { |x, y| [x+1, y] }, crnt_clr | |
draw_lines_between crnt_points.map { |x, y| [x, y+1] }, crnt_clr | |
draw_lines_between crnt_points.map { |x, y| [x+2, y] }, crnt_clr | |
draw_lines_between crnt_points.map { |x, y| [x, y+2] }, crnt_clr | |
end | |
end | |
end | |
(@delayed_draw.shift||[]).each(&:call) | |
end | |
def white | |
@white ||= [255, 255, 255] | |
end | |
def dim((r, g, b), percent) | |
end_r, end_g, end_b = CLEAR_COLOR | |
[ r + (end_r-r)*percent, | |
g + (end_g-g)*percent, | |
b + (end_b-b)*percent, | |
] | |
end | |
def draw_lines_between(points, color) | |
points.each_cons 2 do |(x1, y1), (x2, y2)| | |
line x1, y1, x2, y2, color | |
end | |
end | |
# feels like if I think about calculus for a little bit, I might be able to | |
# come up with an equation for htis so that we don't have to repeatedly invoke it | |
def percentages_between(points, percent) | |
points.each_cons(2).map do |(x1, y1), (x2, y2)| | |
[x1+(x2-x1)*percent, y1+(y2-y1)*percent] | |
end | |
end | |
def rand_point | |
[rand(5*w)-2*w, rand(5*h)-2*h] | |
end | |
end | |
CoffeeAndCream.new.run |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment