Spriteオブジェクトの管理方法

アクションゲームなどを作る場合に、キャラのオブジェクトを管理する方法としては、Rubyなので標準で組み込まれている配列クラスを使うのが普通じゃないかと思う。
しかし、配列はループ中に消したりできないから、何らかのフラグなどを用いてArray#delete_ifなどで後から消すような処理を書く必要がある。
そういった部分については基本機能ではなくフレームワークレベルなのでDXRuby本体では提供しない方針としていて、ユーザーがそれぞれ使いやすい方法で実装するのが望ましい。
じゃあ、例えば配列以外にどんな方法があるのか、というのが今回の話題。

例えばSpriteクラスにnextというプロパティを追加して、それを使ってSpriteオブジェクトを連鎖させる、いわゆるリンクリストとか。Cなどの場合はよく使われる手ではある。
再帰で書けば簡単だが、Rubyには末尾再帰最適化が無いから、それを展開したコードを自分で書くほうがよい。
だいたいこんな感じ。

#!ruby -Ks
require 'dxruby'

class Sprite
  attr_accessor :next
end

class Sprites
  def initialize
    @top = nil
    @last = nil
  end

  def add(s)
    if @last == nil
      @top = s
    else
      @last.next = s
    end
    @last = s
  end

  def update
    if @top
      s = @top
      while s
        s.update
        s = s.next
      end
    end
  end

  def draw
    if @top
      s = @top
      while s
        s.draw
        s = s.next
      end
    end
  end
end

sprites = Sprites.new
image = Image.new(40,40,[255,255,255])
10.times do
  s = Sprite.new(rand(600), rand(440), image)
  sprites.add(s)
end

Window.loop do
  sprites.draw
end

nextでつながったオブジェクトを辿って一連の処理を行う。このコードは片方向のリンクだから削除することができない。最初から辿って検索すれば可能だが、実行性能的にあまり喜ばしくない。双方向リストにしたほうが性能的にはよい。
ただ、現時点ではSprite.checkの衝突判定は引数に配列を受け取るから、使う場合は予めリンクを辿って配列を作る必要がある。そういう意味ではDXRuby1.3系は配列による管理を推奨していると言えるかもしれない。
まあ、オブジェクト数が異様に多くない限りは配列を作る負荷など気にするほどでもないから、配列以外のやり方をいろいろ試してみる価値はあるとは思う。