Class: Metro::EventRelay

Inherits:
Object
  • Object
show all
Defined in:
lib/metro/events/event_relay.rb

Overview

Note:

registering for ‘button_held’ events require that the window be speicfied. As that is the only way to ask if the button is currently pressed.

An EventRelay represents a target’s willingness to respond to events generate from the window. An event relay is generate for every scene but additional relays can be generated to also listen for events.

An event relay can register a target to listen for the following window events: ‘button_down’; ‘button_up’; and ‘button_held’.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target, window = nil) ⇒ EventRelay

An event relay is created a with a target and optionally a window.

Parameters:

  • target (Object)

    the object that will execute the code when the button events have fired have been triggered.

  • window (Window) (defaults to: nil)

    the window of the game. This parameter is optional and only required if the events are interested in buttons being held.



63
64
65
66
67
68
69
70
71
# File 'lib/metro/events/event_relay.rb', line 63

def initialize(target,window = nil)
  @target = target
  @window = window
  @up_actions ||= {}
  @down_actions ||= {}
  @held_actions ||= {}
  @mouse_movement_actions ||= []
  @custom_notifications ||= HashWithIndifferentAccess.new([])
end

Instance Attribute Details

#custom_notificationsObject (readonly)

Returns the value of attribute custom_notifications.



252
253
254
# File 'lib/metro/events/event_relay.rb', line 252

def custom_notifications
  @custom_notifications
end

#down_actionsObject (readonly)

Returns the value of attribute down_actions.



248
249
250
# File 'lib/metro/events/event_relay.rb', line 248

def down_actions
  @down_actions
end

#held_actionsObject (readonly)

Returns the value of attribute held_actions.



248
249
250
# File 'lib/metro/events/event_relay.rb', line 248

def held_actions
  @held_actions
end

#mouse_movement_actionsObject (readonly)

Returns the value of attribute mouse_movement_actions.



250
251
252
# File 'lib/metro/events/event_relay.rb', line 250

def mouse_movement_actions
  @mouse_movement_actions
end

#targetObject (readonly)

Returns the value of attribute target.



73
74
75
# File 'lib/metro/events/event_relay.rb', line 73

def target
  @target
end

#up_actionsObject (readonly)

Returns the value of attribute up_actions.



248
249
250
# File 'lib/metro/events/event_relay.rb', line 248

def up_actions
  @up_actions
end

#windowObject (readonly)

Returns the value of attribute window.



73
74
75
# File 'lib/metro/events/event_relay.rb', line 73

def window
  @window
end

Class Method Details

.check_for_already_defined_control!(control) ⇒ Object



48
49
50
51
52
# File 'lib/metro/events/event_relay.rb', line 48

def self.check_for_already_defined_control!(control)
  if instance_methods.include? control.name
    error! "error.reserved_control_name", name: control.name
  end
end

.define_control(control) ⇒ Object

Defines a control from a ControlDefinition for all EventRelays. A control is a way of defining a shortcut for a common event. This could be the use of a common set of keys for confirmation or canceling.



40
41
42
43
44
45
46
# File 'lib/metro/events/event_relay.rb', line 40

def self.define_control(control)
  check_for_already_defined_control!(control)

  define_method control.name do |&block|
    send(control.event,*control.args,&block)
  end
end

.define_controls(controls) ⇒ Object

Defines the provided controls for every EventRelay that is created.

Parameters:

  • controls (Array<ControlDefinition>)

    the definitions of controls that should be added to all EventRelays.

See Also:

  • #define_control


31
32
33
# File 'lib/metro/events/event_relay.rb', line 31

def self.define_controls(controls)
  controls.each { |control| define_control control }
end

Instance Method Details

#_fire_event_for_notification(event, sender, action) ⇒ Object

Fire a single event based on the matched notification.

An action without any parameters is assumed to be executed within the contexxt of the target. If there are two parameters we will simply execute the action and pass it both the target and the sender.



