Ruby2.0のprependでHitRangeを使う

DXRuby1.5devにはHitRangeモジュールをサンプルとして添付してあるが、これはSpriteを継承したクラスに対してincludeして使う。
RubyのModule#includeは実行されたときのself(つまりなんかのクラス)に対して、継承階層の上位にモジュールを挿し込む。といってもモジュールは継承できないので、正確にはモジュールをクラス化した特殊なクラスが挿し込まれる。
Module#includeを使う場合の問題点は、指定したクラスの上に入るために、そのクラスで実装したメソッドが先に動いてしまう点だ。まあ、superを最初に書けばいいのかもしれないが、そうするとさらにその上位のsuperまで先に動いてしまうので、そのあたりが何かと面倒な制限になる。また、DXRubyのSprite#drawメソッドのようにsuperしてくれないメソッドをモジュールのメソッドで拡張しようとすると、わざわざSpriteを継承してから派生クラスのほうにincludeしないといけない。そういうわけでHitRangeモジュールはSpriteの派生クラスにincludeして使わざるを得ないのである。
こんな感じだ。

  class TestSprite < Sprite
    include HitRange
  end
  s = TestSprite.new(100,100)

これだと、たとえばSprite全部の衝突判定範囲を描画したい場合に、派生したすべてのクラスにincludeを書かなければならないとか、そのためにわざわざ派生クラスを一段多く作らなければならないとか、そういう話になってしまうので、なんとかできるとうれしい。
Ruby2.0なら、できる。

  class Sprite
    prepend HitRange
  end
  s = Sprite.new(100,100)

追加されたModule#prependは、クラスの継承階層の下位側にモジュールを追加する。実装の詳細は知らないがおそらくモジュールを内部でクラス化したものを追加しているのだろう。ともかくこれを使えばSpriteクラスにHitRangeをprependするだけですべてのSpriteの衝突判定範囲が描画されるようになる。非常に楽である。
こんな感じに一発で描画できるようになる。

しかし困ったことにHitRangeはDXRuby1.5dev用に追加したメソッドを使っているのでそのままでは1.4.0では使えないし、Ruby2.0用にDXRuby1.5devは用意してないのだ。いまいち意味の無い記事である。
しょうがないので続きにDXRuby1.4.0で使えるHitRangeモジュールをおいておく。一部コメントアウトしただけなんだけど。

続きを読む