Skip to content

Instantly share code, notes, and snippets.

@alexdantas
Created September 30, 2013 14:04
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 alexdantas/6764298 to your computer and use it in GitHub Desktop.
Save alexdantas/6764298 to your computer and use it in GitHub Desktop.
Implementation of The Chaos Game in Ruby
#!/usr/bin/env ruby
#
# A test on fractals, implementing The Chaos Game
# http://math.bu.edu/DYSYS/chaos-game/node1.html
#
# UGLY CODE IS UGLY
require 'sdl'
# Global SDL screen pointer
$screen = nil
$width = 500
$height = 500
$intro_string = <<END_OF_INTRO
Welcome to kure's first fractal test
Controls: a start stepping
s stop stepping
q increase speed of steps
w decrease speed of steps
f full speed of steps
o disable output (for speed boost!)
u, i single step
Enjoy!
END_OF_INTRO
class Point
attr_accessor :x, :y, :color
def initialize(x=0, y=0)
@x = x
@y = y
end
def set_color(r, g, b)
@color = $screen.format.map_rgb(r, g, b)
end
def draw
$screen.put_pixel(@x, @y, @color)
$screen.update_rect(0, 0, 0, 0)
end
def distance_to(point)
a = (@x - point.x).abs
b = (@y - point.y).abs
Math.sqrt(a**2 + b**2)
end
def inside_triangle?(v1, v2, v3)
def sign(p1, p2, p3)
return (p1.x - p3.x) * (p2.y - p3.y) -
(p2.x - p3.x) * (p1.y - p3.y)
end
test1 = sign(self, v1, v2) < 0
test2 = sign(self, v2, v3) < 0
test3 = sign(self, v3, v1) < 0
(test1 == test2) && (test2 == test3)
end
def move_halfway_to point
delta_x = ((@x - point.x).abs)/2
delta_y = ((@y - point.y).abs)/2
@x += delta_x if point.x > @x
@x -= delta_x if point.x <= @x
@y += delta_y if point.y > @y
@y -= delta_y if point.y <= @y
end
end
begin
SDL.init(SDL::INIT_EVERYTHING)
$screen = SDL::Screen.open($width, $height, 0, SDL::HWSURFACE)
SDL::WM.set_caption("kure fractal test", "minimized thingy")
redpoint = Point.new($width/2, $height/8)
redpoint.set_color(255, 0, 0)
redpoint.draw
greenpoint = Point.new($width/8, 7*$height/8)
greenpoint.set_color(0, 255, 0)
greenpoint.draw
bluepoint = Point.new(7 * $width/8, 7*$height/8)
bluepoint.set_color(0, 0, 255)
bluepoint.draw
# Random position inside triangle
begin
previous_point = Point.new((0..($width-1)).to_a.sample,
(0..($height-1)).to_a.sample)
end while not previous_point.inside_triangle?(redpoint,
greenpoint,
bluepoint)
# Starting with random color
color = (1..3).to_a.sample
case color
when 1
previous_point.set_color(255, 0, 0)
when 2
previous_point.set_color(0, 255, 0)
when 3
previous_point.set_color(0, 0, 255)
end
previous_point.draw
count = 0
keep_going = false
step_delay = 0.5
do_one_step = false
disable_output = false
puts $intro_string
terminated = false
step_delta = 0.01
while not terminated
while event = SDL::Event2.poll
case event
when SDL::Event2::Quit
terminated = true
when SDL::Event2::KeyDown
SDL::Key.scan
if SDL::Key.press? SDL::Key::A
keep_going = true
puts "Stepping..." if not disable_output
elsif SDL::Key.press? SDL::Key::S
keep_going = false
puts "Stopped" if not disable_output
elsif SDL::Key.press? SDL::Key::Q
step_delta = 0.1
step_delta = 0.001 if step_delay < 0.02
step_delay -= step_delta
step_delay = 0 if step_delay < 0
puts "New delay: #{step_delay} miliseconds" if not disable_output
elsif SDL::Key.press? SDL::Key::W
step_delta = 0.1
step_delay += step_delta if step_delay < 1
puts "New delay: #{step_delay} miliseconds" if not disable_output
elsif SDL::Key.press? SDL::Key::F
step_delay = 0
puts "Full speed ahead!" if not disable_output
elsif SDL::Key.press? SDL::Key::O
if disable_output == false
disable_output = true
puts "Output: Disabled"
else
disable_output = false
puts "Output: Enabled"
end
elsif (SDL::Key.press? SDL::Key::U) or
(SDL::Key.press? SDL::Key::I)
one_step = true
end
end
end
if one_step or keep_going
count += 1
puts "Iteration #{count}" if not disable_output
target_point = nil
newpoint = Point.new(previous_point.x, previous_point.y)
# Randomly selecting a color and setting it's primary
# point as the target to move.
color = (1..3).to_a.sample
case color
when 1
newpoint.set_color(255, 0, 0)
target_point = redpoint
when 2
newpoint.set_color(0, 255, 0)
target_point = greenpoint
when 3
newpoint.set_color(0, 0, 255)
target_point = bluepoint
end
newpoint.move_halfway_to target_point
newpoint.draw
previous_point = newpoint
# sleep step_delay if not one_step
one_step = false
end
sleep 0.05
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment