Gem 'Ruby 2D' で遊ぶ(2)

過去記事のプログラムを少し改変したものです。
 
コード。
ruby2d_sample2a.rb

require 'ruby2d'
require 'matrix'
include Math

Width = 500
C = 15    #円の数
R = 20    #円の半径

L = 70    #三角形の外接円の半径

set width: Width, height: Width

circles = C.times.map {
  Circle.new x: rand(R..Width - R), y: rand(R..Width - R),
     radius: R, color: Color.new([rand, rand, rand, 0.8]), z: 0
}
cvs = circles.map {[rand(-3.0..3.0), rand(-3.0..3.0)]}    #円の移動ベクトル
circles_move = circles.zip(cvs)


rot = ->(θ) {
   θ1 = θ / 180.0 * PI
   Matrix[[cos(θ1), sin(θ1)], [-sin(θ1), cos(θ1)]]
}

points = ->(θ) {
  o = Vector[Width / 2.0, Width / 2.0]
  v0 = Vector[0, -L]
  p1 = o + rot.(θ +   0) * v0
  p2 = o + rot.(θ + 120) * v0
  p3 = o + rot.(θ + 240) * v0
  [p1, p2, p3]
}

triangle = Triangle.new z: 10, opacity: 0.8

triangle.define_singleton_method(:rotate) do |θ|
  p1, p2, p3 = points.(θ)
  self.x1 = p1[0]
  self.y1 = p1[1]
  self.x2 = p2[0]
  self.y2 = p2[1]
  self.x3 = p3[0]
  self.y3 = p3[1]
end

triangle_color = [rand, rand, rand]
triangle_color_step =
   (Vector[rand(-1.0..1.0), rand(-1.0..1.0), rand(-1.0..1.0)]
     .normalize / 100).to_a

triangle_color.define_singleton_method(:update) do
  triangle.color = self + [0.8]
  replace(zip(triangle_color_step).map {|a, b| a + b})
  triangle_color.each_index do |i|
    if triangle_color[i] < 0 || triangle_color[i] > 1
      triangle_color_step[i] = -triangle_color_step[i]
    end
  end
end


θ = 0

update do
  #円の移動
  circles_move.each do |c, vec|
    c.x += vec[0]
    c.y += vec[1]
    c.x = Width + R if c.x < -R
    c.y = Width + R if c.y < -R
    c.x = -R if c.x > Width + R 
    c.y = -R if c.y > Width + R 
  end
  
  #三角形の回転
  triangle.rotate(θ)
  triangle_color.update if (θ % 3).zero?
  θ = (θ + 1) % 360
end

show