# Sand Traveler
# After Jared Tarbell

# Description:
# Sand Traveler was a special commision for Sonar 2004, Barcelona.
# This one has been tweaked, half of the (non-running) code exorcised, 
# color palette broadened, and done in negative.

require 'ruby-processing'

class SandTraveler < Processing::App
  include Math
  attr_reader :num
  
  def setup
    $app = self
    @dx, @dy = 0, 0
    @num = 150
    $cities = []
    smooth
    reset_all
  end
  
  def draw
    $cities.each {|city| city.move }
  end
  
  def mouse_pressed
    reset_all
  end
  
  def reset_all
    @source_colors = [[rand(255), rand(255), rand(255), rand(30) + 45],[rand(255), rand(255), rand(255), rand(30) + 45]]
    background 0
    vt = 4.2
    vvt = 0.2
    ot = rand * PI * 2
    @num.times do |i|
      tinc = ot + (1.1 - i / @num) * 2 * i * (PI * 2) / @num
      vx, vy = vt * sin(tinc), vt * cos(tinc)
      $cities[i] = City.new(width/2+vx*2, height/2+vy*2, vx, vy, i)
      vvt -= 0.00033
      vt += vvt
    end
    $cities.each {|city| city.find_friend}
  end
  
  def some_color
    choice = @source_colors[rand(2)].dup
    choice.map! {|c| c + (rand * 120 - 60)}
    choice[3] = choice[3] * 0.7
    return choice
  end
end

class City
  include Math
  attr_reader :x, :y, :myc
  
  def initialize(dx, dy, vx, vy, idx)
    @x, @y = dx, dy
    @vx, @vy = vx, vy
    @idx = idx
    @myc = $app.some_color
    @num_travelers = 13
  end
  
  def move
    if (@vx.abs + @vy.abs) > 0.01
      @vx += (@friend.x - @x) / 1000
      @vy += (@friend.y - @y) / 1000
      @vx *= 0.946; @vy *= 0.946
      @x += @vx; @y += @vy
      draw_travelers
    end
  end
  
  def find_friend
    @friend = $cities[(@idx + rand($app.num/5) + 1) % $app.num]
  end
  
  def draw_travelers
    @num_travelers.times do |i|
      t = rand * PI * 2
      dx = sin(t) * (@x - @friend.x) / 2 + (@x + @friend.x) / 2
      dy = sin(t) * (@y - @friend.y) / 2 + (@y + @friend.y) / 2
      if rand < 0.01
        dx += rand * 6 - 3
        dy += rand * 6 - 3
      end
      $app.stroke *@friend.myc
      $app.point dx, dy
    end
  end
end

SandTraveler.new :width => 700, :height => 700, :title => "Sand Traveler", :full_screen => true


