Sceneにメインループを置く例
昨日のコードには2つほど問題がある。一つはシーン切り替えのトリガが1フレーム処理の最後にあるところで、まあこれは単純なミスだ。
もう一つは、シーン切り替えの瞬間のみInput.updateが1フレーム中に2回呼ばれるところ。2回呼ぶのはDXRuby的には反則なのだが、これを1回にするように修正すると今度はシーン切り替え後のInput.key_push?(K_SPACE)がしょっぱなからtrueになって、SecondSceneがいきなり終わることになる。最初の入力を無視するのも面倒だし、どうしていくのがいいのかはおいおい考えるとして、今はこの状態で先に進めることとする。と思ったけどこれちょっと前に発覚したバグじゃん。まあ、結局のところ後で考えるわけだが。
今回はメニューぽいSceneを追加してみよう。
Escapeキーでメニュー表示するが、このときにメインのシーンはそのまま実行し続ける、ということをしてみる。一応フェードアウトでちょっと暗くしてみる。メニューはぜんぜんメニューじゃないけどまあ何か表示するというだけにしておいて、Escapeでフェードインして元のシーンに戻る。とする。
とりあえずFirstSceneを修正する。メニューシーンから呼べるようにupdateとdrawのメソッドを追加して、EscapeキーでMenuSceneを作ってrunを呼ぶ。呼び返しができるようにselfを渡しておく。
class FirstScene < Scene def initialize @objects = [] @screen_collision = Sprite.new @screen_collision.collision = [0, 0, 639, 479] end def run Window.loop do if Input.key_push?(K_SPACE) return SecondScene.new end if Input.key_push?(K_ESCAPE) MenuScene.new(self).run end update @objects = @screen_collision.check(@objects) draw end end def update @objects.push Hoge.new Sprite.update @objects end def draw Sprite.draw @objects end end
MenuSceneのほうは適当にフェードアウトとフェードインを書いて、その間にメニューぽいものを描画するメインループを置く。ここでカーソル移動やらなんやらをすればちゃんとしたメニューになるはずだが、面倒なのでこれでよい。
class MenuScene < Scene @@fadeimage = Image.new(1,1,C_BLACK) @@backimage = Image.new(1,1,[192,0,0,0]) @@menuimage = Image.new(100,50,C_BLACK).box(0, 0, 99, 49, C_WHITE) .draw_font_ex(10,10,"メニュー",Font.new(32)) def initialize(s) @s = s end def run Window.times(30) do |i| @s.update @s.draw Window.draw_ex(0, 0, @@fadeimage, :alpha=>255*i/45, :scale_x=>640, :scale_y=>480, :center_x => 0, :center_y=>0) end Window.loop do if Input.key_push?(K_ESCAPE) break end @s.update @s.draw Window.draw_scale(0, 0, @@backimage, 640, 480, 0, 0) Window.draw(270, 215, @@menuimage) end Window.times(30) do |i| @s.update @s.draw Window.draw_ex(0, 0, @@fadeimage, :alpha=>255*(29 - i)/45, :scale_x=>640, :scale_y=>480, :center_x => 0, :center_y=>0) end return nil end end
フェードアウト/フェードインをするのにあると便利だったのでWindow.timesを作ってみた。
module Window def self.times(count) unless @@created Window.create @@created = true end count.times do |i| raise ExitException if Input.update yield i Window.sync Window.update end end end
FirstSceneと同じようにSecondSceneを修正すると、どっちからでもメニューが呼べるようになる。こういう画面になる。