Fiberを使いやすくする仕掛け2

実際にFiberSpriteを使って何か作ろうと考えたとき、ゲームに登場するキャラはFiberを使うものと使わないものに分かれることに気づく。たとえば敵キャラ全体のスーパークラスを作ったときに、その派生クラスがFiberを使うものと使わないものに分かれてしまうと、FiberSpriteクラスを使うことができない。
ということでFiberSpriteをモジュール化してみた。includeしたSpriteだけがFiberを使う。

require 'dxruby'

module FiberSprite
  def initialize(x=0,y=0,image=nil)
    super
    @fiber = Fiber.new do
      self.fiber_proc
    end
  end

  def update
    @fiber.resume
  end

  def wait(t=1)
    t.times {Fiber.yield}
  end

  def add_x(x, t=1)
    t.times {self.x += x;Fiber.yield}
  end

  def add_y(y, t=1)
    t.times {self.y += y;Fiber.yield}
  end
end

class Enemy < Sprite
  include FiberSprite

  @@image = Image.load_tiles("image/enemy2.png", 4, 1)

  def self.objects=(ary)
    @@objects = ary
  end

  def initialize(x=0, y=0)
    super(x, y, @@image[0])
    @angle = 90
  end

  def fire(angle)
    @@objects << Shot.new(self.x+20, self.y+@@image[0].height/2+20, angle)
    @@objects << Shot.new(self.x+108, self.y+@@image[0].height/2+20, angle)
  end

  def fiber_proc
    loop do
      wait 5
      fire(@angle)
      @angle += 15
    end
  end
end

class Shot < Sprite
  @@image = Image.load("image/enemyshot2.png")

  def self.objects=(ary)
    @@objects = ary
  end

  def initialize(x=0, y=0, angle=0)
    super(x-@@image.width/2, y-@@image.height/2, @@image)
    @dx = Math.cos(angle / 180.0 * Math::PI) * 3.5
    @dy = Math.sin(angle / 180.0 * Math::PI) * 3.5
  end

  def update
    self.x += @dx
    self.y += @dy
    if self.x < -@@image.width or self.x > 640 or self.y < -@@image.height or self.y > 480
      vanish
    end
  end
end

objs = []
Enemy.objects = objs
Shot.objects = objs

objs << Enemy.new(100,100)

Window.loop do
  Sprite.update(objs)
  Sprite.draw(objs)
  Sprite.clean(objs)
end