Star RubyでDXRubyExtensionを使う

DXRubyExtensionは用途は色々になる予定だが、とりあえず衝突判定ロジックが詰め込まれている。
これはRuby汎用の拡張ライブラリだから、名前にはDXRubyと付いているしサンプルもDXRuby用だがDXRubyには依存しない。
はずだ。
論より証拠ということで、Star Rubyと一緒に使ってみた。

円が無いのはStar Rubyに円を描画する機能がなくて作るのが面倒だったからだ。
ソースはこんな感じで、ハッキリ言ってしまって、Star RubyとDXRuby間の移植はメソッド呼び出し部分を書き換えるだけだ。
これを統一したらほぼ同じソースになるんじゃね?ってぐらい。
とはいえお互い独特な機能があるから、そこまで単純な話ではないのだが。
でも使用感はやっぱ似てるな。

# DXRubyExtension0.0.5サンプル(StarRuby版)
require "starruby"
require "dxrubyex"

include StarRuby

# 衝突判定配列
# ここに判定オブジェクトをたくさん入れる
$collisions = []

# 動くもの共通クラス
class CollisionObject
  def initialize
    @x = rand(639-@image1.width)
    @y = rand(439-@image1.height)
    @hit = false
    @dx = (rand(4)*2-3)/2.0
    @dy = (rand(4)*2-3)/2.0
  end

  # キャラ移動と判定配列設定
  def update
    @x += @dx
    @y += @dy
    @dx = -@dx if @x <= 0 or @x >= 639-@image1.width
    @dy = -@dy if @y <= 0 or @y >= 479-@image1.height

    # setメソッドで判定オブジェクトの位置を移動する
    @collision.set(@x, @y)
    # 配列にpush
    $collisions.push(@collision)
    @hit = false
  end

  def draw(game)
    if @hit then
      game.screen.render_texture(@image2, @x, @y)
    else
      game.screen.render_texture(@image1, @x, @y)
    end
  end

  # あたっていたらhitが呼ばれる
  def hit(d)
    @hit = true
  end
end

# しかく
class Box < CollisionObject
  def initialize
    # 衝突判定オブジェクト作成。
    # 第一引数のオブジェクトのhitメソッドが呼ばれる。
    # 第二以降の引数は判定範囲の指定。原点はキャラの座標。
    # setメソッドで移動させるから、判定範囲は変更する必要がない。
    @collision = CollisionBox.new(self, 0, 0, 29, 29)
    @image1 = Texture.new(30, 30).fill(Color.new(200,0,0))
    @image2 = Texture.new(30, 30).fill(Color.new(200,200,200))
    super
  end
end

# さんかく
class Triangle < CollisionObject
  def initialize
    # 三角は3点の座標を指定する。
    @collision = CollisionTriangle.new(self, 20,0,0,39,39,39)
    @image1 = Texture.new(40, 40)
    @image2 = Texture.new(40, 40)
    for i in 0..39
      @image1.render_line(20-i/2, i, 20+i/2, i, Color.new(0,200,0))
      @image2.render_line(20-i/2, i, 20+i/2, i, Color.new(200,200,200))
    end
    super
  end
end

font = Font.new("MS UI Gothic", 24)

# 移動&描画するモノの配列。30個ずつ作る。
object = Array.new(30) {Box.new} +
         Array.new(30) {Triangle.new}

# メインループ
Game.run(640, 480, :fps=>60) do |game|
  # 移動&判定オブジェクトの配列へのpush
  object.each do |o|
    o.update
  end

  # マウスカーソルの座標をセットした点判定オブジェクト。
  # 第一引数にnilを指定すると衝突通知が行われない。
  mousecollision = CollisionPoint.new(nil)
  x, y = Input.mouse_location
  mousecollision.set(x, y)

  # マウスカーソルとオブジェクトの衝突判定。
  # 単体の場合は配列である必要はない。
  Collision.check(mousecollision, $collisions)

  # オブジェクト同士の衝突判定。
  Collision.check($collisions, $collisions)

  # 判定配列をクリアする。
  $collisions.clear

  # 描画
  game.screen.clear
  object.each do |o|
    o.draw(game)
  end

  break if Input.keys(:keyboard).include?(:escape)

  game.screen.render_text(game.real_fps.to_s + " fps", 0, 0, font, Color.new(255,255,255))
end

あ、このサンプルコードはいつものようにパブリックドメインということで。