Created
September 30, 2013 14:04
-
-
Save alexdantas/6764298 to your computer and use it in GitHub Desktop.
Implementation of The Chaos Game in Ruby
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
#!/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