Learn Corona Engine
Thursday, 12 April 2012
Corona Hello World 3
local beepSound = audio.loadSound( "beep.caf" )
local textObject = display.newText( "Hello World!", 50, 50, native.systemFont, 24 )
textObject:setTextColor( 255,255,255 )
local button = display.newImage( "button.png" )
button.x = display.contentWidth / 2
button.y = display.contentHeight - 50
function button:tap( event )
local r = math.random( 0, 255 )
local g = math.random( 0, 255 )
local b = math.random( 0, 255 )
textObject:setTextColor( r, g, b )
audio.play( beepSound )
end
button:addEventListener( "tap", button )
transition.to( textObject, { time=1000, y=textObject.y+100 } )
Corona Hello World 2
local textObject = display.newText( "Hello World!", 50, 50, native.systemFont, 24 )
textObject:setTextColor( 255,255,255 )
local button = display.newImage( "button.png" )
button.x = display.contentWidth / 2
button.y = display.contentHeight - 50
function button:tap( event )
local r = math.random( 0, 255 )
local g = math.random( 0, 255 )
local b = math.random( 0, 255 )
textObject:setTextColor( r, g, b )
end
button:addEventListener( "tap", button )
Corona Hello World
Hello World
The best (only) way to learn how to use the Corona SDK is by writing an app. To do that we write programs in a language called Lua. In keeping with tradition, let's write a some Lua code that prints “Hello World”.
The big roadblock, here, is figuring out the details of how to actually use the Corona SDK to do this. Once you've got these details mastered, everything gets a lot easier.
So let's get started! What you'll need is a text editor to write your program in. Later, you'll save that file to a folder so that the Corona Simulator can run and show you the results.
In the text editor, type the following:
print( "Hello World" )
Then save it to a file called
main.lua in some folder that's easy to locate. Generally, every program should have its own folder on your system.
To run the program, you need to launch the Corona Simulator. All Corona SDK files should be in the Corona folder in your Applications folder (see Getting Started Guide for more information on how to install the Corona SDK.)
The contents of the SDK will look something like the picture at right. Double-click on the icon for Corona Terminal (the circled icon below).
This will launch a Terminal window and bring up a file dialog. In the dialog, navigate to the folder containing your
main.lua file and click the Open button.
At this point, you will see “Hello World” in the Terminal window:
You will also see a blank simulator window (right) that simulates what would display on the actual phone. In this case, the phone screen remains blank because we're told the program to output to the Terminal.
Let's explain how this program worked. The app launches from the file called
main.lua. The simulator loads this file and follows the instructions contained inside. Generally, an app consists of statements and variables. Statements provide instructions on what operations and computations need to be done; variables store the values of these computations.
In this program, we use a function called
print. A function is just a collection of statements that perform some task. You send inputs into the function calledparameters (or arguments). Some functions return results. In the case of print, all it does is output the arguments as strings to the Terminal.
Hello World
local textObject = display.newText( "Hello World!", 50, 50, native.systemFont, 24 )
textObject:setTextColor( 255,255,255 )
Detecting Touch with Corona
One of the most distinguishing features of today’s mobile devices, especially the Android and iOS devices that are supported by Corona SDK, is the presence of a touch screen. So naturally, as a developer it makes sense for you to know exactly how to detect user touches in your Corona-made apps, so you can have your app to react accordingly.
Without being able to detect the most basic form of user-input on a touch-screen device, a touch, then your app wouldn’t be much of an app at all. But there’s a lot more to touches than you might think, so this tutorial will not only show you how to detect touches, but will also give you some insight on the various aspects of a user touch so you can design your app exactly as you planned it.
Things like touch phases, focus, and dragging should all be familiar concepts by the time you’re finished with this tutorial. This tutorial will only cover basic, single touches. Multi-touch is a more advanced topic and will be saved for another day—it’s important you understand “regular” touch events first.
If you’re not familiar with Corona events, I recommend you read The Corona Event Model Explained first, so you can get an understanding of how events and listeners work. That article also covers the basics of touch events, so when you’re finished reading about the event model you can come back to this tutorial to get a more complete understanding.
Detecting User Touches
User touches can be detected in two different ways. They can be detected on a per-object basis, or detected on the entire screen (also known as “Runtime” or “global” touches). It’s important to know the differences so I’ll go over both of them.
Per-object touches
First thing’s first. Before any particular event can be detected, you must add an event listener. There are two ways to do this, with a table listener or a function listener. Below are examples of both.
For all intents and purposes, ‘Table Listener A’ and ‘Table Listener B’ are identical, with some minor differences. Take a moment to study the differences—you can gain some valuable Lua/Corona knowledge (that’s best explained through examples and practice).
Table Listener A
local obj = display.newImage( "image.png" )
-- touch listener
function obj:touch( event )
-- 'self' parameter exists via the ':' in function definition
end
-- begin detecting touches
obj:addEventListener( "touch", obj )
-- touch listener
function obj:touch( event )
-- 'self' parameter exists via the ':' in function definition
end
-- begin detecting touches
obj:addEventListener( "touch", obj )
Table Listener B
local obj = display.newImage( "image.png" )
-- touch listener
local function onObjectTouch( self, event )
-- 'self' parameter must be defined via function argument
end
-- begin detecting touches
obj.touch = onObjectTouch
obj:addEventListener( "touch", obj )
-- touch listener
local function onObjectTouch( self, event )
-- 'self' parameter must be defined via function argument
end
-- begin detecting touches
obj.touch = onObjectTouch
obj:addEventListener( "touch", obj )
Function Listener
local obj = display.newImage( "image.png" )
-- touch listener
local function onObjectTouch( event )
-- no 'self' parameter exists in this scenario
end
-- begin detecting touches
obj:addEventListener( "touch", onObjectTouch )
-- touch listener
local function onObjectTouch( event )
-- no 'self' parameter exists in this scenario
end
-- begin detecting touches
obj:addEventListener( "touch", onObjectTouch )
I’ll cover what goes IN the listener functions in a moment, but for now, just pay attention to how the listener is added to the object. What all of the above examples do is simply tell Corona to call the listener function whenever a “touch” event is dispatched. Take the third code snippet for example. Here’s what’s going on:
When the user touches ‘obj’, call the onObjectTouch() function.
NOTE: It is important to know that touch events are dispatched several times for a single touch, in separate phases, which I’ll cover in a moment.
Runtime Touches
You can also add a touch listener to the global Corona “Runtime” object, which will detect touches on the entire screen, and aren’t bound to any one object. Runtime touches only support function listeners. Here’s an example:
local function onScreenTouch( event )
-- no 'self' parameter
end
-- begin listening for screen touches
Runtime:addEventListener( "touch", onScreenTouch )
-- no 'self' parameter
end
-- begin listening for screen touches
Runtime:addEventListener( "touch", onScreenTouch )
How to STOP detecting touches
If you want to stop listening to touch events on a specific object (including the global Runtime object), you simply call removeEventListener() in the same exact manner that you called addEventListener().
-- example 1:
obj:removeEventListener( "touch", obj )
-- example 2:
obj:removeEventListener( "touch", onObjectTouch )
-- example3 :
Runtime:removeEventListener( "touch", onScreenTouch )
obj:removeEventListener( "touch", obj )
-- example 2:
obj:removeEventListener( "touch", onObjectTouch )
-- example3 :
Runtime:removeEventListener( "touch", onScreenTouch )
VERY IMPORTANT: Runtime event listeners are never automatically removed. If you add a touch listener (or any kind of listener) to the global Runtime object, it is your sole responsibility to remove the event listeners when you’re finished with them to prevent bugs and crashes from occurring.
Event listeners that are added to individual objects are automatically removed when the object is removed; however, it is still recommended you remove them when you’re finished as well (just to ensure you don’t accidentally “double up” event listeners on an object).
Touch Event Phases
Many Corona beginners run into problems when working with touch listeners, because naturally, you’d expect your listener function to get called once per user touch. However, that is not the case. Touch events have several “phases” which are listed below:
- began – dispatched when the user first touches the object.
- moved – dispatched whenever user moves their finger, as they are touching.
- ended & cancelled – dispatched whenever user lifts their finger or touch is cancelled for whatever reason.
Whenever a touch phase is dispatched, the touch event listener function that you specified when adding the listener will be called. This usually results in a minimum of two (but usually three) calls to your function for every user touch!
You will most-likely need to do different things (or do nothing) depending on which phase of the touch is currently in, so you’ll want to test for that via the event.phaseproperty of your touch listener. Here’s an example:
local function onObjectTouch( self, event )
if event.phase == "began" then
-- Touch has began
elseif event.phase == "moved" then
-- User has moved their finger, while touching
elseif event.phase == "ended" or event.phase == "cancelled" then
-- Touch has ended; user has lifted their finger
end
return true -- IMPORTANT
end
if event.phase == "began" then
-- Touch has began
elseif event.phase == "moved" then
-- User has moved their finger, while touching
elseif event.phase == "ended" or event.phase == "cancelled" then
-- Touch has ended; user has lifted their finger
end
return true -- IMPORTANT
end
The above example shows you how you can test for the different event phases of a single user touch, and do something (or do nothing) during a specific phase. In most cases, the “ended” and “cancelled” phases will be handled together (as shown in the example).
To return true, or not to—THAT is the question.
At the end the the previous example, you probably noticed I put a comment that says “IMPORTANT” next to a return true statement. Whether your function returns true orfalse/nil will affect the outcome of your touch event.
When your touch listener returns true, then that means your touch was successful; the object that was touched is the one that was supposed to be touched during that time. The next event in the sequence will be dispatched properly. If there is a “touchable” object underneath the object that was touched, a touch will not register on the object because the object above successfully captured the touch event.
However, if your listener returns false (or nothing at all), then the touch will be assumed to be faulty and the only event phase you will get is the “began” phase. If there is a “touchable” object underneath the object you touched, then in this case, the touch will “leak through” the object you actually touched and be passed to the next object (assuming you’re touching two objects at once).
This is unfortunately a common cause of confusion for new Corona developers. If you come across the above scenario or something similar, just remember: Return true to keep the touches from going through.
Touch Focus
When you set up your touch listener, in a real-world scenario, it will most-likely resemble something like the following:
local function onObjectTouch( self, event )
if event.phase == "began" then
-- specify the global touch focus
display.getCurrentStage():setFocus( self )
self.isFocus = true
elseif self.isFocus then
if event.phase == "moved" then
-- do something here; or not
elseif event.phase == "ended" or event.phase == "cancelled" then
-- reset global touch focus
display.getCurrentStage():setFocus( nil )
self.isFocus = nil
end
end
return true
end
if event.phase == "began" then
-- specify the global touch focus
display.getCurrentStage():setFocus( self )
self.isFocus = true
elseif self.isFocus then
if event.phase == "moved" then
-- do something here; or not
elseif event.phase == "ended" or event.phase == "cancelled" then
-- reset global touch focus
display.getCurrentStage():setFocus( nil )
self.isFocus = nil
end
end
return true
end
When detecting touch events on a specific object, it is important to set the object as the global “touch focus” to prevent unexpected behavior from occurring, and to ensure your touch event handling goes as smooth as possible. This should be done during the “began” phase (as shown in the example). Touch focus should then be reset during the ended/cancelled phase of the touch so other objects can be touched once the touch is completed, which is also demonstrated in the example.
If it helps, I recommend copying/pasting the above example into a text file to serve as a “touch event” snippet you can re-use in your own apps (it’ll save you a lot of typing).
Other Event Properties
Included with every touch event (to include each of the individual phases) is an eventtable that has a some properties that may be useful to you. They are described below:
- event.id – a unique identifier for the touch event (mostly used for multi-touch).
- event.name – this will always be “touch” for touch events.
- event.phase – the current “phase” of the user’s touch. Possible values include: “began”, “moved”, “ended”, and “cancelled” (hint: I already covered this one)
- event.target – the object that is being touched; same as ‘self’ (when self is available)
- event.time – timestamp of when the event took place.
- event.x, event.y – the x/y coordinates (global/screen) of where the touch is currently taking place.
- event.xStart, event.yStart – the x/y coordinates of where the touch event began (it can be different if the use dragged their finger during the course of a single touch). Example usage here.
You can get a more detailed account of all of the above touch event properties on thetouch event API reference page.
Subscribe to:
Comments (Atom)