Events

Events are the central mechanism to handle responses and they allow to create interactive applications.

All classes that dispatch events inherit from EventDispatcher. The target of an event is a listener function and an optional data value. When an event is dispatched, the registered function is called. If the optional data value is given, it is used as a first parameter while calling the listener function.

In Gideros, events can be divided into two categories: built-in events which are generated by the system (e.g. ENTER_FRAME event, touch events, timer events, etc.) and custom events which can be generated by the user. According to their event type, built-in events can be broadcasted to multiple targets (e.g. ENTER_FRAME event, touch events, etc.) or can be dispatched to a single target (e.g. timer event).

ENTER_FRAME Event

The Gideros runtime dispatches the built-in Event.ENTER_FRAME event to Sprite instances before rendering the screen. Visual changes made by any Event.ENTER_FRAME listener function will be visible at next frame.

This first basic example shows a moving sprite one pixel to the right at each frame. In this example, onEnterFrame function increases the x-coordinate of a sprite object at each frame:

local sprite = Sprite.new()

local function onEnterFrame(event)
    sprite:setX(sprite:getX() + 1)
end

sprite:addEventListener(Event.ENTER_FRAME, onEnterFrame)

The next example shows 3 independent sprites moving one pixel to the right at each frame. In this example, we use the optional data parameter to move independent sprites with one common listener function:

local sprite1 = Sprite.new()
local sprite2 = Sprite.new()
local sprite3 = Sprite.new()

local function onEnterFrame(self, event)
    self:setX(self:getX() + 1)
end

sprite1:addEventListener(Event.ENTER_FRAME, onEnterFrame, sprite1)
sprite2:addEventListener(Event.ENTER_FRAME, onEnterFrame, sprite2)
sprite3:addEventListener(Event.ENTER_FRAME, onEnterFrame, sprite3)

The last example shows subclassing of the Sprite class and registering Event.ENTER_FRAME:

MySprite = Core.class(Sprite)

function MySprite:init()
    self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
end

function MySprite:onEnterFrame(event)
    self:setX(self:getX() + 1)
end

Note: Event.ENTER_FRAME event is dispatched to all Sprite instances no matter these instances are on the scene tree or not.

Mouse, Touch and Key Events

Gideros runtime dispatches mouse and touch events when the the user’s finger touches the screen. Mouse events are mainly used in single-touch whereas touch events are used in multi-touch applications. Key events are dispatched when user presses and releases a physical key on the keyboard.

The mouse, touch and key events are dispatched to Sprite instances which are on the scene tree. If a Sprite instance is not on the scene tree, this instance doesn’t receive mouse, touch and key events.

Note: Even if touch or mouse doesn’t hit the Sprite instance, the instance receive mouse/touch events.

The order of dispatch is determined by the hierachy of the scene tree. The Sprite instance that is drawn last (top-most sprite) receives the event first. The next sprite at the bottom of the top-most sprite receives the event second and so on.

For example, assume that we have an sprite hierachy like this:

Sprite Hierachy

which is constructed by the code below:

local A = Sprite.new()
local B = Sprite.new()
local C = Sprite.new()
local D = Sprite.new()
local E = Sprite.new()
local F = Sprite.new()

A:addChild(B)
A:addChild(C)
B:addChild(D)
B:addChild(E)
C:addChild(F)

In this hiearchy, the drawing order is A, B, C, D, E, F while mouse/touch event receive order is F, E, D, C, B, A.

Stopping an Event Dispatch

It is possible to stop the propagation of mouse, touch and key events. To stop an event dispatch, invoke the Event:stopPropagation() function on the Event object passed to the listener function. In this example below, MOUSE_DOWN event is dispatched only to F, E, D and C:

local A = Sprite.new()
local B = Sprite.new()
local C = Sprite.new()
local D = Sprite.new()
local E = Sprite.new()
local F = Sprite.new()

-- stop propagation at sprite C
C:addEventListener(Event.MOUSE_DOWN, function(event) event:stopPropagation() end)

A:addChild(B)
A:addChild(C)
B:addChild(D)
B:addChild(E)
C:addChild(F)

Timer Events

The Timer class is used for executing code at specified time intervals. Each Timer object dispatches Event.TIMER event at specified frequency.