331
332
333
334
335
336
337
338
339
# File 'lib/metro/events/event_relay.rb', line 331

def _fire_event_for_notification(event,sender,action)
  if action.arity == 2
    target.instance_exec(sender,event,&action)
  elsif action.arity == 1
    target.instance_exec(sender,&action)
  else
    target.instance_eval(&action)
  end
end

#_on(hash, args, block) ⇒ Object



254
255
256
257
258
259
260
# File 'lib/metro/events/event_relay.rb', line 254

def _on(hash,args,block)
  options = (args.last.is_a?(Hash) ? args.pop : {})

  args.each do |keystroke|
    hash[keystroke] = block || lambda { |instance| send(options[:do]) }
  end
end

#down_action(id) ⇒ Object

Returns a block of code that is mapped for the ‘button_down’ id.

Returns:

  • a block of code that is mapped for the ‘button_down’ id



310
311
312
# File 'lib/metro/events/event_relay.rb', line 310

def down_action(id)
  down_actions[id] || lambda {|no_op| }
end

#execute_block_for_target(&block) ⇒ Object



299
300
301
302
# File 'lib/metro/events/event_relay.rb', line 299

def execute_block_for_target(&block)
  event_data = EventData.new(window)
  target.instance_exec(event_data,&block)
end

#fire_button_down(id) ⇒ Object

This is called by external or parent source of events, usually a Scene, when a button down event has been triggered.



274
275
276
# File 'lib/metro/events/event_relay.rb', line 274

def fire_button_down(id)
  execute_block_for_target( &down_action(id) )
end

#fire_button_up(id) ⇒ Object

This is called by external or parent source of events, usually a Scene, when a button up event has been triggered.



266
267
268
# File 'lib/metro/events/event_relay.rb', line 266

def fire_button_up(id)
  execute_block_for_target( &up_action(id) )
end

#fire_events_for_held_buttonsObject

Fire the events mapped to the held buttons within the context of the specified target. This method is differently formatted because held buttons are not events but polling to see if the button is still being held.



283
284
285
286
287
# File 'lib/metro/events/event_relay.rb', line 283

def fire_events_for_held_buttons
  held_actions.each do |key,action|
    execute_block_for_target(&action) if window and window.button_down?(key)
  end
end

#fire_events_for_mouse_movementObject

Fire events for all the registered actions that are suppose to receive the mouse movement events.



293
294
295
296
297
# File 'lib/metro/events/event_relay.rb', line 293

def fire_events_for_mouse_movement
  mouse_movement_actions.each do |action|
    execute_block_for_target(&action)
  end
end

#fire_events_for_notification(event, sender) ⇒ Object

Fire all events mapped to the matching notification.



317
318
319
320
321
322
# File 'lib/metro/events/event_relay.rb', line 317

def fire_events_for_notification(event,sender)
  notification_actions = custom_notifications[event]
  notification_actions.each do |action|
    _fire_event_for_notification(event,sender,action)
  end
end

#notification(param, &block) ⇒ Object

Register for a custom notification event. These events are fired when another object within the game posts a notification with matching criteria. If there has indeed been a match, then the stored action block will be fired.

When the action block is specified is defined with no parameters it is assumed that that the code should be executed within the context of the object that defined the action, the ‘target’.

The action block can also be specified with two parameters. In this case the code is no longer executed within the context of the object and is instead provided the the action target and the action source.

Examples:

Registering for a save complete event that would re-enable a menu.


class ExampleScene
  event :notification, :save_complete do
    menu.enabled!
  end
end

Registering for a win game event that explicitly states the target and source.


class ExampleScene

  event :notification, :win_game do |target,winner|
    target.declare_winner winner
  end

  def declare_winner(winning_player)
    # ...
  end
end


244
245
246
# File 'lib/metro/events/event_relay.rb', line 244

def notification(param,&block)
  custom_notifications[param.to_sym] = custom_notifications[param.to_sym] + [ block ]
