DXRubyFramework実験中

Rubyの性能を引き出すやりかたで、さらに使いやすく、というのは無茶な話だということがわかった。
普通は書き方による性能の違いなどあまり意識しない用途で使うのがLLなのだろう。
だから、DXRubyFrameworkは通常のRubyユーザーからすると使いにくいものになる気がしてきた。
初心者にもオススメできないかもしれない。
しかしこれは速い。異常な速さだ。
Ruby1.9.1-p0+DXRuby1.0.5+DXRubyExtension0.0.6+DXRubyFramework0.0.1。
未公開モノのオンパレード。
ハードはPentium4 2.4GHz、メモリ1GB、GeForce7300GT。
スクリーンショットをどうぞ。

require "dxruby"
require "dxrubyex"
require "dxrubyfw"

class Array
  include ArrayExtension
end

class Ruby < Sprite
  MAX_X = 640 - 32
  MAX_Y = 480 - 32

  # Imageオブジェクトを作成
  @@image = Image.load("ruby.png")

  # 初期化メソッド
  def init
    self.x= rand(MAX_X) # x座標
    self.y= rand(MAX_Y) # y座標
    self.dx= rand(2) * 2 - 1 # x増分
    self.dy= rand(2) * 2 - 1 # y増分
    self.image = @@image  # 画像
    self.setRange(1, 1, MAX_X - 1, MAX_Y - 1) # 判定範囲。これをオーバーしたらoutが呼ばれる
  end

  # カウントを設定してあれば、0になったときに呼ばれる
  def update
  end

  # 設定範囲から出た場合に呼ばれる
  def out
    if self.x <= 0 or MAX_X <= self.x
      self.dx = -self.dx
    end
    if self.y <= 0 or MAX_Y <= self.y
      self.dy = -self.dy
    end
  end
end

# Sprite オブジェクトの配列を生成する。
sprites = Array.new(14000){ Ruby.new }

font = Font.new(32)

# ウィンドウのキャプションを設定する。 
Window.caption = "Sprites"

# fpsを設定する。
Window.fps = 60

# メインループ。
# ウィンドウが閉じられた場合は自動的に終了する。
# 画面は毎フレームリセットされる。
Window.loop do
  # sprites構造体の増減
  if Input.keyDown?(K_RIGHT) then
    10.times do
      sprites.push(Ruby.new)
    end
  end
  if Input.keyDown?(K_LEFT) then
    10.times do
      sprites.pop
    end
  end

  # ESC キーが押された場合終了する。
  break if Input.keyPush?(K_ESCAPE)

  # Sprite オブジェクトそれぞれについて処理する。
  # まだ上位処理ができていないので、Spriteの内部処理を呼ぶ。
  sprites.hs_each(:internal_update)

  Window.drawFont(0,0,Window.fps.to_s + " fps", font)
  Window.drawFont(0,40,sprites.size.to_s + " objects", font)
  Window.drawFont(0,80,Window.getLoad.to_i.to_s + " %", font)
end

各種情報の登録はメソッドx=などを使っている。
いい名前があればいいのだが、思いつかなかったからx=なのだが、これはself.を付けないと呼べない。
setXとかでもいいんだろうか。使いにくいよなあ。
全部self付けてくれたまえ。
インスタンス変数へのアクセスはRuby1.9.1だと大変時間がかかるようで、そのようにするとRubyで書くより遅くなる。
rb_float_newも死ぬほど遅いから、xとyのゲッターについては整数で返すようになっている。
小数点以下が欲しい場合はx_fとy_fで取れるようにはしてある。


また、DXRubyとは別のライブラリになってるから、Window.draw系の内部情報にアクセスできない。
Ruby経由でWindow.drawを呼ぶと、これまた死ぬほど遅く(9000個ぐらいに)なる。
よくわからないが、Ruby1.9.1は実行が速いかわりにCのインターフェースが遅くなってたりしないだろうか。
言いがかりかもしれない。
まあ、ともかくそういう理由で、DXRuby本体からWindow.drawでRubyから呼ばれている関数を外に公開してみた。
これはテスト用の暫定対応であって、きちんとしたインターフェースを作る必要がある。
なんせdrawScaleとかdrawRotはFlaotで渡さないと精度が悲しいことになるが、rb_float_newを呼ばないといけなくなるからヤバいのだ。
内部でfloat型の値を持っていて、呼び先でもfloat型で使うのだから、Rubyオブジェクトを介する必要はない。


まあなんだ。
実用レベルまで行ってくれればいいんだけど。
あ、dxとdyが整数になってた・・・。
これのゲッターはrb_float_newしないとあかんから結構ロスだなあ。
まだまだ遅くなりそうだ。
うちで60fpsで10000ぐらい動いてくれれば、ローエンドでも本格的に弾幕ゲーができそうなのだが。