sdl2rでゲームライブラリを作る(7)
昨日の記事で「オススメできない」と書いたばっかりだが、せっかくボタン用定数にオブジェクトが入っているのだから、これを利用して何か面白いことができないかを考えてみた。
条件の論理合成
module DXRuby module Input class ButtonChecker attr_reader :prc def initialize(prc) @prc = prc end def check @prc.call end def &(v) ButtonChecker.new(Proc.new{@prc.call and v.prc.call}) end def |(v) ButtonChecker.new(Proc.new{@prc.call or v.prc.call}) end def ! ButtonChecker.new(Proc.new{!@prc.call}) end end module UseButtonChecker def down ButtonChecker.new(Proc.new{self.down?}) end def push ButtonChecker.new(Proc.new{self.push?}) end def release ButtonChecker.new(Proc.new{self.release?}) end end end end
Inputモジュールの下にButtonCheckerクラスを作ってみた。これはボタンの状態チェックをするProcオブジェクトを受け取って、論理演算で合成することができるクラスである。UseButtonCheckerモジュールをMouseButtonクラスとKeyboardクラスにincludeしておくと、down/push/releaseの3つのメソッドが追加されて、これを呼ぶことでそれぞれのチェックを行うProcを持つButtonCheckerオブジェクトが返ってくる。ButtonCheckerオブジェクトはcheckメソッドで条件が成立しているかをチェックすることができる。もうちょっといい名前ありそうなのだが英語よくわかんないし。
具体的な使い方は以下のような感じ。
B_SHIFT_Z = K_LSHIFT.down & K_Z.push Window.loop do if B_SHIFT_Z.check break end end
左シフトが押された状態で、新たにZが押された場合にのみ終了する。&はメソッドとして定義してあり、selfと引数をandで繋いだ条件式を生成する。|と!もあるのでそれなりに思い通りの条件を作ることができる。
複数ボタンをまとめる
module DXRuby module Input class Buttons include UseButtonChecker def initialize(*ary) @ary = ary end def push? @ary.any?{|b|b.push?} end def down? @ary.any?{|b|b.down?} end def release? @ary.any?{|b|b.release?} end end end end
さっきのんは条件自体(pushとかreleaseとか)ごと合成する機能だったが、ボタンだけをまとめたい、ということがある。例えばK_LSHIFTとK_RSHIFTをまとめてK_SHIFTにしたい、などである。これを実現する方法として、Buttonsクラスを作ってみた。単純に受け取った引数を全て配列として保持して、any?でチェックするだけである。
以下のように使う。
K_LSHIFT = Input::Keyboard.new(SDL::SCANCODE_LSHIFT) K_RSHIFT = Input::Keyboard.new(SDL::SCANCODE_RSHIFT) K_SHIFT = Input::Buttons.new(K_LSHIFT, K_RSHIFT)
これで普通にK_SHIFTを扱うことができるようになる。
おしまい
キー定数に独自のオブジェクトを入れるようにすると、基本の使い方は同じままでも、発想次第でいろんなことができるようになるみたいである。
ただし、この状態でdxsdl2rに突っ込むかというと怪しい。もうちょいうまいこと作れるんじゃないかとか思うし、もうちょい機能追加できるんじゃないかとも思うし、とりあえず思いついたから作ってみただけなので、まあ、まだ練り込みが足りない。