Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Last active February 16, 2017 04:24
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 JoshCheek/445fb5cda04b579305c59350fe0c1ca7 to your computer and use it in GitHub Desktop.
Save JoshCheek/445fb5cda04b579305c59350fe0c1ca7 to your computer and use it in GitHub Desktop.
Writhing Electric Bezier
# Video @ https://twitter.com/josh_cheek/status/832083163220475905
# 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 Integer
def of(obj)
times.map { obj }
end
end
class WritingElectricBezier < Graphics::Simulation
def initialize
super 500, 500*9/16, 24
@derivations = 100 # in the calc sense
@length = 75 # how many points our line should have
@points = (@derivations + @length).times.map { rand_point }
color.default_proc = -> h, k { k } # so we don't have to rely on named colours
# Put white in there more times so since it has the most "electrifying" feel
@vibrant_colors = [:red, :green, :blue, :cyan, :magenta, :yellow, :black, *5.of(:white)]
end
def draw(iteration)
clear
# randomly swap out some of the points so the lines change across frames
rand(10).times do
idx = rand(@points.length)
@points[idx] = rand_point
end
# how many lines to draw
rand(8).times do |line_i|
# random distance along the bezier, leads to lines that are nearby but different
percentage = 0.5 + rand(-0.3..0.3)
# "derive" aka run out the iterations along the bezier curve
points = @derivations.times.reduce @points do |pts,*|
percentages_between pts, percentage
end
if line_i.zero?
# first line gets drawn thick and in one of the vibrant colors with
# a higher probability of being white
color = @vibrant_colors.sample
draw_lines_between points, color
next unless color == :white
draw_lines_between points.map { |x, y| [x-2, y] }, color
draw_lines_between points.map { |x, y| [x+1, y] }, color
draw_lines_between points.map { |x, y| [x, y-2] }, color
draw_lines_between points.map { |x, y| [x, y+1] }, color
else
# the rest of the lines are thinner and can appear anywhere on the color spectrum
draw_lines_between points, [rand(255), rand(255), rand(255)]
end
end
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(3*w)-w, rand(3*h)-h]
end
end
WritingElectricBezier.new.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment