require 'RUDL'; include RUDL; include Constant # Here is an example of how you can use the event system. # It might not be the best ruby code ever written, but, just as the rest of the stuff in this # directory, it's there to be copied and modified, or just as inspiration. # EventMapper maps the events that EventQueue generates to handlers that you assign. class EventMapper def initialize @event_map={ QuitEvent=>proc {}, KeyDownEvent=>proc {}, QuitEvent=>proc {}, KeyDownEvent=>proc {}, KeyUpEvent=>proc {}, ActiveEvent=>proc {}, MouseMotionEvent=>proc {}, MouseButtonDownEvent=>proc {}, MouseButtonUpEvent=>proc {}, JoyAxisEvent=>proc {}, JoyBallEvent=>proc {}, JoyHatEvent=>proc {}, JoyButtonUpEvent=>proc {}, JoyButtonDownEvent=>proc {}, ResizeEvent=>proc {}, TimerEvent=>proc {}, EndOfMusicEvent=>proc {} } end # distribute processes all events in the queue and calls any assigned eventhandlers def distribute event=EventQueue.poll case event when QuitEvent @event_map[QuitEvent].call when KeyDownEvent @event_map[KeyDownEvent].call(event.key, event.mod, event.unicode) when KeyUpEvent @event_map[KeyUpEvent].call(event.key, event.mod, event.unicode) when ActiveEvent @event_map[ActiveEvent].call(event.gain, event.state) when MouseMotionEvent @event_map[MouseMotionEvent].call(event.pos, event.rel, event.button) when MouseButtonDownEvent @event_map[MouseButtonDownEvent].call(event.pos, event.button) when MouseButtonUpEvent @event_map[MouseButtonUpEvent].call(event.pos, event.button) when JoyAxisEvent @event_map[JoyAxisEvent].call(event.id, event.value, event.axis) when JoyBallEvent @event_map[JoyBallEvent].call(event.id, event.ball, event.rel) when JoyHatEvent @event_map[JoyHatEvent].call(event.id, event.hat, event.value) when JoyButtonUpEvent @event_map[JoyButtonUpEvent].call(event.id, event.button) when JoyButtonDownEvent @event_map[JoyButtonDownEvent].call(event.id, event.button) when ResizeEvent @event_map[ResizeEvent].call(event.size) when TimerEvent @event_map[TimerEvent].call(event.id) when EndOfMusicEvent @event_map[EndOfMusicEvent].call end end # Attach takes the name of an eventclass (like TimerEvent) and attaches the supplied block # to it. Next time the event is encountered in "EventMapper.distribute", this block will be called. # Only the last assigned block is called. def attach(event_classname, &block) @event_map[event_classname]=block end end # --------------- end of recyclable code # --------------- start of example/test code # Events won't be handled without a display surface. $d=DisplaySurface.new [100,100], RESIZABLE event_mapper=EventMapper.new # This happens when the close button on the window is pressed event_mapper.attach(QuitEvent) { puts "bye!" exit } # This happens when a key is pressed. event_mapper.attach(KeyDownEvent) { |key, mod, unicode| # Show a few modifiers mods='' mods+='left shift ' if(mod & KMOD_LSHIFT)>0 mods+='right shift ' if(mod & KMOD_RSHIFT)>0 mods+='control ' if(mod & KMOD_CTRL)>0 # key gets over 255 when pressing a few modifiers. I don't know what it is, but I just # AND it away :-) # Unicode is defined far far away. puts "#{(key&0xff).chr} (#{mods}) unicode: #{unicode}" } # This happens when a mouse button is pressed. event_mapper.attach(MouseButtonDownEvent) { |pos,button| puts "pos "+pos.inspect+" button "+button.inspect } # This happens when you resize the window. You need to pass "RESIZABLE" to # DisplaySurface.new to make the window resizable at all. event_mapper.attach(ResizeEvent) { |new_size| puts "Window now #{new_size.join('x')}" # Reallocate the display surface at the new size $d=DisplaySurface.new new_size, RESIZABLE } # Keep on distributing events forever. The QuitEvent block will exit the program. loop do event_mapper.distribute Timer.delay(10) end