The steps to use Timer class are as follows:

  1. Create a new Timer object with specified frequency and specified total number of Event.TIMER events to be triggered. For example, the following code sets the frequency to 1000 miliseconds and sets the count to 5.

      local timer = Timer.new(1000, 5)
    
  2. Register to the Event.TIMER event with a listener function:

     local function onTimer(event)
         -- will be executed 5 times at 1000 miliseconds intervals
     end
    
     timer:addEventListener(Event.TIMER, onTimer)
    
  3. Start the timer.

     timer:start()
    
  4. To stop the timer, you can use Timer:stop() function:

     timer:stop()
    
  5. Event.TIMER_COMPLETE event is triggered after finishing the specified number of timer events.

     local function onTimerComplete(event)
         -- will be executed after the specified number of timer events (5) are dispatched
     end
    
     timer:addEventListener(Event.TIMER_COMPLETE, onTimerComplete)
    

Also, it is possible to pause and resume all the timers in your application. It is very useful when you are implementing a pause/resume functionality in your game:

Timer.pauseAllTimers()      -- pause all timers. if all timers are alredy paused, does nothing.
Timer.resumeAllTimers()     -- resume all timers. if all timers are alredy running, does nothing.

ADDED_TO_STAGE and REMOVED_FROM_STAGE Events

If a sprite is added to the scene tree, the sprite instance and all of it’s descendants receive Event.ADDED_TO_STAGE event. Similarly, if a sprite is removed from the scene tree, the sprite instance and all of it’s descendants receive Event.REMOVED_FROM_STAGE event. These events are used to detect when a Sprite instance is added to, or removed from, the scene tree. For example, by the help of these events, it is possible to register Event.ENTER_FRAME event only for the sprites that are on the scene tree:

MySprite = Core.class(Sprite)

function MySprite:init()
    self:addEventListener(Event.ADDED_TO_STAGE, self.onAddedToStage, self)
    self:addEventListener(Event.REMOVED_FROM_STAGE, self.onRemovedFromStage, self)
end

function MySprite:onAddedToStage(event)
    self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
end

function MySprite:onRemovedFromStage(event)
    self:removeEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
end

function MySprite:onEnterFrame(event)
    -- enter frame logic
end

Custom Events

To dispatch a new custom, user defined event, create the event with Event.new() function and dispatch it with EventDispatcher:dispatchEvent().

ClassA = Core.class(EventDispatcher)
ClassB = Core.class(EventDispatcher)

function ClassA:funcA(event)
    print("funcA", self, event:getType(), event:getTarget())
end

local a = ClassA.new()
local b = ClassB.new()

b:addEventListener("myevent", a.funcA, a)   -- when b dispatches an "myevent" event,
                                            -- a.funcA will be called with 'a'
                                            -- as first parameter

b:dispatchEvent(Event.new("myevent"))       -- will print "funcA"

List of all Built-in Events

ENTER_FRAME

Dispatched to all Sprite instances before rendering the screen.

  • event.frameCount: The total number of frames that have passed since the start of the application
  • event.time: Time in seconds since the start of the application
  • event.deltaTime: The time in seconds between the last frame and the current frame

ADDED_TO_STAGE

Dispatched when target Sprite instance is added to the stage.

REMOVED_FROM_STAGE

Dispatched when target Sprite instance is removed from the stage.

MOUSE_DOWN

Dispatched to all Sprite instances on the scene tree when user presses the mouse button or starts the first touch.

  • event.x: The x-coordinate of the mouse or touch
  • event.y: The y-coordinate of the mouse or touch

MOUSE_MOVE

Dispatched to all Sprite instances on the scene tree when user moves the mouse or moves the first touch.

  • event.x: The x-coordinate of the mouse or touch
  • event.y: The y-coordinate of the mouse or touch

MOUSE_UP

Dispatched to all Sprite instances on the scene tree when user releases the mouse button or ends the first touch.

  • event.x: The x-coordinate of the mouse or touch
  • event.y: The y-coordinate of the mouse or touch

TOUCHES_BEGIN