end

#on_down(*args, &block) ⇒ Object Also known as: button_down

Register for a button_down event. These events are fired when the button is pressed down. This event only fires once when the button moves from the not pressed to the down state.

Here in this scene if the GpLeft or GpUp buttons are pressed down the method ‘previous_options` will be executed.

This example uses a block instead of a method name but it is absolultey the same as the last example.

Examples:

Registering for a button down event to call a method named ‘previous_option’


class ExampleScene
  event :on_down, GpLeft, GpUp, do: :previous_option

  def previous_option
    @selected_index = @selected_index - 1
    @selected_index = options.length - 1 if @selected_index <= -1
  end
end

Registering for a button down event with a block of code to execute


class ExampleScene
   event :on_down, GpLeft, GpUp do
    @selected_index = @selected_index - 1
    @selected_index = options.length - 1 if @selected_index <= -1
  end
end


107
108
109
# File 'lib/metro/events/event_relay.rb', line 107

def on_down(*args,&block)
  _on(@down_actions,args,block)
end

#on_hold(*args, &block) ⇒ Object Also known as: button_hold, button_held

Note:

button_held events require that the window be specified during initialization.

Register for a button_held event. These events are fired when the button is currently in the downstate. This event continues to fire at the beginning of every update of a scene until the button is released.

Examples:

Registering for button held events


class ExampleScene
  event :on_hold KbLeft, GpLeft do
    player.turn_left
  end

  event :on_hold, KbRight, GpRight do
    player.turn_right
  end

  event :on_hold, KbUp, Gosu::GpButton0, do: :calculate_accleration

  def calculate_acceleration
    long_complicated_calculated_result = 0
    # ... multi-line calculations to determine the player acceleration ...
    player.accelerate = long_complicated_calculated_result
  end
end


175
176
177
178
# File 'lib/metro/events/event_relay.rb', line 175

def on_hold(*args,&block)
  log.warn "Registering for a on_hold event requires that a window be provided." unless window
  _on(@held_actions,args,block)
end

#on_mouse_movement(*args, &block) ⇒ Object

Note:

mouse movement events fire with each update so it is up to the receiving object of the event to determine if the new mouse movement is a delta.

Note:

mouse movement events require that the window be specified during initialization.

Register for mouse movements events. These events are fired each update providing an event which contains the current position of the mouse.

Examples:

Registering for button held events


class ExampleScene

  draws :player

  event :on_mouse_movement do |event|
    player.position = event.mouse_point
  end
end


205
206
207
208
# File 'lib/metro/events/event_relay.rb', line 205

def on_mouse_movement(*args,&block)
  options = (args.last.is_a?(Hash) ? args.pop : {})
  @mouse_movement_actions << ( block || lambda { |instance| send(options[:do]) } )
end

#on_up(*args, &block) ⇒ Object Also known as: button_up

Register for a button_up event. These events are fired when the button is released (from being pressed down). This event only fires once when the button moves from the pressed state to the up state.

Here in this scene if the Escape Key is pressed and released the example scene will transition to the title scene.

This example uses a block instead of a method name but it is absolultey the same as the last example.

Examples:

Registering for a button down event to call a method named ‘next_option’


class ExampleScene
   event :on_up, KbEscape, do: :leave_scene

  def leave_scene
    transition_to :title
  end
end

Registering for a button up event with a block of code to execute


class ExampleScene
  event :on_up, KbEscape do
   transition_to :title
  end
end


142
143
144
# File 'lib/metro/events/event_relay.rb', line 142

def on_up(*args,&block)
  _on(@up_actions,args,block)
end

#up_action(id) ⇒ Object

Returns a block of code that is mapped for the ‘button_up’ id.

Returns:

  • a block of code that is mapped for the ‘button_up’ id



305
306
307
# File 'lib/metro/events/event_relay.rb', line 305

def up_action(id)
  up_actions[id] || lambda {|no_op| }
end