Jewel-mmo開発日記

RubyでMMORPGを作る過程を記録する日記。 Yokohama.rb 発起人。
2006-04-10

イベント処理をラップ (2)

昨日のイベント処理をメソッドとして定義する案を書いて、すぐにあれでは使いにくいことに気づいた。例えばマウスカーソルの位置にボールを表示する場合。簡単にはマウスの座標をループ内の x, y に伝えられないのだ。

def event_mousemotion(event)
  event.x # あれ、どうしよう……
  event.y
end

game_init
screen = Screen.new(SCREEN_W, SCREEN_H)
x, y = 0, 0
game_loop do
  draw_image screen, 'ball.bmp', x, y
end

じゃあ結局ループ内でマウスイベントをポーリングする仕組みのほうがいいか。ループ内に毎回判定を書くの実は好きなんだけど、もっといい方法がありそうだ。

game_loop do
  if event_mousemotion?
     x = event_mouse_x
     y = event_mouse_x
  end
  draw_image screen, 'ball.bmp', x, y
end

こんな書き方はできないのだろうか。というかこれできるんじゃないの?

x, y = 0, 0
add_event_mousemotion {|event| x, y = event.x, event.y }

game_loop do
  draw_image screen, 'ball.bmp', x, y
end

とりあえず簡単な実装。おおうまくいく。ブロックというか proc ってほとんど使ったことなかったけどこうやって使うんだ。なるほど。

def add_event_mousemotion(&block)
  $event_blocks << block
end

require 'sdl'

SDL.init SDL::INIT_VIDEO
screen = SDL.setVideoMode(320, 240, 16, SDL::SWSURFACE)
$event_blocks = []

x, y = 0, 0
add_event_mousemotion { puts "MouseMotion" }
add_event_mousemotion {|event| x, y = event.x, event.y }

loop do
  while event = SDL::Event2.poll
    case event
    when SDL::Event2::Quit 
      exit
    when SDL::Event2::MouseMotion
      $event_blocks.each {|block| block.call event }
    end
  end
  puts x, y
  sleep 1.0 / 60
end

--

いやあ、やっぱりRubyのパワーすごい。今まで Ruby での GUI のゲームはあんまり手を着けてなかったんだけど、 Ruby + Ruby/SDL かなり面白いかも。