DXRubyの人の日記を読んでBitmapの扱いを修正
さて、最近、id:mirichiさんのDXRubyというライブラリが非常に気になっています。
Wikiは↓
http://sourceforge.jp/projects/dxruby/wiki/FrontPage
RubyでDirectXを操作して、高速に動作させるライブラリ、実は「やりたいやりたい」と言っていてできなかったのがDirectXとRubyとの連携。しばらくみないうちにかなりすごくなってました・・・OTL DXRuby上で動くMiyakoを作りたくなってきた(オイ)
さて、そのid:mirichiさんの日記で、各ライブラリの画像の扱いについて語っておられます。いろいろ参考になりました。ありがとうございます。
http://d.hatena.ne.jp/mirichi/20090415
そのとき、以下の文章を読んでいて、ふと思ったことが2つありました。以下引用。
MiyakoのSpriteオブジェクトは、画像情報を持つスプライト機能クラスで、画面に表示されるモノ1つについて、オブジェクトが1つ必要になる。
Ruby/SDLはVRAMにデータをベタに転送するイメージで、StarRubyはそれをラッピングして簡単にした感じだ。
DXRubyは、内部実装と概念は全然違うだろうが、使い方としてはStarRubyが一番近い。
(「mirichiの日記」より)
1つ目
文面と直接関係ないのですが、Miyakoでの画像管理は、Spriteオブジェクト一つにつき、画像(SDL::Surface)オブジェクトを一つ持っています。
実装上はそうなっているのですが、僕が考えていた仕様と違うことに気づきました。
僕が考えていた仕様では、Sprite.newメソッドの引数に:bitmap=>で示したオブジェクトを渡すと、そのオブジェクトそのものを持つように考えていました。ところが、上記の文面を読んだ後、ふと思ってSprite.newのソースを見てみたら、内部でSDL::Surface#display_format_alphaが呼ばれているので、内部では、元の画像の複製を持っていることになります。
たくさんのスプライトを用意するゲームやったら、メモリがもったいなさ過ぎる。対策せんと・・・。
というわけで、display_format_alphaの呼び出しを、Sprite.newではなくてBitmap.createもしくはBitmap.loadに変更いたしました。
Sprite#newで複製しなくなったので、スプライトを生成するときに、同じ画像を共用できるようになります。
サンプルスクリプトを載せておきます。現状の2.1ではまだ機能いたしません(今後アップするバージョンで対応)。
画像が2つ出てきますが、bitmapは共用していますので、どちらかのスプライトに手を加えると、両方のスプライトに影響が出てきます。
require 'Miyako/miyako' bitmap = Miyako::Bitmap.load("hoge") spr1 = Miyako::Sprite.new(:bitmap=>bitmap) spr2 = Miyako::Sprite.new(:bitmap=>bitmap) spr1.left!.top! spr2.right!.bottom! loop do Miyako::Input.update break if Miyako::Input.pushed_any?(:spc) Miyako::Screen.clear spr1.render spr2.render Miyako::Screen.render end Miyako::Drawing.line(spr1, [0,0,*spr1.size], [0,0,0]) loop do Miyako::Input.update break if Miyako::Input.pushed_any?(:spc) Miyako::Screen.clear spr1.render spr2.render Miyako::Screen.render end
これに加えて、これまで非公開だったBitmap.createとBitmap.loadを公開メソッドといたしました。
2つ目
あと、2つめは細かい話なのですが、仕様上の話で、
Miyako2.0以降では、「Spriteオブジェクト1つ≠画像に表示されるもの1つ」です
Miyako2.0以降の描画は、Miyako1.xとStarRubyとの中間の使い方になっています(move!メソッドなどで位置を変えて、引数なしのrenderで描画)。
ただし、基本的には画面更新1回ごとにrenderメソッドを1回呼び出すだけですので、
僕も、リンク先で紹介されているWikiをいじっているのですが、まだMiyako1.x時代の内容が多いので(というか、誤解を与えてるな)修正しないといけないな・・・。
ついでに、サンプルを載せておきます。画像が円状に並びます。
require 'Miyako/miyako' spr1 = Miyako::Sprite.new(:file=>"hoge") spr1.centering! r = 100 times = 20 radians = Array.new(times){|i| i.to_f * 2.0 * Math::PI / times.to_f } loop do Miyako::Input.update break if Miyako::Input.quit_or_escape? Miyako::Screen.clear radians.each{|rad| spr1.move!(r * Math.cos(rad), r * Math.sin(rad)){ spr1.render; nil } } Miyako::Screen.render end