Skip to content

Instantly share code, notes, and snippets.

@moumar
Created December 5, 2010 02:47
Show Gist options
  • Save moumar/728713 to your computer and use it in GitHub Desktop.
Save moumar/728713 to your computer and use it in GitHub Desktop.
#!/usr/bin/ruby
# inkscape -b '#ffffff' -e circles.png -w 3000 circles.svg
# gem install color-tools
require 'color'
# http://code.google.com/p/chipmunk-physics/
# svn checkout http://chipmunk-physics.googlecode.com/svn/trunk/ chipmunk-physics-read-only
# cmake -D BUILD_RUBY_EXT=ON .
# make && sudo make install
require 'chipmunk'
# gem install progressbar
require 'progressbar'
def random(from, to = nil)
if to
rand()*(to - from) + from
else
rand()*from
end
end
def hsl_to_html(h, s, l)
Color::HSL.new(h*3.6, s, l).html
end
class Circle
attr_reader :x, :y, :radius
class<<self
attr_reader :circles
def add_circle(c)
@circles << c
end
def clear_circles
@circles = []
end
def collide_any?(circle)
@circles.each do |c|
if c.collide?(circle)
return true
end
end
return false
end
end
def initialize(x, y, radius)
@x, @y, @radius = x, y, radius
end
def collide?(circle)
# compare the distance to combined radii
dx = circle.x - self.x
dy = circle.y - self.y
radii = self.radius + circle.radius
return dx*dx + dy*dy < radii*radii
end
end
NUM_CIRCLES = 1000
WIDTH = HEIGHT = 1000
MARGIN = 25
#COLORS_START = [0, 47, 25, 12, 60, 90]
COLORS_START = [0, 57, 22, 9]
pbar = ProgressBar.new("circles", NUM_CIRCLES*COLORS_START.size)
$circles = []
#color_start = COLORS_START.at(random(COLORS_START.size))
COLORS_START.each_with_index do |color_start, color_index|
Circle.clear_circles
translation = [(color_index%2)*WIDTH + MARGIN, (color_index/2)*HEIGHT + MARGIN]
while Circle.circles.size < NUM_CIRCLES
radius = random(5, 180)
x = random(WIDTH - MARGIN - 2*radius) + radius
y = random(HEIGHT - MARGIN - 2*radius) + radius
circle = Circle.new(x, y, radius)
next if Circle.collide_any?(circle)
Circle.add_circle(circle)
r = radius
circle = { 'x' => circle.x + translation[0],
'y' => circle.y + translation[1],
#'radius' => radius,
'circles' => []
}
while r > 1
color = hsl_to_html(random(0, 8) + color_start, random(90, 100), 50)
circle['circles'] << [r, color]
r -= random(1, 30)
end
$circles << circle
pbar.inc
end
end
File.open("circles.yaml", "w") { |f| f.puts({'width' => WIDTH*2 + MARGIN, 'height' => HEIGHT*2 + MARGIN, 'circles' => $circles }.to_yaml) }
#!/usr/bin/env ruby
require 'chipmunk'
require 'progressbar'
require 'yaml'
WIDTH = HEIGHT = 600
DT = 1.0/10.0
$space = CP::Space.new
#$space.damping = 1
#$space.gravity = CP::Vec2.new(0, 100)
class Circle
attr_reader :body, :radius
def initialize(x, y, circles)
@circles = circles
@radius = @circles.first[0] + @circles.first[0]*0.05
@body = CP::Body.new(0.01*@radius, 0.0001)
@body.p = CP::Vec2.new(x, y) # position
#@body.velocity = CP::Vec2.new(1.0, 2.0) # velocity
#@body.angle = (3*Math::PI/2.0) # angle in radians; faces towards top of screen
@shape = CP::Shape::Circle.new(@body, @radius, CP::Vec2.new(0.0, 0.0))
$space.add_body(@body)
$space.add_shape(@shape)
end
def x
@body.p.x
end
def y
@body.p.y
end
def to_svg
str = ""
#str << "<g>"
@circles.each do |c|
str << %|<circle cx="#{x}" cy="#{y}" r="#{c[0]}" fill="#{c[1]}"/>|
end
#str << "</g>"
str
end
end
$data = YAML::load_file("circles.yaml")
$circles = $data['circles'].collect do |c|
x = c['x'] + 1000
y = c['y'] + 1000
Circle.new(x, y, c['circles'])
end
=begin
cols = 10
$circles = (0...100).collect do |i|
Circle.new((i%cols)*20 + 100, (i/cols)*25 + 100)
end
=end
x = 500
y = 1500
circles = [
[ 50, '#ddd' ],
[ 35, '#aaa' ],
[ 22, '#222' ],
[ 15, '#fff' ],
[ 5, '#bbb' ]
]
shoot_ball = Circle.new(x, y, circles)
#shoot_ball.body.v = CP::Vec2.new(300, 0)
shoot_ball.body.apply_force(CP::Vec2.new(1000, 0), CP::Vec2.new(0, 0))
shoot_ball.body.m = 1
$circles << shoot_ball
x = 3500
y = 2500
shoot_ball = Circle.new(x, y, circles)
#shoot_ball.body.velocity = CP::Vec2.new(-300, 0)
shoot_ball.body.apply_force(CP::Vec2.new(-1000, 0), CP::Vec2.new(0, 0))
shoot_ball.body.m = 1
$circles << shoot_ball
NUM_FRAMES = 1000
pbar = ProgressBar.new('frame', NUM_FRAMES)
NUM_FRAMES.times do |frame_num|
$space.step(DT)
#next unless frame_num % 25 == 0
w = $data["width"]*2
h = $data["height"]*2
outfile = "tmp/circle_%05d.svg" % frame_num
f = File.open(outfile, "w")
f.puts <<EOF
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="#{w}" height="#{h}" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" fill="white" width="#{w}" height="#{h}" />
EOF
$circles.each do |circle|
f.puts circle.to_svg
end
f.puts "</svg>"
f.close
pbar.inc
end
#exit
#system("java -jar /usr/share/java/batik-1.7.jar -w 600 -d tmp/ tmp/*.svg") || exit!
#apt-get install libbatik-java
system("rasterizer -w 600 -d tmp/ tmp/*.svg") || exit!
#system("mencoder -o test.avi -ovc lavc -mf type=png:fps=25 mf://tmp/*.png") || exit!
system("ffmpeg -r 25 -i tmp/circle%05d.png -y -an test.avi") || exit!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment