Difference between revisions of "Event system"

From GiderosMobile
(update?)
m (formatting)
Line 6: Line 6:
  
 
== Introduction to events ==
 
== 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.
+
Events are the central mechanism to handle responses and they allow to create interactive applications.
<br/>
+
 
 +
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:
 
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.)
 
* 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.
+
* custom events which can be generated by the user.
<br/>
 
  
 
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).
 
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 ==
 
== 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 anyEvent.ENTER_FRAME listener function will be visible at next frame.
+
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.
<br/>
 
  
 
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:
 
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:
Line 28: Line 29:
 
sprite:addEventListener(Event.ENTER_FRAME, onEnterFrame)
 
sprite:addEventListener(Event.ENTER_FRAME, onEnterFrame)
 
</source>
 
</source>
<br/>
 
  
 
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:
 
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:
Line 42: Line 42:
 
sprite3:addEventListener(Event.ENTER_FRAME, onEnterFrame, sprite3)
 
sprite3:addEventListener(Event.ENTER_FRAME, onEnterFrame, sprite3)
 
</source>
 
</source>
<br/>
 
  
 
The last example shows subclassing of the Sprite class and registering Event.ENTER_FRAME:
 
The last example shows subclassing of the Sprite class and registering Event.ENTER_FRAME:
Line 54: Line 53:
 
end
 
end
 
</source>
 
</source>
<br/>
 
  
'''Note:''' Event.ENTER_FRAME event is dispatched to all Sprite instances no matter these instances are on the scene tree or not.
+
'''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:  
+
 
 +
'''Note''': when the ENTER_FRAME event dispatches, the event object contains time and deltaTime. Consider the following example:  
 
<source lang="lua">
 
<source lang="lua">
 
local function onEnterFrame(event)
 
local function onEnterFrame(event)
Line 67: Line 66:
 
== Mouse and touch events ==
 
== 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.
 
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.
<br/>
 
  
 
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.
 
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.
<br/>
 
  
'''Note:''' Even if touch or mouse doesn’t hit the Sprite instance, the instance receives mouse/touch events.
+
'''Note''': even if touch or mouse doesn’t hit the Sprite instance, the instance receives mouse/touch events.
<br/>
+
 
 +
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:
  
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:
 
<br/>
 
 
[[File:Sprite_hierarchy.png]]
 
[[File:Sprite_hierarchy.png]]
<br/>
 
  
 
which is constructed by the code below:
 
which is constructed by the code below:
Line 94: Line 89:
 
C:addChild(F)
 
C:addChild(F)
 
</source>
 
</source>
<br/>
 
  
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.
+
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 ==
 
== 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 this example below, MOUSE_DOWN event is dispatched only to F, E, D and C:
+
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:
 
<source lang="lua">
 
<source lang="lua">
 
local A = Sprite.new()
 
local A = Sprite.new()
Line 117: Line 113:
 
C:addChild(F)
 
C:addChild(F)
 
</source>
 
</source>
<br/>
 
  
'''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).
+
'''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 ==
 
== 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 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:
 
The steps to use Timer class are as follows:
<br/>
 
  
 
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:
 
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:
Line 130: Line 125:
 
local timer = Timer.new(1000, 5)
 
local timer = Timer.new(1000, 5)
 
</source>
 
</source>
<br/>
 
  
 
2- Register to the Event.TIMER event with a listener function:
 
2- Register to the Event.TIMER event with a listener function:
Line 139: Line 133:
 
timer:addEventListener(Event.TIMER, onTimer)
 
timer:addEventListener(Event.TIMER, onTimer)
 
</source>
 
</source>
<br/>
 
  
3- Start the timer.
+
3- Start the timer:
 
<source lang="lua">
 
<source lang="lua">
 
timer:start()
 
timer:start()
 
</source>
 
</source>
<br/>
 
  
 
4- To stop the timer, you can use Timer:stop() function:
 
4- To stop the timer, you can use Timer:stop() function:
Line 151: Line 143:
 
timer:stop()
 
timer:stop()
 
</source>
 
</source>
<br/>
 
  
 
Event.TIMER_COMPLETE event is triggered after finishing the specified number of timer events.
 
Event.TIMER_COMPLETE event is triggered after finishing the specified number of timer events.
<br/>
 
 
 
<source lang="lua">
 
<source lang="lua">
 
local function onTimerComplete(event)
 
local function onTimerComplete(event)
Line 163: Line 152:
 
timer:addEventListener(Event.TIMER_COMPLETE, onTimerComplete)
 
timer:addEventListener(Event.TIMER_COMPLETE, onTimerComplete)
 
</source>
 
</source>
<br/>
 
  
 
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:
 
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:
Line 176: Line 164:
  
 
== ADDED_TO_STAGE and REMOVED_FROM_STAGE Events ==
 
== 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:
+
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:
 
<source lang="lua">
 
<source lang="lua">
 
MySprite = gideros.class(Sprite)
 
MySprite = gideros.class(Sprite)
Line 195: Line 185:
  
 
== Custom events ==
 
== Custom events ==
To dispatch a new custom user defined event, create the event with Event.new() function and dispatch it with EventDispatcher:dispatchEvent(). Example:
+
To dispatch a new custom user defined event, create the event with '''Event.new()''' function and dispatch it with '''EventDispatcher:dispatchEvent()'''. Example:
 
<source lang="lua">
 
<source lang="lua">
 
ClassA = gideros.class(EventDispatcher)
 
ClassA = gideros.class(EventDispatcher)
 
ClassB = gideros.class(EventDispatcher)
 
ClassB = gideros.class(EventDispatcher)
 
function ClassA:funcA(event)
 
function ClassA:funcA(event)
  print("funcA", self, event:getType(), event:getTarget())
+
print("funcA", self, event:getType(), event:getTarget())
 
end
 
end
 
local a = ClassA.new()
 
local a = ClassA.new()
Line 333: Line 323:
 
'''PREV.''': [[Extend_your_application_with_plugins]]<br/>
 
'''PREV.''': [[Extend_your_application_with_plugins]]<br/>
 
'''NEXT''': [[File system]]
 
'''NEXT''': [[File system]]
 
 
<!-- ---- -->
 
<!--{{Special:PrefixIndex/Event}}-->
 

Revision as of 01:24, 10 May 2020

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:

Sprite hierarchy.png

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.: Extend_your_application_with_plugins
NEXT: File system