Event system
The Ultimate Guide to Gideros Studio
Event system
Introduction to 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.)
- 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 = gideros.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 if these instances are on the scene tree or not.
Note: when the ENTER_FRAME event dispatches, the event object contains time and deltaTime. Consider the following example:
local function onEnterFrame(event)
print(event.time, event.deltaTime)
end
stage:addEventListener(Event.ENTER_FRAME, onEnterFrame)
Mouse and touch 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.
The mouse and touch 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 and touch events.
Note: even if touch or mouse doesn’t hit the Sprite instance, the instance receives mouse/touch events.
The order of dispatch is determined by the hierarchy 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 hierarchy like this:
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 hierarchy, 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 and touch events. To stop an event dispatch, invoke the Event:stopPropagation() function on the Eventobject passed to the listener function.
In the 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©
B:addChild(D)
B:addChild(E)
C:addChild(F)
Note: stopPropagation is only for mouse and touch events. Because only for them there is a definite dispatching order (the display object on top receives the event first).
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 milliseconds 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()
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:
-- pause all timers.
-- if all timers are alredy paused, does nothing.
Timer.pauseAllTimers()
-- resume all timers. if all timers
-- are already running, does nothing.
Timer.resumeAllTimers()
ADDED_TO_STAGE and REMOVED_FROM_STAGE Events
If a sprite is added to the scene tree, the sprite instance and all of its descendants receive Event.ADDED_TO_STAGE event. Similarly, if a sprite is removed from the scene tree, the sprite instance and all of its 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 = gideros.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(). Example:
ClassA = gideros.class(EventDispatcher)
ClassB = gideros.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
The following tables show a list of all built-in events in Gideros SDK, with a brief explanation of what they are for.
Frame & stage 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 events
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 |
Touch events
TOUCHES_BEGIN | Dispatched to all Sprite instances on the scene tree when one or more fingers touch down.
• event.touches: Array of current touches where each element contains x, y and id • event.allTouches: Array of all touches where each element contains x, y and id |
TOUCHES_MOVE | Dispatched to all Sprite instances on the scene tree when one or more fingers move.
• event.touches: Array of current touches where each element contains x, y and id • 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.touches: Array of current touches where each element contains x, y and id • 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.touches: Array of current touches where each element contains x, y and id • event.allTouches: Array of all touches where each element contains x, y and id |
Application events
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 the application goes to background. When an application goes to background, ENTER_FRAME and TIMER events are not dispatched until the application is resumed from background. |
APPLICATION_RESUME | Dispatched to all event listeners (broadcast event) when the application is resumed from background. |
Sound & Timer events
SOUND_COMPLETE | Dispatched when a sound has finished playing. |
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. |
UrlLoader events
COMPLETE | Dispatched after all data is received and placed in the data property of the UrlLoader object. |
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 |
Physics events
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.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.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.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.fixtureA: The first fixture in this contact • event.fixtureB: The second fixture in this contact |
PREV.: Playing Sound and Music
NEXT: File system