Skip to content
Franklin Webber edited this page Apr 27, 2013 · 5 revisions

Events

Events within Metro are predominately user input from the various input devices available. However, they also include global notifications that can be generated by scenes or model objects within the game.

Types of Events

Keyboard, Gamepad, and Mouse Clicks (Input)

A scene or model can respond to the following events:

  • All possible Keyboard, Gamepad, and Mouse Events can be found in the Gosu Documentation

  • Keyboard button, gamepad button, or mouse button down events or on_down.

This is the first event that is generated when a user presses the button down.

class Hero < Metro::Model
  event :on_down, KbSpace, KbA do
    jump
  end
end
  • Keyboard button, gamepad button, or mouse button held events or on_hold, on_held.

This is the second event that is generated when a user holds a button down. This event will continue to trigger while the button is held down.

class Hero < Metro::Model
  event :on_hold, KbB do
    accelerate
  end
end
  • Keyboard button, gamepad button, or mouse button up events or on_up.

This is the third event that is generated when a user releases a down/held button.

class ExampleScene
  event :on_up, KbEsc, KbDelete do
    transition_to :menu
  end
end

Mouse Movement

This event is generated with each update and allows you to respond to the current mouse position

class ExampleScene

  # This event fires with each game update

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

  def show
    # To see the mouse cursor for troubleshooting
    window.show_cursor
  end
end

Controls (Meta-Input)

Often times a particular keyboard button, gamepad button, or mouse button or several inputs may be used repeatedly throughout a game to represent a common action like: 'confirmation'; 'cancel'; 'back'; or 'forward'. It is suggested in those cases to reduce the redundancy and define a control within your game configuration.

In this example, when any input defined as the cancel control has been performed, perform the action associated with the event.

class BrandToTitleScene < GameScene
  event :cancel do
    transition_to :title
  end
end

Within the game configuration a cancel control is defined as any button up event for several keyboard buttons.

controls do
  cancel is: :button_up, with: [ KbEscape, KbDelete ]
end

Notifications

A scene or model may subscribe to a global notification. A global notification has a uniquely defined named. Any scene or model may generate a global notification. All scenes and models subscribed will be alerted and execute the associated action.

In this example the score board registers for any notifications of stars being collected:

class ScoreBoard < Metro::Model

  property :ding, type: :sample, path: "pickup.wav"
  property :score, default: 0

  event :notification, :star_collected do
    ding.play
    self.score += 1
  end

end

This event would be generated by another model which determines if the player is close enough to collect the star:

class StarCollectionMonitor < Metro::Model

  attr_accessor :player, :star_generator

  def update
    living_stars = star_generator.living_stars
    stars_player_is_close_enough_to_collect = living_stars.find_all {|star| Gosu.distance(player.x, player.y, star.x, star.y) < 35 }

    stars_player_is_close_enough_to_collect.each do |star|
      star.collapse
      notification :star_collected
    end
  end

end

Registering for Events

Both scenes and models can register for events. When a scene or model receives the event, it does not exclude another resource from also receiving the same event.

The signature of input events use the pattern:

event (:on_down|:on_up|:on_held|:on_hold), Input, Input Input do
  # course of action to take when event is true
end

The signature of control events use the pattern:

event CONTROL_SYMBOL_NAME do
  # course of action to take when event is true
end

The signature of notification events use the pattern:

event :notification, NOTIFICATION_SYMBOL_NAME do
  # course of action to take when event is true
end

Input - Block Variations

All of the previously defined examples show registration where a block has been provided as the course of action. This is common way of defining a course of action that should take place if an event.

class Hero < Metro::Model
  event :on_down, KbSpace do
    jump
  end
end

An alternative to this format is to provide a block which accepts a single parameter. The parameter is an EventData object which contains information about the event as well as the state of other buttons or modifier keys.

An example of this is used to determine if any Ctrl key is being held while the keyboard button R is being pressed down and then released:

class Game
  event :on_up, KbR do |event|
    if event.control?
      Metro.reload!
      transition_to scene_name
    end
  end
end

Input - Method Name instead of Block

Input related events may also be defined without a block and instead with an additional key-value parameter added to the definition do: :method_name_to_execute:

class Hero < Metro::Model
  event :on_down, KbSpace do: :jump

  def jump
    # jump is executed when the Keyboard Space key is pressed down
  end

end

Notifications - Block Variations

Notifications can alternatively be defined with a block that accepts 1 parameter or 2 parameters. The first parameter is the sender of the event. When the sender is unknown an UknownSender is present. The second parameter is the name of the notification.

Our previous notifications example could have been defined like the following:

class ScoreBoard < Metro::Model

  property :ding, type: :sample, path: "pickup.wav"
  property :score, default: 0

  event :notification, :star_collected do |sender,event_name|
    ding.play
    puts "Score updated by #{sender}"
    self.score += 1
  end

end

Or with a second parameter:

class ScoreBoard < Metro::Model

  property :ding, type: :sample, path: "pickup.wav"
  property :score, default: 0

  event :notification, :star_collected do |sender,event_name|
    ding.play
    puts "Score updated by #{sender} which sent #{event_name}"
    self.score += 1
  end

end