Dispatched to all Sprite instances on the scene tree when one or more fingers touch down.

  • event.touch: A table with fields x, y and id which specifies the coordinates and id of the current touch
  • event.allTouches: Array of all touches where each element contains x, y and id

For example, you can print the x, y and id properties of current touch and all touches as:

local function onTouchesBegin(event)
    print(event.touch.x, event.touch.y, event.touch.id)
    for i=1,#event.allTouches do
        print(event.allTouches[i].x, event.allTouches[i].y, event.allTouches[i].id)
    end
end

TOUCHES_MOVE

Dispatched to all Sprite instances on the scene tree when one or more fingers move.

  • event.touch: A table with fields x, y and id which specifies the coordinates and id of the current touch
  • event.allTouches: Array of all touches where each element contains x, y and id

TOUCHES_END

Dispatched to all Sprite instances on the scene tree when one or more fingers are raised.

  • event.touch: A table with fields x, y and id which specifies the coordinates and id of the current touch
  • event.allTouches: Array of all touches where each element contains x, y and id

TOUCHES_CANCEL

Dispatched to all Sprite instances on the scene tree when a system event (such as a low-memory warning) cancels a touch event.

  • event.touch: A table with fields x, y and id which specifies the coordinates and id of the current touch
  • event.allTouches: Array of all touches where each element contains x, y and id

KEY_DOWN

Dispatched to all Sprite instances on the scene tree when user presses a physical key on the keyboard.

  • event.keyCode: The key code value of the key pressed

KEY_UP

Dispatched to all Sprite instances on the scene tree when user releases a physical key on the keyboard.

  • event.keyCode: The key code value of the key released

APPLICATION_START

Dispatched to all event listeners (broadcast event) right after the application is launched and all Lua codes are executed.

APPLICATION_EXIT

Dispatched to all event listeners (broadcast event) when the application is about to exit. If an application is forced to be terminated (e.g. by double tapping the home button and kill the application), this event may not be dispatched. If you want to save your game state before exiting, save your state also on APPLICATION_SUSPEND event.

APPLICATION_SUSPEND

Dispatched to all event listeners (broadcast event) when when the application is about to move from the active to inactive state. When an application is inactive, Event.ENTER_FRAME and Event.TIMER events are not dispatched until the application is resumed.

APPLICATION_RESUME

Dispatched to all event listeners (broadcast event) when the application is moved from the inactive to active state.

APPLICATION_BACKGROUND

Dispatched to all event listeners (broadcast event) when the application is now in the background.

APPLICATION_FOREGROUND

Dispatched to all event listeners (broadcast event) when the application is about to enter the foreground.

TIMER

Dispatched whenever a Timer object reaches an interval specified according to the delay property.

TIMER_COMPLETE

Dispatched whenever a Timer object has completed the number of requests specified according to the repeatCount property.

COMPLETE

Dispatched when:

  • a sound channel has finished playing.
  • after all data is received and placed in the event.data field

ERROR

Dispatched when UrlLoader fails and terminates the download.

PROGRESS

Dispatched by UrlLoader as the notification of how far the download has progressed.

  • event.bytesLoaded: The number of bytes loaded
  • event.bytesTotal: The total number of bytes that will be loaded

BEGIN_CONTACT

Dispatched by b2.World when two fixtures begin to overlap. This is dispatched for sensors and non-sensors. This event can only occur inside the time step.

  • event.contact: The contact
  • event.fixtureA: The first fixture in this contact
  • event.fixtureB: The second fixture in this contact

END_CONTACT

Dispatched by b2.World when two fixtures cease to overlap. This is dispatched for sensors and non-sensors. This may be dispatched when a body is destroyed, so this event can occur outside the time step.

  • event.contact: The contact
  • event.fixtureA: The first fixture in this contact
  • event.fixtureB: The second fixture in this contact

PRE_SOLVE

Dispatched by b2.World after collision detection, but before collision resolution.

  • event.contact: The contact
  • event.fixtureA: The first fixture in this contact
  • event.fixtureB: The second fixture in this contact

POST_SOLVE

Dispatched by b2.World after collision resolution.

  • event.contact: The contact
  • event.fixtureA: The first fixture in this contact
  • event.fixtureB: The second fixture in this contact
  • event.maxImpulse: Maximum of the normal impulses