Sie sind auf Seite 1von 145

Tutorial

-1-
Indice

1. Introduccin al desarrollo con Corona SDK 3


Ejercicios tema 1 9

2. Empezar a programar con LUA ...13


Ejercicios tema 2 ..21

3. Formas, imgenes y texto .23


Ejercicios tema 3 ..35

4. Eventos e interaccin ....39


Ejercicios tema 4 ......47

5. Timers y animaciones ...50


Ejercicios tema 5 ..58

6. Motor Fsico ..61


Ejercicios tema 6 ..71

7. Hardware y multimedia .....74


Ejercicios tema 7 ..85

8. Gestin de mapas y GPS ..90


Ejercicios tema 8 ..97

9. Diseando la interfaz de usuario ..100


Ejercicios tema 9 105

10. Entrada y salida ..108


Ejercicios tema 10 ..116

11. Composer y widget .120


Ejercicios tema 11 ..130

12. Motor fsico Parte 2 ....135


Ejercicios tema 12 ..142

-2-
Tema 1
Introduccin al desarrollo con

Corona SDK
Corona es un kit de desarrollo de software que permite la creacin de
aplicaciones mviles para iPhone, iPad y dispositivos Android.

Su objetivo es el de ahorrar el mayor tiempo posible desarrollando


proyectos mviles al compartir cdigo entre los diferentes sistemas

Tiene una versin gratuita para desarrollar que se puede descargar desde
el siguiente enlace:

https://developer.coronalabs.com/downloads/corona-sdk

El proceso de desarrollo con Corona SDK es muy simple:

Diseamos los elementos de audio, vdeo, imagen y animacin con


alguna herramienta destinada a ello (Photoshop, Premiere, Audacity...).

Rpido desarrollo de la aplicacin haciendo uso del simulador


multiplataforma para previsualizar nuestro proyecto en los diferentes
dispositivos.

Publicacin con muy pocos clicks del resultado de nuestro proyecto


en la App Store y en Google Play

El lenguaje de programacin empleado para el desarrollo con Corona SDK


es LUA:

-3-
LUA es un lenguaje de programacin imperativo (se basa en estados
de la aplicacin que podemos ir modicando mediante sentencias),
estructurado y bastante ligero

Slo funciona embebido en un cliente antrin, este caso, el


framework Corona

Ofrece un buen soporte para la programacin orientada a objetos,


programacin funcional y programacin orientada a datos

Corona SDK - LUA

A travs del uso de funciones C, Lua puede ser aumentado para


abarcar un amplio rango de diferentes dominios, creando as lenguajes
de programacin personalizados.

LUA es software libre y se proporciona sin garantas, tal y como


especica su manual de referencia en el sitio ocial www.lua.org.

Caractersticas de Corona

Posee un motor OpenGL-ES propio que nos permite realizar grandes


manipulaciones grcas de manera muy sencilla

Destaca por su desarrollo multiplataforma. Permite crear aplicaciones tanto


para iOS (iPhone y iPad), como para Android.

Cuenta con controles nativos para el acceso al dispositivo y a los diferentes


elementos hardware como cmara, acelermetro, GPS... etc.

Las aplicaciones creadas con Corona se pueden optimizar para ocupar el


menor espacio posible. A partir de 400ks.

-4-
Instalacin de Corona SDK

Para obtener la versin gratuita del framework, con la que podremos crear
aplicaciones de manera ilimitada, tendremos que crearnos una cuenta de
desarrollador en la web ocial de Corona

http://www.coronalabs.com/

Debemos descargarnos e instalar la aplicacin correspondiente a nuestro


sistema operativo (Mac OS X o Microsoft Windows)

-5-
Con la instalacin obtendremos una carpeta en nuestra mquina con las
siguientes aplicaciones

-6-
Contamos con tres aplicaciones para poder acceder al Simulador de
Corona (Corona Simulator, Corona Terminal y debugger)

Las tres nos dan acceso al mismo simulador, slo que las dos ltimas se
acompaan de herramientas para poder realizar la depuracin de cdigo a
travs del terminal.

El resto de directorios corresponden a herramientas, recursos y diferentes


ejemplos donde podemos apreciar la diversidad de aplicaciones que
podemos desarrollar con Corona SDK
Corona SDK

Simulador Corona SDK

Desde la ventana principal de la aplicacin simulador podremos acceder a


todos nuestros proyectos, as como crear uno nuevo o ejecutar cualquiera de
los ejemplos que nos vienen dentro del directorio SampleCode

Si abrimos cualquier proyecto, ejecutaremos automticamente la vista del


simulador, la cual podemos cambiar para realizar las pruebas pertinentes en
los diferentes dispositivos.

-7-
Para editar el cdigo de nuestro proyecto se usar el editor de texto que
tengamos denido por defecto en nuestra mquina. Para cambiar esto
tendremos que cambiar la aplicacin asociada a los archivos de tipo .lua

Al salvar un chero .lua correspondiente al proyecto activo en el simulador,


ste nos preguntar si deseamos volver a cargar la aplicacin para poder
observar los cambios en el dispositivo. Esta opcin se puede desactivar.

-8-
Ejercicios Tema 1

Ejercicio 1

Vamos a realizar la instalacin completa de Corona SDK y comprobaremos


su correcto funcionamiento en nuestra mquina, para as poder afrontar el
resto de temas sin problemas.

Para comenzar con la instalacin, debemos acceder a la web ocial de


Corona para darnos de alta como desarrolladores
(https://developer.coronalabs.com/user/register)

Una vez estemos correctamente registrados e iniciemos sesin en la pgina,


podemos descargarnos el sdk desde la propia web, distinguiendo el sistema
operativo sobre el que vamos a trabajar
(https://developer.coronalabs.com/downloads/corona-sdk)

-9-
Procedemos a instalar el ejecutable que hemos descargado de la web y
tendremos acceso a la carpeta con las herramientas de Corona SDK, en el
directorio donde hayamos especicado durante la instalacin. Los
ejecutables que se han instalado en nuestra mquina son los siguientes:

- 10 -
Si hacemos doble click sobre la aplicacin Corona Simulator, abrimos la
interfaz principal para desarrollar con Corona SDK

- 11 -
En el men de la aplicacin podemos acceder a File -> Open.. y si
accedemos a la carpeta Sample Codes del directorio donde hemos instalado
Corona SDK, podemos observar un gran nmero de ejemplos.

Prueba a ejecutar algunos ejemplos que vienen por defecto con Corona SDK
para visualizar cmo se ven reejados en el simulador.

Ampliacin 1

Cambia el tipo de simulador en el que se ejecuta la aplicacin accediendo al


men de Corona SDK en Window -> View As

Ejercicio 2

En vez de ejecutar la aplicacin Corona Simulator, vamos a ejecutar la


aplicacin Corona Terminal. Prueba a seguir los mismos pasos que el
ejercicio anterior y observa los mensajes que van apareciendo en el terminal.

Para acceder al cdigo que se est ejecutando slo hay que abrir el men de
la aplicacin en la ruta File -> Open project in Editor...

- 12 -
Tema 2
Empezar a programar con LUA

LUA

Lua es un lenguaje de programacin extensible el cual debe funcionar


dentro de un programa contenedor o simplemente antrin.

Se pretende que Lua sea usado como un lenguaje de script potente y ligero
para cualquier programa que lo necesite.

Los programas en Lua no son interpretados directamente, sino compilados


a cdigo bytecode, que es ejecutado por la mquina virtual de Lua.

El proceso de compilacin es normalmente transparente al usuario y se


realiza en tiempo de ejecucin, pero puede hacerse con anticipacin para
aumentar el rendimiento y reducir el uso de la memoria al prescindir del
compilador.

LUA -Variables

Los nombres de las variables pueden ser denidos con cualquier


combinacin de letras, dgitos y caracteres de subrayado (underscore)
siempre y cuando no comiencen por un dgito.

En Lua hay diferencia entre maysculas y minsculas a la hora de denir


los nombres de las variables

and - palabra reservada del sistema


And y AND - nombres diferentes y vlidos

Como convencin, las nombres de variables que empiezan por un carcter


de subrayado seguido por letras maysculas estn reservadas para su uso
como variables globales internas de Lua (ej: _VERSION)

Lua es un lenguaje dinmicamente tipado, es decir, las variables no tienen


tipo, slo tienen tipo los valores. No existen deniciones de tipo en el
lenguaje ya que cada valor almacena su propio tipo.

- 13 -
Existen 8 tipos bsicos en Lua:

nil, boolean, number, string, function, userdata, thread y table

El tipo nil es el valor nulo, cuya principal funcin es la de ser diferente a


cualquier otro valor

boolean es el tipo de los valores true (verdadero) o false (falso)

Tanto nil como false hacen que una condicin sea falsa, cualquier otro valor
la hace verdadera

number representa nmeros reales en coma otante y doble precisin

String representa una tira de caracteres. Lua trabaja con 8 bits. Los strings
pueden contener cualquier carcter de 8 bits.

El tipo userdata se incluye para permitir guardar en diferentes espacios de


memoria distintas funciones creadas en C. No tienen asociadas operaciones
predenidas en Lua, excepto la asignacin y el test de identidad.

El tipo thread representa procesos de ejecucin y es usado para


implementar co-rutinas. Estas rutinas no deben ser confundidas con las
propias del sistema operativo, ya que Lua permite la gestin de diferentes
procesos incluso en aquellos sistemas operativos que no lo soporten.

El tipo table implementa arrays asociativos, es decir, arrays que no slo


pueden ser indexados con nmeros, si no que pueden como clave cualquier
valor diferente de nil.

Debido a que las funciones en Lua son valores de primera clase los campos
de las tablas pueden contener funciones, por lo que las tablas pueden
contener tambin mtodos.

- 14 -
Las variables pueden ser de tres tipos: locales, globales y campos de tabla

Por defecto todas las variables son de tipo global a no ser que sean
declaradas explcitamente como locales, con la palabra reservada local.

Las variables locales tienen un mbito (scope) denido. Se puede acceder


a ellas desde dentro de las funciones denidas en su mismo mbito.

LUA -Tablas

Las tablas son variables utilizadas para almacenar dentro otros valores.
Sera el tipo equivalente a lo que conocemos como arrays en otros lenguajes
de programacin.

Para inicializar nuestras tablas tenemos dos posibilidades:

miTabla = {} creamos una tabla vaca

miTabla = { 1, 4, Test, true} en este caso le asignamos directamente


4 elementos nada ms crearla. Los ndices
son de tipo numrico

miTabla = { latitud = 30.05, longitud = -3.07, direccion = C/ Prueba 123}


Tambin asignamos directamente los valores, pero en este caso
los ndices no son de tipo numrico

- 15 -
Para acceder a los valores almacenados en una tabla tambin podemos
proceder de varias maneras:

miTabla = { 1, 4, Test, true}

miTabla [3] accedemos al valor de la tabla situado en la posicin 3, en


este caso Test

miTabla = { latitud = 30.05, longitud = -3.07, direccion = C/ Prueba 123}

miTabla.latitud en este caso accedemos al valor de la tabla cuya clave es


latitud. En este caso, 30.05

LUA -Tablas (funciones)

Podemos conocer el tamao de una tabla con el operador #

miTabla = { 1, 4, Test, true} la sentencia #miTabla nos devolver el tamao de la


tabla. En este caso 4

Con la funcin table.sort ordenamos los valores de la tabla ignorando las


claves. (La ordenacin se basa en el algoritmo quicksort)

tablaCiudades = {"Zaragoza", "Barcelona", "Madrid", "Valencia", "Almeria"}


table.sort (tablaCiudades)

for i=1, #tablaCiudades, 1 do


print (tablaCiudades[i])
end

Nos muestra el siguiente


resultado en el Terminal:
Almeria
Barcelona
Madrid
Valencia
Zaragoza

- 16 -
La funcin table.concat recoge una tabla de strings o de nmeros y
devuelve otro string concatenando todos los valores de la tabla.

tablaCiudades = {"Zaragoza", "Barcelona", "Madrid", "Valencia", "Almeria"}

concatenada = table.concat (tablaCiudades)

En la variable concatenada obtendremos el valor


ZaragozaBarcelonaMadridValenciaAlmeria

Con table.remove eliminamos el ltimo elemento de la tabla y el valor es


devuelto por la funcin

ultimoValor = table.remove (tablaCiudades)

En la variable ultimoValor obtendremos el valor


Almeria

Para recorrer una tabla en Lua, tenemos diferentes opciones. La primera y


ms sencilla es usando un bucle for a partir de la longitud de la tabla

tablaCiudades = {"Zaragoza", "Barcelona", "Madrid", "Valencia", "Almeria"}

for i=1, #tablaCiudades Resultado en el Terminal:


do print (tablaCiudades [i])
end Zaragoza
Barcelona
Madrid
Valencia
Almeria

Otra forma para recorrer la tabla, obteniendo el mismo resultado es


utilizando la estructura for ... inpairs

for i, ciudad in ipairs(tablaCiudades) do Cada iteracin del bucle, la


print(ciudad) variable ciudad toma el valor de la
end tabla correspondiente

- 17 -
LUA - Control de ujo

if [condicion] then else | elseif [condicion]

La sentencia if comprueba la condicin y ejecuta la parte del then si esta


condicin se cumple, si no, se ejecuta la parte del else, la cual es opcional

if a < 0 then Si el valor de la variable a es menor que cero, se le


a=0 asigna el valor cero. Si es mayor que cero, no se
end hace nada

if a < 0 then Si el valor de la variable a es menor que cero, se le


a=0 asigna el valor cero. Si es mayor que cero, se le
else asigna el valor 20
a = 20
end

Para evaluar distintas condiciones, utilizaremos la sentencia if anidada


utilizando elseif

if n == 1 then
print (N es 1) Dependiendo del valor de N,
elseif n == 2 then obtendremos el mensaje
print (N es 2) correspondiente a travs
elseif n == 3 then del Terminal
print (N es 3)
end

while [condicion] do

Se ejecuta el proceso incluido dentro del bucle hasta que la evaluacin de


la condicin devuelva false

n=2
while n<10 do Mientras que la variable n sea menor que 10,
print(n) mostrar en el terminal el valor de n

- 18 -
n = n+1
end
Debemos controlar en el interior del bucle la condicin de salida para evitar
que la ejecucin del bucle sea innita

Bucle for

El bucle for, puede ser denido de varias maneras:

La formula ms comn para el uso del for es:

for [valor inicial], [valor nal], [aumento] do

end

for i=0, 10, 1 do En este ejemplo mostraremos en el


print (i) terminal los nmeros del 0 al 10
end

Otra de las formas de realizar un for y que suele ser de bastante utilidad en
el recorrido tablas es:

for i, v in ipairs(a) do

end

local tabla = {Enero, Febrero, Marzo, Abril} Este ejemplo nos mostrar a travs del
for i, mes in ipairs(tabla) do Terminal todos los elementos de la
print (mes) tabla, en este caso, 4 meses
end

- 19 -
LUA Funciones

Las funciones son una agrupacin de sentencias y declaraciones de


variables que cumplen un objetivo comn

En Lua, las funciones pueden llevar tantos parmetros como sea necesario,
siempre incluidos entre parntesis. Incluso puede no llevar ninguno

Para especicar el valor devuelto por la funcin, en el caso de que sea


imprescindible, utilizamos la palabra reservada return

function nombreFuncion (parametro1, parametros2... parametroN)

[return valorDevuelto]

end

Una de las grandes ventajas de las funciones en Lua es que pueden


devolver varios valores.

- 20 -
Ejercicios Tema 2
Ejercicio 1 - Hola Mundo Lua

Para comenzar con los ejercicios, vamos a arrancar la aplicacin Corona


SDK, teniendo en cuenta que escogemos la opcin que nos permite
visualizar el terminal.

En el men de la aplicacin, accedemos a File -> New Project y


completamos los datos que nos piden:

-App Name: HolaMundo


-Choose Template: Blank
-Screen Size: Phone preset | Width: 320 | Height: 480
-Default Orientation: Upright

Una vez creado el proyecto y seleccionado el directorio donde lo vamos a


guardar, seleccionamos abrir el editor, para poder modicar nuestro cdigo.
En este momento, tendremos algo as, en nuestro chero main.lua:

-----------------------------------------------------------------------------------------
--
-- main.lua

-----------------------------------------------------------------------------------------

- Your code here

Para terminar nuestro primer proyecto Lua, podemos agregar la siguiente


lnea de cdigo:

-----------------------------------------------------------------------------------------
--
-- main.lua

-----------------------------------------------------------------------------------------

- Your code here


- 21 -
print ("Hola mundo Lua")
Salvamos el chero main.lua y automticamente, el simulador detecta
cambios y nos refresca la vista del modelo de mvil que tengamos
seleccionado.

Para poder observar el mensaje que hemos programado, debemos acceder


al Terminal.

Ejercicio 2

A partir de la siguiente tabla:

local miTabla = {Pajaro, Perro, Tiburn, Pulpo}

Crea un mtodo que reciba como parmetro un nmero e imprima en el


Terminal la posicin de la tabla correspondiente a ese nmero

Ejercicio 3

Crea un mtodo que reciba como parmetro un nmero N y muestre por el


Terminal los N primeros nmeros primos.

- 22 -
Tema 3
Formas, Imgenes y Texto

Formas Geomtricas Bsicas

Desde la API de Corona tenemos la posibilidad de acceder a una serie de


mtodos que nos permiten mostrar elementos geomtricos en nuestros
dispositivos.

Los elementos que podemos representar mediante mtodos de Lua en el


simulador son: lneas, rectngulos, crculos, elipses y rectngulos
redondeados

display.newLine ( x1, y1, x2, y2)

Con el mtodo newLine podemos especicar una lnea recta entre dos
puntos

Los parmetros (x1, y1) indican el punto de inicio de la recta. Los


parmetros (x2, y2) indican el punto nal de la recta.

El color por defecto es el blanco

display.newLine( 120, 100, 300, 120)

Podemos especicar el color y el tamao de la recta con el mtodo setColor


y el atributo width

Los colores deben especicarse con valores especcos para el Rojo, Verde
y Azul. El nmero que debe indicarse debe estar entre 0 y 255.

- 23 -
local recta =
display.newLine( 100,50, 270,350 )
recta:setColor( 1, 0, 0 )
recta.width = 6

display.newRect (left, top, width, height)

Con este mtodo especicamos la creacin de un rectngulo en nuestra


aplicacin

Los parmetros left y top especican la situacin de la coordenada del


centro de la gura. Los parmetros width (anchura) y height (altura)
especican el tamao de nuestro rectngulo.

display.newRect ( 200, 250, 150, 50)

- 24 -
Si almacenamos la creacin de nuestro rectngulo en una variable,
podemos modicar el relleno y el trazo.

local miRect = display.newRect(175, 250,


200, 100)
miRect.strokeWidth = 6
miRect:setFillColor(0, 1, 0)
miRect:setStrokeColor(1, 0, 0)

Con el mtodo strokeWidth especicamos el tamao del trazo del


rectngulo

Con setFillColor denimos el color de relleno del rectngulo

El mtodo setStrokeColor dene el color del trazo

Los colores se denen indicando los valores de Rojo, Verde y Azul con
nmeros entre 0 y 1. No obstante, si se dene un nico parmetro se
trabajar con una escala de grises, siendo 1 el blanco y 0 el negro.

display.newRoundedRect( left, top, width, height, cornerRadius )

Funciona como el mtodo anterior, slo que en este le tenemos que


especicar el radio de curvatura en las esquinas del rectngulo con el ltimo
parmetro.

local miRoundRect =
display.newRoundedRect(135, 200, 150, 150, 20)
miRoundRect.strokeWidth = 3
miRoundRect:setFillColor( 1, 1, 0)
miRoundRect:setStrokeColor(0, 0, 1) - 25 -
display.newCircle( xCenter, yCenter, radius )

Este mtodo nos permite dibujar un crculo especicando el punto central


del crculo (xCenter, yCenter) y el radio (radius)

local miCirc = display.newCircle( 150, 200, 100 )

Imgenes

display.newImage( lename [,centerx, centery] )

Con este mtodo podemos situar en nuestra aplicacin imgenes. Para ello
debemos incluir las imgenes en el directorio de nuestra aplicacin y a travs
del parmetro lename debemos especicarle la ruta exacta donde poder
encontrarlas.

Mediante top y left, que son parmetros opcionales, podemos especicar


las coordenadas donde vamos a situar la imagen. Si no especicamos
coordenadas, el centro de la imagen se sita en la coordenadas (0,0) de la
vista que la contenga.

- 26 -
display.newImage ("img/corona.jpg", 200, 250)

local imagen = display.newImage( "img/corona.jpg" )


imagen:translate( 80, 200 )

Creamos una imagen y con translate le asignamos una nueva posicin.

imagen:setFillColor( 1, 0, 0 )

Se le asigna un color de relleno a la imagen, siguiendo la asignacin de


valores para Rojo, Verde y Azul (valores entre 0 y 255).

imagen.isVisible = true

Propiedad de la imagen para mostrarla (true) u ocultarla (false) dentro de la


vista donde se encuentra

imagen:removeSelf()

Cargando imgenes remotas

- 27 -
display.loadRemoteImage
( url, method, listener, destFilename [, baseDir] [, x, y] )

Accedemos, a travs de este mtodo a una imagen alojada en un servidor


de internet para mostrarla en nuestra aplicacin.

Mediante el parmetro url le especicamos la direccin donde se encuentra


alojada la imagen.

Con el parmetro method indicamos cmo se va a realizar la peticin sobre


la imagen. Tiene dos valores posibles, GET (valor por defecto) y POST

En el parmetro listener tenemos que especicar el nombre de un mtodo


en el que vamos a poder tratar la respuesta de la peticin al servidor

El mtodo que especiquemos en el parmetro listener se llamar una vez


se complete la peticin http para la descarga de la imagen.

En este mtodo tendremos acceso a un objeto de tipo event dentro


del cual podremos acceder a 3 propiedades diferentes:

event.response - un string que contiene la ruta de destino del chero


creado.
event.target - el nuevo objeto creado una vez se descarga la imagen.
event.isError - un valor de tipo booleano que indica si se ha producido
un error de red (true) o no (false).

En el parmetro destFilename indicamos cual ser el nombre de la imagen


descargada dentro del sistema de archivos propio de nuestro dispositivo.

El parmetro baseDir, que es opcional, nos sirve para indicar dnde vamos
a guardar la nueva imagen dentro del sistema de archivos de nuestro
dispositivo.

Podemos denir las coordenadas exactas donde vamos a situar nuestra


imagen, con los parmetros opcionales x e y.

- 28 -
local function networkListener( event )
if ( event.isError ) then
print ( "Error en la red - Fallo en la descarga" )
end
end

display.loadRemoteImage( "http://developer.anscamobile.com/demo/hello.png",
"GET", networkListener, "helloCopy.png", system.DocumentsDirectory, 160,200)

Estamos lanzando una peticin GET sobre la url indicada para que nos
devuelva la imagen. La respuesta de esta imagen la estamos tratando en el
mtodo networkListener y le indicamos que se guarde en el directorio de
documentos por defecto con el nombre helloCopy.png. La situamos en el
punto (160,200) dentro de nuestra vista.

Manipulando imgenes

Contamos con una serie de mtodos que nos permiten modicar las
propiedades ms importantes de nuestras imgenes:

- 29 -
local img = display.newImage ("img/corona.jpg")
img.x = 200
img.y = 300

Podemos modicar la posicin de una imagen accediendo a sus atributos x


ey

Con el atributo alpha, podemos especicar la transparencia de la imagen. El


valor que se indica vara entre 0 y 1

local img = display.newImage ("img/corona.jpg", 200, 175)


img.alpha = 0.6

Podemos denir la escala en la que se muestra la imagen accediendo a los


atributos xScale e yScale.

- 30 -
local img = display.newImage ("img/corona.jpg", 160,230)
img.xScale = 3
img.yScale = 5

Podemos modicar la rotacin de la imagen creada modicando el atributo


rotation. El valor se debe especicar en grados.

local img = display.newImage ("img/corona.jpg", 200, 175)


img.rotation = 70

Para modicar el tamao de la imagen tenemos los atributos width (ancho)


y height (alto)

- 31 -
local img = display.newImage ("img/corona.jpg", 190,175)
img.width = 250
img.height = 50

Mscaras sobre imgenes

graphics.newMask( lename )

Con este mtodo podemos crear mscaras a partir de una imagen, la cual
denimos a travs de lename, para aplicrselas a otras imgenes
diferentes.

La imagen que acta como mscara, tiene unas caractersticas concretas


que debe cumplir:

Su altura y su anchura, deben ser nmeros mltiplos de 4

La imagen de mscara debe llevar un borde negro alrededor de,

Mscara Imagen sobre la que se aplica la mscara

- 32 -
local img = display.newImage ("img/corona.jpg", 175,200)

img.width = 190
img.height = 190

local mask = graphics.newMask ("img/circlemask.png")


img:setMask (mask)

Manejando Texto

display.newText( string, Xcenter, Ycenter, [width, height,] font, size )

Con el mtodo newText podemos mostrar una cadena de texto (string)


situada en las coordenadas Xcenter, Ycenter, de la vista que lo contiene.

Como parmetros opcionales, podemos denir el tamao del texto que


vamos a mostrar con width y height

A travs del parmetro font podemos denir la fuente que vamos a usar
para el texto. Se puede especicar las fuentes del sistema por defecto con
native.systemFont y native.systemFontBold

Para obtener una lista con todas las fuentes disponibles, podemos ejecutar
el cdigo siguiente, con la llamada al mtodo native.getFontNames()

local fuentes = native.getFontNames()

for i=1, #fuentes, 1 do


print (fuentes[i])
end

- 33 -
Con el parmetro size, especicamos el tamao del texto, denido en
pxeles

local myText = display.newText("Hello World!", 160, 100, native.systemFont, 36)

- 34 -
Ejercicios Tema 3
Ejercicio 1

A partir de lo aprendido en el tema 3, vamos a dibujar un rectngulo marrn


en un nuevo proyecto de Corona

local rect = display.newRect (150,300,60,100)


rect:setFillColor (0.56,0.33,0.15)

Ahora vamos a nalizar nuestra obra maestra dndole un toque de


naturaleza al dibujo. Ya que tenemos el tronco, vamos a dibujar la copa del
rbol.

Para dibujar polgonos ms complejos, Corona nos ofrece la posibilidad de


utilizar las llamadas Polylines.

Podemos dibujar una lnea con los mtodo ya conocidos y posteriormente,


agregarle, todos los puntos que queramos (mediante un par de coordenadas)
para completar todos los vrtices del polgono que queramos crear.

local copaArbol = display.newLine (120, 250, 90, 230)


copaArbol:append(80,200, 100,150, 170,140, 220,200, 180,250, 120,250)
copaArbol:setColor (0, 1, 0)

- 35 -
El polgono creado para la copa del rbol no se puede rellenar sin usar
complejos algoritmos en los que no vamos a entrar de momento.

Trata de completar el ejercicio para obtener un dibujo como el de la imagen

- 36 -
Ejercicio 2

Intenta realizar el siguiente dibujo. No utilices coordenadas absolutas para


ello. Puedes usar las coordenadas (x, y) y las propiedades width y height de
cada objeto para situar los dems.

NOTA: con display.contentWidth y display.contentHeight puedes obtener el


ancho y el alto del dispositivo

Ejercicio 3

En este ltimo ejercicio vamos a insertar un gradiente por debajo de nuestro


dibujo anterior

- 37 -
Para ello, podemos usar la funcin de la librera graphics newGradient.

local g = graphics.newGradient( color1, color2 [ , direction] )

color1 y color2 son dos tablas que determinan el color de inicio y el color de
n (Ej: {1,1,1})

direction determina la direccin del gradiente (up, down, left, right)

el gradiente creado se le puede aadir a un rectngulo a travs de su funcin


setColor

- 38 -
Tema 4
Eventos e interaccin
Detectando eventos

Los Eventos son la principal fuente de informacin desde la cual podemos


recoger datos y as crear una interaccin con el usuario de nuestra
aplicacin.

Existen muchas maneras para detectar los Eventos. Por ejemplo, cada uno
de los elementos de nuestra aplicacin puede ser tratado como un botn
interactivo. Esto nos ofrece una gran exibilidad a la hora de estructurar
nuestras interfaces grcas.

Durante este tema, aprenderemos cmo agregar diferentes eventos sobre


los objetos mostrados en nuestra vista, as como la forma de manejar
eventos de tipo global, como puede ser la orientacin de nuestro dispositivo.

La funcin addEventListener

Objeto:addEventListener ( eventName, listener)

Con esta funcin vamos a poder indicar qu evento vamos a registrar sobre
un objeto en concreto y cmo vamos a proceder a tratarlo.

En este caso, Objeto se tratara de la entidad sobre la que vamos a recoger


el evento en el que estamos interesados. Puede ser cualquier elemento que
tengamos situado en la vista de nuestra aplicacin.

Con el parmetro eventName podemos especicar el tipo de evento que


vamos a recoger.

En listener debemos especicar el nombre de la funcin que vamos a


ejecutar una vez tenga lugar el evento que estamos capturando.

Para dejar de escuchar un evento concreto sobre un objeto, debemos usar


el mtodo removeEventListener

- 39 -
Eventos Globales

Hablamos de Eventos Globales cuando hacemos referencia a ese tipo de


eventos que no estn directamente relacionados con ningn objeto en
concreto.

Envan informacin a todos los listeners (mtodos para capturar los


eventos) que se hayan implementado para tratarlos.

A travs de estos eventos podemos acceder a la informacin de la


orientacin de nuestro dispositivo, el estado de nuestra aplicacin, el uso del
acelermetro y la brjula...

Al no asignarse sobre ningn objeto en concreto, tendremos que asignarlos


a la clase Runtime

enterFrame

Este evento se lanza cada vez que se actualice la vista de nuestra


aplicacin. Por defecto son 30fps, pero este valor se puede modicar si
accedemos al archivo cong.lua que se crea en la carpeta de nuestro
proyecto.

Capturando este evento podramos, por ejemplo modicar el contenido de


nuestra pantalla en tiempo real en funcin de las acciones del usuario.

function capturarEvento (event)


print (event.name)
print (event.time)
end

Runtime:addEventListener("enterFrame", capturarEvento )

System

Este evento se lanza para avisar a nuestra aplicacin de eventos externos,


como cuando la aplicacin tiene que entrar en suspenso por la entrada de
una llamada telefnica.

- 40 -
Podemos acceder a la propiedad type del evento para saber qu se est
lanzando. Los diferentes tipos para el evento system son:

applicationStart - Ocurre cuando la aplicacin se lanza y todo el


cdigo en main.lua se ha ejecutado.

applicationExit - Se captura cuando el usuario cierra la aplicacin.

applicationSuspend - Ocurre cuando la aplicacin debe suspenderse


por la entrada de una llamada o porque el dispositivo entra en
inactividad por falta de uso. Mientras que la aplicacin est
suspendida no recibe eventos de ningn tipo.

applicationResume - Este evento se lanza cuando la aplicacin


vuelve a ejecucin despus de un estado de suspensin.

Con el siguiente ejemplo detectamos cuando arranca nuestra aplicacin y


mostramos un mensaje. Esto puede ser til para congurar todos los
parmetros iniciales de nuestra aplicacin

function capturarEvento (event)


if (event.type == "applicationStart") then
print ("Acaba de arrancar la aplicacion")
end
end

Runtime:addEventListener("system", capturarEvento )

Orientation

Con este tipo de evento podemos detectar los cambios en la orientacin de


nuestro dispositivo. Slo estar disponible para telfonos que tengan soporte
para acelermetro.

Los diferentes tipos (event.type) de orientacin a los que podemos acceder


son: portrait, landscapeLeft, landscapeRight, portraitUpsideDown, faceUp,
faceDown.

Si accedemos a la propiedad delta del evento, obtenemos la diferencia

- 41 -
entre la orientacin inicial y la nal.

local label = display.newText( "portrait", 100, 200, nil, 30 )

local function onOrientationChange( event )


label.text = event.type
local newAngle = label.rotation - event.delta
transition.to( label, { time=150, rotation=newAngle } )
end

Runtime:addEventListener( "orientation", onOrientationChange )

accelerometer

El evento de acelermetro nos permite capturar movimientos repentinos de


nuestro dispositivo y determinar su orientacin en relacin a la gravedad.

Este evento slo puede ser tratado por dispositivos con soporte para
acelermetro.

Podemos capturar la aceleracin del dispositivo de dos maneras, en


relacin a la gravedad, con los parmetros xGravity, yGravity y zGravity, o
la aceleracin instantnea con los parmetros del evento xInstant, yInstant
y zInstant.

Si el parmetro del evento isShake es verdadero, nos indica que el usuario


est agitando el dispositivo.

local label = display.newText( "En reposo", 100, 200, nil, 30 )

local function detectaAcelerometro( event )


if (event.isShake == true) then
label.text = "Agitado"
end
end

Runtime:addEventListener( "accelerometer", detectaAcelerometro )

- 42 -
Heading

En este caso vamos a ser capaces de detectar los eventos generados por
la brjula del dispositivo, si est disponible. Hay que tener en cuenta que el
simulador de Corona no detecta este tipo de eventos

Podemos acceder a dos atributos del evento que nos devuelven la


desviacin en grados con respecto al norte geogrco (geographic) o al
norte magntico (magnetic). Android slo soporta el acceso al atributo
magnetic. heading

local function detectaBrujula( event )


print (event.magnetic)
end

Runtime:addEventListener( "heading", detectaBrujula )

memoryWarning

Este evento slo est disponible para iOS

Se ejecuta cuando recibimos un aviso por algn error determinado de


memoria. Apple sugiere capturar este evento y en caso de ser lanzado,
liberar el mayor nmero de memoria posible para subsanarlo

El evento no contiene ningn atributo.

local function capturandoMemoriaBaja( event )


print( "Recibido aviso de memoria" )
end

Runtime:addEventListener( "memoryWarning", capturandoMemoriaBaja )

- 43 -
Touch Events

Cuando el usuario toca la pantalla se genera un evento de toque sobre el


objeto que ha sido pulsado. El evento puede ser interceptado y tratado por
cualquier objeto disponible en nuestra vista.

Los eventos se propagan entre todos los objetos con capacidad para
tratarlo hasta que uno de ellos lo capture y ejecute el cdigo correspondiente
para manejarlo.

La propagacin del evento se realiza siguiendo la jerarqua de disposicin


de los objetos en nuestra vista, es decir, el primero en recibirlo ser el que se
encuentre encima de todos los dems.

Si el evento no ha sido capturado por ninguno de los objetos de nuestra


vista, se propaga como un evento global para poder ser capturado por el
objeto Runtime

Touch

Detectamos cuando el usuario pulsa sobre el objeto al que le hemos


asignado el listener.

Cuando se produce el toque, se lanza una secuencia de estados que


podemos capturar para poder realizar diferentes acciones en cada una de las
fases.

Las propiedades del evento a las que podemos acceder son las siguientes:

event.x - es la posicin x de las coordenadas del toque dentro de la


pantalla
event.y - es la posicin y de las coordenadas del toque dentro de la
pantalla
event.xStart - se trata de la coordenada x donde ha comenzado el
toque
event.yStart - la coordenada y donde ha comenzado el toque
event.phase - Las diferentes fases del toque touch

- 44 -
Los diferentes estados a los que podemos acceder dentro del evento de
toque son los siguientes:

began - nos indica que un dedo empieza a tocar la pantalla del


dispositivo

moved - un dedo se desliza por la pantalla

ended - un dedo deja de tocar la pantalla

cancelled - el sistema cancela el seguimiento del toque

local img = display.newImage( "img/imagina.jpg", 100, 200)

local function capturaEventoToque(event )


if (event.phase == "began") then
print ("Comienza el toque")
elseif (event.phase == "moved") then
img.x = event.x
img.y = event.y
elseif (event.phase == "ended") then
print ("Fin del toque")
end
return true
end

img:addEventListener( "touch", capturaEventoToque )

touch (multitouch)

Lo primero que debemos hacer para permitir los eventos con varios toques
sobre la pantalla es decrselo a nuestra aplicacin con la siguiente sentencia:

system.activate( "multitouch" )

- 45 -
Una vez tengamos esto activado, cuando se reciban mltiples toques, estos
se trataran individualmente, recogindose en sus respectivos listeners. Lo
nico que tendrn en comn, ser su propiedad de timestamp.

Creacin de eventos propios

En Corona podemos crear eventos propios y asignrselos para su captura


sobre objetos de nuestra aplicacin o sobre el propio objeto Runtime

En cualquiera de los dos casos, se debe asignar el evento sobre el objeto


que lo captura, utilizando el siguiente mtodo:

object:dispatchEvent(event)

El parmetro event debe ser una tabla donde se especique el identicador


del evento (name) y el objeto que ser el encargado de recibir dicho evento
(target)

-- Creamos un objeto para poder asignarle el evento


local imagen = display.newImage("img/imagina.jpg",100,100 )

-- Conguramos el listener
local myListener = function( event )
print( "Evento " .. event.name )
print( "Target tiene un ancho de: " ..
event.target.contentWidth )
end

imagen:addEventListener( "myEventType", myListener )

-- Creamos el evento y lo asignamos


local event = { name="myEventType", target=imagen }
imagen:dispatchEvent( event

- 46 -
Ejercicios Tema 4
Ejercicio 1

Vamos a crear un botn que nos permita mostrar una imagen. Para ello
vamos a dibujar un botn en nuestra vista

local rect = display.newRoundedRect( 160, 150, 100, 50, 20)


rect:setFillColor( 1, 0, 0)

Necesitamos capturar el evento de toque sobre el botn que acabamos de


crear:

rect:addEventListener( "touch", listener )

Por ltimo, tenemos que implementar el mtodo que ejecutaremos al


capturar el evento de toque, el cual nos insertar una imagen en nuestra
vista

- 47 -
local function listener(event)
if event.phase == "began" then
local img = display.newImage ("corona.png", 0,0)
img.width =200
img.height = 200
img.x = 150
img.y = 300
end
return true
end

Ejercicio 2

A partir del siguiente diseo que debes crear en tu proyecto:

- 48 -
Debes detectar los cambios de orientacin del dispositivo, para organizar el
contenido de la siguiente manera:

Puedes usar los mtodos rotate y translate de los objetos para situarlos
dependiendo de la orientacin.

- 49 -
Tema 5
Timers y Animaciones

Timer

Muchas veces puede ser de utilidad para nuestra aplicacin ejecutar cierta
funcin en el futuro en vez de inmediatamente.

Para ello tenemos la librera timer que nos provee de varios mtodos para
poder llevar a cabo esta tarea.

timer.performWithDelay( delay, listener [, iterations] )

Con el mtodo performWithDelay de la librera timer podemos ejecutar una


funcin, la cual especicaremos a travs del parmetro listener con un
retraso de los segundos que le asignemos mediante el parmetro delay.

El parmetro opcional iterations podemos usarlo para concretar el nmero


de veces que queremos que se repita la ejecucin de la funcin.

Por ejemplo, si ponemos que el valor de iterations es 3, se ejecutara la


funcin que hayamos especicado en listener 3 veces con un retraso de
tantos segundos como hayamos puesto en el parmetro delay.

local function holaMundo()


print( "Hola Mundo!" )
end

timer.performWithDelay( 5000, holaMundo, 5 )

En este ejemplo vamos a ejecutar la funcin holaMundo 5 veces. Cada


ejecucin se lanzar pasados 5 segundos con respecto a la anterior.

Como el segundo parmetro del mtodo especica que se debe usar un


objeto de tipo funcion, podemos utilizar una funcin annima para especicar
el cdigo que queremos ejecutar cada X tiempo.

Una funcin annima es aquella que no tiene nombre, es decir, que no


queda ligada a ninguna variable.

- 50 -
El cdigo a continuacin realiza las mismas acciones que el primer ejemplo
que hemos expuesto.

timer.performWithDelay( 5000, function()


print( "Hola Mundo!" )
end, 5 )

El parmetro listener slo acepta como valor la referencia a una funcin, es


decir, su nombre, es por ello que, directamente no podemos pasarle
parmetros cuando programamos su ejecucin a travs de timer.

Esto podemos solucionarlo juntando en un solo ejemplo las dos maneras


que hemos aprendido para ejecutar el mtodo performWithDelay
local function holaMundo( arg1, arg2 )

local function holaMundo( arg1, arg2 )


print( "Hola Mundo!", arg1, arg2 )
end

timer.performWithDelay( 5000, function()


holaMundo( "primero", "segundo" )
end, 5 )

Timer - Otras funciones

A parte de poder lanzar funciones cada cierto tiempo, la librera timer nos
ofrece otros mtodos para poder interactuar con las ejecuciones futuras que
realicemos:

timer.pause ( timerId )

Este mtodo se encarga de pausar un timer (timerId) creado con


performWithDelay. Devuelve un Number que representa el tiempo que le falta
al timer

timer.resume ( timerId )

Con este mtodo podemos volver a arrancar la ejecucin de un timer

- 51 -
(timerId) sobre el que anteriormente hubiramos ejecutado el mtodo pause

timer.cancel ( timerId )

Se cancela la ejecucin de un timer (timerId) que hubiramos creado con


timer.performWithDelay()

Transitions

Una de las caractersticas ms valoradas de Corona, es que todos los


objetos que mostremos en nuestras vistas pueden ser animados.

Las animaciones se realizan mediante la generacin de una secuencia de


frames que van pasando suavemente de unos a otros.

El trmino tween hace referencia a cmo estas transiciones se van a


generar. Tambin es usado en ocasiones para indicar que la propiedad de un
objeto va a ser modicada.

La librera Transitions nos permite crear animaciones con una nica lnea
de cdigo con la posibilidad de modicar una o ms propiedades de alguno
de los elementos mostrados en nuestras vistas.

La manera ms sencilla para realizar esta accin es usando el mtodo


transition.to.

Mediante este mtodo podemos especicar los cambios que queramos


sobre las propiedades que nos interesen de cualquiera de los objetos que
tengamos en nuestras vistas.

Transitions transition.to (target, params)

El parmetro target hace referencia al objeto sobre el que vamos a aplicar


la transicin

En params especicamos los valores sobre los que se va a ejecutar la


animacin. Podemos usar las siguientes opciones no-animables:

- 52 -
- params.time - especica el la duracin de la transicin
enmilisegundos
- params.transition - por defecto la transicin es lineal
- params.delay - indica el retardo hasta que comience la transicin
- params.delta - se trata de un valor booleano que indica si los
parmetros animables son tomados como valores nales o como
cambios sobre lo que ya exista.
- params.onStart - funcin que se ejecuta cuando comienza la
animacin.
- params.onComplete - funcin ejecutada cuando se completa la
animacin

El siguiente cdigo nos muestra cmo realizar una simple animacin.


Mostramos un cuadrado en nuestra vista modicamos sus parmetros.

local w,h = display.contentWidth, display.contentHeight

local square = display.newRect( 0, 0, 100, 100 )


square:setFillColor( 1,1,1 )

local w,h = display.contentWidth, display.contentHeight

transition.to( square, { time=1500, alpha=0, x=(w-100), y=(h-100),


width=200, height=200 } )

transition.to( square, { time=500, delay=2500, alpha=1.0 } )

Con este mtodo facilitamos mucho el proceso para la creacin de


animaciones. Comparamos estos dos mtodos de animar un rectngulo:

- 53 -
Movieclips
Movieclip es una librera externa que nos permite crear animaciones de tipo
sprite (una serie de imgenes que ejecutadas en serie crean una animacin)

Esta solucin es una manera muy sencilla y poco pesada de desarrollar


animaciones muy vistosas. Nos ayuda tambin para importar a Corona
contenido ya existente en Flash.

Para usar la librera Movieclip, debemos descargarla desde el siguiente


enlace:

Movieclips

Antes de poder usar la librera en nuestros proyectos, debemos importarla a


nuestro cdigo, de la siguiente manera:

local movieclip = require (movieclip)

Con esto declaramos que vamos a usar una librera llamada movieclip.lua,
la cual debe estar localizada en el mismo directorio que el archivo .lua donde
la estemos importando.

movieclip:newAnim (frames)

Con este mtodo creamos la animacin a partir de un array de imgenes

- 54 -
que sern, en el orden que ocupen, las encargadas de conformar nuestro
movieclip.

myAnim =
movieclip.newAnim{ "img1.png", "img2.png", "img3.png", "img4.png" }

Si no especicamos una ruta concreta dentro de nuestro proyecto, las


imgenes contenidas en el array que da forma a la animacin deben estar en
la misma ruta que el chero .lua que contenga el movieclip.

movieclip:play()

Da comienzo a la animacin en el orden insertado en la creacin del


movieclip.

Si se ha pausado la animacin en algn frame, llamando al mtodo frame


sin parmetros podremos reanudarla.

movieclip:play { startFrame = X, endFrame = Y, loop = Z, remove = true }

De esta manera determinamos que comience la animacin indicndole el


frame de comienzo (startFrame), el frame de n (endFrame), el nmero de
veces que se debe ejecutar la animacin (loop) y si se debe eliminar el
movieclip a si mismo cuando se termine la animacin

movieclip:reverse ()

Arranca la animacin pero en sentido contrario al establecido en su


creacin.

Una vez alcance el primer frame, volver automticamente al primero y


reanudar el movieclip.

movieclip:reverse { startFrame = X, endFrame = Y, loop = Z, remove =


true }

Al igual que con play podemos indicar el frame de comienzo, el de


nalizacin, el nmero de vueltas que tendr la animacin y si se debe

- 55 -
eliminar una vez terminada.

movieclip:nextFrame ()

Aplicado sobre una animacin, detiene su ejecucin y muestra el siguiente


frame en el orden indicado en la creacin del movieclip.

movieclip:previousFrame ()

Detiene cualquier movieclip sobre el cual se ejecute la funcin y muestra el


frame anterior con el orden indicado en su creacin.

movieclip:stop ()

Detiene la animacin en el frame que se encuentre siguiendo el orden


inicial.

movieclip:stopAtFrame (frame)

Detiene la aplicacin en el frame indicado.

Podemos usarlo seguido de una llamada al mtodo play y conseguiremos


que la animacin pase automticamente al frame que necesitemos segn
nuestras necesidades

movieclip:setDrag

Convierte cualquier objeto denido con movieclip a un objeto con


capacidades para ser arrastrado por nuestra vista.

Podemos utilizar una serie de parmetros para denir limitar el objeto.


Deniendo la propiedad drag = true indicamos que el objeto puede ser
arrastrado. De la misma manera, podemos usarlo con false para quitarle esa
propiedad.

Con limitX y limitY denimos los lmites en el eje de las x y en el eje de las
y hasta donde vamos a poder arrastrar nuestra animacin.

El parmetro bounds dene los lmites del objeto que nos permiten

- 56 -
arrastrarlo. Est denido como {left, top, width, height} movieclip:setDrag

Los parmetros onPress, onDrag y onRelease, nos indican los mtodos


que se deben ejecutar una vez se capturen esos tres eventos (pulsar,
arrastrar y dejar de pulsar)

myAnim:setDrag{
drag=true,
limitX=false,
limitY=false,
onPress=myPressFunction,
onDrag=myDragFunction,
onRelease=myReleaseFunction,
Bounds={ 10, 10, 200, 50 }
}

- 57 -
Ejercicios Tema 5

Ejercicio 1

En este primer ejercicio vamos a tratar con una imagen de tipo sprite para
realizar diferentes operaciones aprendidas en este tema.

Necesitamos, para crear nuestro sprite una imagen de este tipo,

La cual podemos dividir en imgenes simples y, al ponerlas en serie


muestren algn tipo de animacin.

Lo primero que debemos hacer es descargarnos la librera movieclip.lua del


siguiente link e incorporarla a nuestro proyecto:

http://developer.anscamobile.com/demo/Movieclip.zip

local movieclip = require ("movieclip")

Para poder usar la librera, el chero movieclip.lua, contenido dentro del


proyecto que nos hemos descargado, debe situarse en el mismo directorio
donde tengamos el archivo main.lua del nuevo proyecto que estamos
creando.

El siguiente paso es crear nuestra animacin a partir de las imgenes que


hemos agregado tambin al mismo directorio del proyecto:

local animacion = movieclip.newAnim {sonic1.png, sonic2.png, sonic3.png,


sonic4.png, sonic5.png, sonic6.png, sonic7.png, sonic8.png, sonic9.png}

Podemos situar nuestra animacin y posteriormente iniciarla.

- 58 -
animacion.x = display.contentWidth / 2
animacion.y = display.contentHeight / 2

animacion:play()

En este momento hemos situado nuestra animacin en el centro de la


pantalla y hemos iniciado su reproduccin

Nuestro siguiente paso en el ejercicio ser crear una serie de botones, los
cuales ejecutarn una serie de transiciones sobre la animacin que hemos
creado.

local botonRojo = display.newRoundedRect (60,400,90,30,10)


botonRojo:setFillColor (1,0,0)

local botonVerde = display.newRoundedRect (160,400,90,30,10)


botonVerde:setFillColor (0,1,0)

local botonAzul = display.newRoundedRect (260,400,90,30,10)


botonAzul:setFillColor (0,0,1)

botonRojo:addEventListener ("touch", pulsarBotonRojo)


botonVerde:addEventListener ("touch", pulsarBotonVerde)
botonAzul:addEventListener ("touch", pulsarBotonAzul)
- 59 -
Se debe rellenar los tres mtodos que capturan los eventos, siguiendo las
siguientes pautas:

-Mientras que se mantenga pulsado el botn rojo, la animacin debe


desaparecer. Una vez se deje de pulsar, la animacin debe volver a
aparecer.

-Si mantenemos pulsado el botn verde, la animacin se debe


desplazar hasta la parte superior de nuestra vista. Una vez dejemos de
pulsar, la animacin volver a su ubicacin original.

-Pulsando el botn azul, la animacin debe rotar sobre su eje. Cuando


dejemos de pulsar, debe volver a su posicin original.

AMPLIACIN

Para este ejercicio vamos a crear una lluvia de objetos. Cada X tiempo
crearemos un objeto y simularemos la animacin para que recorra la pantalla
de arriba abajo, simulando una lluvia. Debemos usar para esto los timer y
sus funciones relacionadas aprendidas en este tema.

NOTA: Para poder hacer que cada objeto se genere en una posicin
aleatoria, podemos usar el mtodo math.random

- 60 -
Tema 6
Motor Fsico

Corona facilita el uso de propiedades fsicas con los elementos que


dispongamos en las distintas vistas de nuestra aplicacin.

Cualquier objeto, imagen o sprite puede ser tratado como una unidad
fsica y automticamente empezar a interactuar con otros objetos dentro de
la simulacin.

Corona traduce automticamente las unidades tpicas de medicin que


usamos para colocar nuestros objetos (pxeles), a una unidad mtrica de
medicin (metros).

Todas las posiciones se especican en pxeles, pero internamente se


traducen en metros con una conversin de 30 pxeles por metro.

Motor Fsico (Conguracin)

Con la siguiente lnea declaramos la posibilidad de usar el motor fsico en


nuestro cdigo:

local physics = require "physics"

El uso de las propiedades fsicas en Corona se pueden habilitar y


deshabilitar en funcin de las diferentes necesidades de la aplicacin. Incluso
se puede pausar la utilizacin del motor fsico.

Los siguientes mtodos sirven para manejar el uso del motor fsico durante
nuestra aplicacin.

physics.start ()

El mtodo start inicializa o restaura el modelo fsico de la aplicacin. Se


debe llamar a este mtodo antes que cualquier otra funcin, para poder
contar con las propiedades fsicas de los objetos.

- 61 -
physics.stop ()

El mtodo stop destruye el mundo fsico de la aplicacin.

physics.pause ()

Utilizamos este mtodo para pausar el motor fsico en cualquier punto de la


ejecucin de nuestra aplicacin.

physics.setGravity (x , y)

Nos permite modicar el valor de la gravedad especicando los valores en


el eje x y en el y.

Para simular la gravedad terrestre podemos usar los siguientes valores:

physics.setGravity (0,9.8)

physics.getGravity ()

Devuelve el valor x e y del vector global de la gravedad, en m/s2

gx, gy = physics.getGravity ()

Podemos denir la gravedad de nuestra aplicacin basndonos en la


inclinacin del dispositivo con una simple funcin que determine este
movimiento utilizando el acelermetro.

local function onTilt( event )


physics.setGravity( 10 * event.xGravity, - 10 * event.yGravity )
end

Runtime:addEventListener( "accelerometer", onTilt )

- 62 -
physics.setScale (x)

Realizando una llamada a este mtodo podemos denir el coeciente de


conversin entre las coordenadas en pxeles con las que denimos nuestros
objetos y las coordenadas fsicas simuladas por Corona.

El valor por defecto es 30, lo que signica que los valores fsicos situados
entre 0.1m y 10m estaran cubiertos entre las coordenadas 3 y 300 de
nuestra vista, aproximadamente.

physics.setDrawMode (text)

Selecciona uno de los 3 posibles modos para el motor fsico. debug,


hybrid y normal

El modo se puede cambiar en tiempo de ejecucin. Es recomendable su


uso en el simulador ya que se pueden apreciar los diferentes
comportamientos de los objetos.

- 63 -
Deteccin de Colisiones

Las colisiones entre eventos fsicos en nuestra aplicacin, deben ser


tratados mediante la captura de una serie de eventos que controlan esta
caracterstica.

Para colisiones genricas, debemos capturar el evento collision.

Este evento incluye fases incluye diferentes fases, began y ended, las
cuales hacen referencia al momento de inicio de la colisin y al momento de
n, respectivamente.

Aparte del evento general de colisin, disponemos de otros dos eventos


para poder controlar la colisin:

preCollision - evento lanzado en el momento anterior de comenzar la


interaccin.

postCollision - evento lanzado justo cuando termina la interaccin entre


los objetos presentes en la colisin. Se trata del nico evento dentro de
la colisin donde se reporta con qu fuerza se ha realizado la misma.

Deteccin de Colisiones - Eventos Globales

Cuando realizamos la deteccin a nivel global, el evento incluye


event.object1 y event.object2, los cuales contienen las propiedades de los
dos objetos incluidos en la colisin.

Como sabemos, Corona trata los objetos como tablas LUA, por lo que
podremos agregar, a nuestros objetos las propiedades que nos interesen a la
hora de tratarlos en el cdigo.

Por ejemplo, podemos aadir un nombre a una imagen que queramos


mostrar en nuestra vista:

local img1 = display.newImage( "imagen.png", 100, 200 )


img1.miNombre = "Imagen1"
- 64 -
local physics = require ("physics")
physics.start()

local suelo = display.newImage( "suelo.png", 175, 450 )


physics.addBody(suelo, "static")
suelo.myName = "suelo"

local bloque1 = display.newImage( "bloque.png", 100, 200 )


physics.addBody( bloque1, { density = 1.0, friction = 0.3, bounce = 0.2 } )
bloque1.myName = "bloque1"

local bloque2 = display.newImage( "bloque.png", 100, 120 )


physics.addBody( bloque2, { density = 1.0, friction = 0.3, bounce = 0.2 } )
bloque2.myName = "bloque2"

local function onCollision( event )


if ( event.phase == "began" ) then
print( "began: " .. event.object1.myName .. " & " .. event.object2.myName )
elseif ( event.phase == "ended" ) then
print( "ended: " .. event.object1.myName .. " & " .. event.object2.myName )
end
end

Runtime:addEventListener( "collision", onCollision )

- 65 -
Deteccin de Colisiones - Eventos Locales

En este caso podemos acceder a los objetos participantes en la colisin


mediante self y event.other

...

local bloque1 = display.newImage( "bloque.png", 100, 200 )


physics.addBody( bloque1, { density = 1.0, friction = 0.3, bounce = 0.2 } )
bloque1.myName = "bloque1"

local bloque2 = display.newImage( "bloque.png", 100, 120 )


physics.addBody( bloque2, { density = 1.0, friction = 0.3, bounce = 0.2 } )
bloque2.myName = "bloque2"

local function onCollision( event )


if ( event.phase == "began" ) then
print( "began: " .. self.myName .. " & " .. event.other.myName )
elseif ( event.phase == "ended" ) then
print( "ended: " .. self.myName .. " & " .. event.other.myName )
end
end

bloque1.collision = onLocalCollision
bloque1:addEventListener("collision", bloque1)

bloque2.collision = onLocalCollision
bloque2:addEventListener("collision", bloque2)

Deteccin de Colisiones Fuerzas

- 66 -
Cuando termina una colisin podemos obtener la fuerza directa entre los
dos objetos, as como la fuerza lateral entre los mismos, la cual es una
fuerza de friccin.

Podemos acceder a la fuerza directa y la lateral dentro del evento


postCollision, recuperando las propiedades event.force y event.friction.

local function onPostCollision( event )


if ( event.force > 1.0 ) then
print( "Fuerza Directa: " .. event.force .. " Friccin: " .. event.friction )
end
end

Runtime:addEventListener( "postCollision", onPostCollision )

Deteccin de Colisiones - Collision Categories

Podemos determinar qu objetos pueden colisionar entre si utilizando las


categoras y las mscaras.

En este caso se deben especicar en binario utilizando su notacin decimal


(1, 2, 4, 8, 16, 32...)

Cada tipo de objeto que denamos en nuestra aplicacin podr tener un


ltro diferente en el que deniremos los valores de categoryBits (categora a
la que pertenece) y maskBits (categoras con las que puede colisionar)

collisionFilter = { categoryBits = 1, maskBits = 6 }


-- Con este filtro, colisionar con los objetos que tengan categoryBits 4 o 2

local redBody = { density=0.2, friction=0, bounce=0.95, radius=43.0, filter=collisionFilter }


redBalloon = display.newImage( "red_balloon.png" )
physics.addBody( redBalloon, redBody )

- 67 -
Para poder determinar los valores de mscara que debemos usar para
cada uno de los ltros, podemos usar la siguiente tabla de colisiones:

En la primera lnea determinamos la categora que le asignamos a cada


uno de los objetos de nuestra aplicacin. En la segunda especicamos con
qu otros objetos puede colisionar.

En la ltima columna obtenemos la suma de las casillas rellenas. El primer


valor corresponde al categoryBits y el segundo al maskBits.
Corona SDK

Cuerpos Fsicos

Una de las caractersticas principales del motor fsico de Corona es que


nosotros podemos representar todos los objetos que necesitemos y Corona
se encargar de re presentarlos fsicamente en nuestra aplicacin y
devolvernos las propiedades caractersticas de cada uno de ellos.

Cuando aadimos un objeto al motor fsico usando physics.addBody, no


obtenemos un objeto nuevo, si no que ampliamos las propiedades del
mismo.

Podremos seguir accediendo a las propiedades del objeto antes del cambio
pero, en este caso, el objeto estar sujeto a todas las propiedades fsicas
proporcionadas por el motor de Corona, como puede ser la gravedad.

Cuerpos Fsicos physics.addBody

- 68 -
Con esta funcin transformamos un objeto simple de Corona en una
simulacin fsica del mismo capaz de interactuar con el motor fsico de la
aplicacin.

Los cuerpos fsicos tienen 3 propiedades principales:

density: es multiplicada por el rea del objeto para determinar su


masa.

friction: indica la resistencia del objeto con respecto a los dems

bounce: hace referencia a la capacidad de rebote del objeto. El valor


por defecto es 0.2. Valores por encima de 1.0 tendrn
comportamientos indeterminados

Por defecto, este constructor asume que el objeto creado es rectangular.

local bloque = display.newImage( "bloque.png", 100, 200 ) physics.addBody( bloque,


{ density = 1.0, friction = 0.3, bounce = 0.2 } )

La tabla con las propiedades fsicas puede ser declarada fuera y usada en
varios componentes.

local bloque1 = display.newImage( "bloqueImagina.png", 100, 200 )


local bloque2 = display.newImage( "bloqueImagina.png", 180, 280 )

local materialBloque = { density = 1.0, friction = 0.3, bounce = 0.2 }

physics.addBody( bloque1, materialBloque )


physics.addBody( bloque2, materialBloque )

Los cuerpos circulares requieren un parmetro adicional radius. Es muy til


para usarlo en objetos como piedras, balones

local roca = display.newImage( "boulder.png", 100, 200 )


physics.addBody( roca, { density = 1.0, friction = 0.3, bounce = 0.2, radius = 40 } )

- 69 -
Para crear polgonos ms complejos, debemos especicar cada uno de los
vrtices como un par de coordenadas mediante la propiedad shape. Estas
coordenadas deben declararse siguiendo el orden de las agujas del reloj.

El mximo nmero de vrtices permitidos para un polgono es de 8. Una


vez creada la forma, esta puede ser usada para varios objetos.

Este sera el ejemplo para crear la forma fsica de un pentgono.

local pentagon = display.newImage("pentagon.png")


pentagon.x = 200
pentagon.y = 50

PentagonShape = { 0,-37, 37,-10, 23,34, -23,34, -37,-10 }

physics.addBody( pentagon, { density=3.0, friction=0.8, bounce=0.3,


shape=pentagonShape } )
Podemos declarar un objeto que acte como sensor. Esto quiere decir, que
no interactua con los dems objetos de la vista, pero s reciben y producen
las diferentes colisiones con los dems.

Por ejemplo, podramos crear un objeto el cual, al pasar por encima de l


con uno de los personajes de nuestra aplicacin, active la apertura de una
caja situada en otra parte del juego.

local rect = display.newRect( 50, 50, 100, 100 )


rect:setFillColor( 1, 1, 1, 1 )
rect.isVisible = true -- opcional
physics.addBody( rect, "static", { isSensor = true } )

- 70 -
Ejercicios Tema 6
Ejercicio 1

Para este primer ejercicio vamos a crear una estructura mediante la cual
podamos apreciar, sin salir de la aplicacin, de los diferentes modos que
tenemos a nuestra disposicin dentro del motor fsico para representar los
diferentes objetos dentro de nuestra aplicacin.

Para nuestro proyecto vamos a necesitar 3 imgenes, las cuales vamos a


dejar a merced de la simulacin gravitatoria que nos ofrece el motor fsico de
Corona para observar su comportamiento.

Nosotros vamos a utilizar las siguientes:

Lo primero que vamos a hacer es importar la librera para manejar objetos


fsicos en Corona e inicializarla:

local physics = require ("physics")


physics.start()

Una vez inicializada la librera, vamos a crear todos los objetos dentro de
nuestra vista, las imgenes, el suelo, para que no se pierdan los objetos en
el innito y 3 botones que nos van a permitir alternar entre las diferentes
opciones para mostrar estos objetos dentro del motor fsico:

local suelo = display.newRect (140,390,400,30)


physics.addBody (suelo, "static")

local logo = display.newImage ("logocorona.png", 180,-100)


physics.addBody (logo, {bounce=0.3, friction= 0.4})

local icuadernos = display.newImage ("icuadernos.png", 100,-100)


physics.addBody (icuadernos, {bounce=0.3, friction= 0.4})
- 71 -
local idiotify = display.newImage ("idiotify.png", 185,-100)
physics.addBody (idiotify, {bounce=0.3, friction= 0.4})
-- Creamos los botones
local rectanguloRojo = display.newRoundedRect (55,425,100,40, 20)
rectanguloRojo:setFillColor (1, 0, 0)

local rectanguloVerde = display.newRoundedRect (160,425,100,40, 20)


rectanguloVerde:setFillColor (0, 1, 0)

local rectanguloAzul = display.newRoundedRect (265,425,100,40, 20)


rectanguloAzul:setFillColor (0, 0, 1)

-- Aadimos estos botones al motor fsico para poder verlos en los diferentes
modos
physics.addBody (rectanguloRojo, "static", { density=1.0})
physics.addBody (rectanguloVerde, "static", { density=1.0})
physics.addBody (rectanguloAzul, "static", { density=1.0})

-- Agregamos los eventos que controlarn cuando pulsemos un botn


rectanguloRojo:addEventListener ("touch", pulsarBotonRojo)
rectanguloVerde:addEventListener ("touch", pulsarBotonVerde)
rectanguloAzul:addEventListener ("touch", pulsarBotonAzul)

Si ejecutamos nuestra aplicacin observaremos nuestras 3 imgenes


cayendo desde lo ms alto de nuestra vista hasta el suelo que hemos
colocado como tope.

Nuestro siguiente paso ser rellenar los mtodos que controlan los eventos
de pulsacin de los botones:

local function pulsarBotonRojo (event)


if event.phase == "began" then
print ("DEBUG")
physics.setDrawMode ("debug")
end
end

Con este mtodo controlariamos el boton Rojo. Rellena los otros 2


mtodos para cambiar entre los modos restantes.

Si utilizamos los modos debug o hybrid para observar nuestra aplicacin

- 72 -
podemos analizar los diferentes estados fsicos de los objetos representados
con diferentes colores:

-Naranja: objetos fsicos en movimiento

-Gris: objetos en reposo

-Verde: objetos estticos, como el suelo o los botones.

AMPLIACIN

Modica las imgenes del ejercicio y utiliza alguna que sea de tipo crcular,
adaptando el objeto fsico para que se adapte a la forma de la nueva imagen.

Ejercicio 2

Modica el ejercicio anterior para realizar un ltro de los objetos. Cada uno
de los objetos cumplir un comportamiento determinado:

-El primer objeto no colisionar ni con el suelo ni con los botones, por lo
que se perder en el innito de nuestra aplicacin

-El segundo objeto no colisionar con el suelo, pero s con los botones.

-El tercer objeto colisionar con el suelo

En todo caso, muestra en la consola el estado de las colisiones y los objetos


que participan en ellas.

- 73 -
Tema 7
Hardware y Multimedia

Informacin del dispositivo

Corona nos ofrece una serie de libreras y mtodos para poder acceder a la
informacin del sistema donde se est ejecutando nuestra aplicacin.

Puede sernos de gran utilidad para poder mostrar determinada informacin


en funcin del modelo de dispositivo donde estemos ejecutando la
aplicacin.

Aparte podemos acceder a los diferentes componentes que tenga nuestro


dispositivo disponible, como puede ser el acelermetro, el sistema de
cheros interno, el sistema de localizacin...
Informacin del dispositivo

system.info (param)

Este mtodo nos devuelve informacin sobre el sistema que est


ejecutando nuestra aplicacin.

Con el parmetro param indicamos cual es la informacin que vamos a


querer recuperar.

Los valores que podemos obtener son los siguientes:

name - devuelve el nombre del dispositivo. Por ejemplo para el


iphone, sera el mismo nombre que podemos encontrar en el Itunes

model - obtenemos el modelo del dispositivo (Ej. Iphone)

deviceId - el identicador nico del dispositivo

environment - te indica dnde ests ejecutando la aplicacin. Puede


tomar valores simulator y device

platformName - devuelve el nombre de la plataforma. Por ej, el


sistema operativo.

- 74 -
platformVersion - obtenemos la versin de la plataforma donde
ejecutamos la aplicacin.

version - la versin de Corona

textureMemoryUsed - nos devuelve el uso de memoria de la


aplicacin en bytes.

maxTextureSize - obtenemos el mximo ancho y alto de textura que


podemos usar en nuestra aplicacin.

system.getTimer ()

Esta funcin nos devuelve, en milisegundos, el tiempo que ha pasado


desde que se ha ejecutado la aplicacin.

system.openURL (url)

Nos permite abrir una url en el navegador del dispositivo.

Permite abrir urls formateadas en dispositivos iOS:

- Mail: mailto:contacto@viveahora.travel
- Telfonos: tel:666888999
- Webs: http://viveahora.travel

system.pathForFile (lename [ ,baseDirectory])

Genera la ruta absoluta donde podemos encontrar el chero lename. Se le


puede especicar un directorio base a partir del cual generar esa ruta.

system.vibrate ()

Emite una vibracin en nuestro dispositivo

Directorios del sistema

- 75 -
En todos los dispositivos tenemos una serie de directorios denidos por el
sistema a los cuales podemos acceder con las siguientes constantes:

system.DocumentsDirectory

Es el directorio que utilizamos para trabajar con cheros que deben


guardarse incluso cuando termine la sesin en la que estamos trabajando.

system.TemporaryDirectory

Se trata de un directorio temporal. La persistencia de los cheros


guardados en este directorio, no se asegura que se mantenga una vez
terminada la sesin.

system.ResourceDirectory

Se trata del directorio donde tenemos empaquetados todos los contenidos


de la aplicacin. Nunca se deben guardar cheros propios en este directorio.

Sistema de Audio

El sistema de audio de Corona nos ofrece la posibilidad de acceder a las


caractersticas ms avanzadas de la librera OpenAL (API multiplataforma de
audio 3D empleada mayoritariamente en juegos)

El nmero mximo de canales que podemos usar es de 32. Es decir,


podemos reproducir simultneamente un mximo de 32 sonidos en nuestra
aplicacin.

El nmero mximo de canales posibles no implica que la aplicacin


funcione correctamente. Cuanto ms cheros de audio se reproduzcan a la
vez, ms carga tendr la CPU, por lo tanto, el rendimiento de nuestra
aplicacin ser menor.

Existen dos maneras de cargar el audio que vamos a reproducir.


Tendremos que seleccionar la que ms se aproxime a las necesidades de
nuestra aplicacin, en funcin del rendimiento y del uso de la Memoria.

audio.loadSound (le)

- 76 -
Con este primer mtodo, cargamos el audio entero en memoria y as lo
tenemos disponible a la hora de reproducirlo. Realiza un gran uso de
memoria, por lo tanto es el mtodo menos aconsejable para aplicaciones con
problemas de rendimiento.

audio.loadStream (le)

En este caso, el audio es preparado para su lectura en pequeos trozos,


segn sea requerido por la aplicacin. Con este mtodo conseguimos un
mayor ahorro de memoria, pero no aseguramos la correcta reproduccin del
audio, ya que esta depende de los recursos disponibles en la CPU.

La ejecucin mltiple de sonidos se debe hacer de diferente manera,


dependiendo del mtodo que utilicemos para cargar el audio.

Si cargamos el audio en memoria, podemos reproducirlo el nmero de


veces que queramos a lo largo de nuestra aplicacin con la misma instancia.

local bomba = audio.loadSound ("bomb_wav.wav")

audio.play (bomba)
audio.play (bomba)
audio.play (bomba)
audio.play (bomba)
audio.play (bomba)
audio.play (bomba)
audio.play (bomba)

No se deben cargar varias instancias de un mismo sonido a travs de


loadSound. Sera una prdida de memoria.

Por el contrario, si el mtodo utilizado para la reproduccin de nuestro


sonido es loadStream, hay que tener en cuenta que una instancia slo puede
ser reproducida simultneamente por cada canal.

Por lo tanto, si queremos lanzar varias reproducciones a la vez, utilizando


loadStream, debemos crear varias instancias que manejen los diferentes
sonidos.

local musica1 = audio.loadStream ("musica1.wav")


local musica2 = audio.loadStream ("musica2.wav")

audio.play (musica1)
audio.play (musica2) - 77 -
Al utilizar los streams, la carga en memoria es ms reducida que de la
manera que hemos visto anteriormente.

audio.play (audioHandle [, options])

Con el parmetro audioHandle denimos el archivo que vamos a reproducir,


el cual tendremos que haber cargado anteriormente con audio.loadSound o
audio.loadStream.

En el parmetro opcional options denimos las propiedades de


reproduccin que va a tener nuestro audio. Podemos reejar los siguientes
valores:

channel - el nmero del canal donde vamos a querer reproducir nuestro


audio.

loops - el nmero de veces seguidas que se va a reproducir el audio. El


audio se va a reproducir (loops+1) veces.

duration - en este valor especicaremos, en milisegundos, el tiempo


que queremos que dure la reproduccin de nuestro audio. audio.play
(audioHandle [, options])

fadein - especicado en milisegundos, nos asigna el valor de la rampa


de volumen que se efectuar al principio de nuestra reproduccin.

onComplete - se trata de un listener, el cual se ejecutar una vez


termine la reproduccin del audio. Nos devuelve la siguiente tabla
event.

event.name - soundCompletion

event.channel

event.handle - el chero de audio reproducido

event.completed - este parmetro tendr valor true si el audio se


ha detenido porque ha llegado al nal normalmente y false si se
ha detenido por otras causas.

- 78 -
audio.stop ([channel])

Mtodo para detener el canal especicado por parmetro. Si no se


especica ningn canal, se detienen todos.

audio.pause ([channel])

Mtodo para pausar los canales especicados como parmetro. Si no


especicamos ningn canal, se pausarn todos los canales activos.

audio.resume ([channel])

Con este mtodo volvemos a poner en reproduccin el canal seleccionado.


Si no se especica ningn canal, afecta a todos los canales activos.

audio.stopWithDelay (duration)

Detiene el audio que se est reproduciendo actualmente una vez pase el


tiempo especicado en duration

audio.setVolume (volumen [, options])

Establece el volumen para la reproduccin en activo. El valor del parmetro


volume va desde 0.0 a 1.0.

En el parmetro options podemos especicar una tabla para especicar el


canal al cual le vamos a cambiar el volumen. Ej. {channel=X}

audio.seek (time [, audioHandle] [, { channel = c }])

Desplaza la reproduccin del audio activo hasta el punto, especicado en


milisegundos que indiquemos.

Como parmetros opcionales podemos especicar el audio a parar y el


canal sobre el que actuaremos

- 79 -
Vdeo

media.playVideo (path [, baseSource], showControls, listener)

Reproduce el vdeo situado en la ruta que especiquemos en el parmetro


path.

Mediante la constante baseSource podemos controlar como se interpreta la


ruta del chero que estamos reproduciendo.

El parmetro showControls es un booleano que especica si se muestran


(true) o no (false) los controles del vdeo mientras est en reproduccin.

En el ltimo parmetro especicamos el mtodo que se va a ejecutar


cuando termine la ejecucin del vdeo.

Nota: Este API no est disponible en el simulador de Windows.

local function terminaVideo (event)


print ("terminado")
end

media.playVideo ("videoEjemplo.mp4", true, terminaVideo)

- 80 -
Captura de imgenes

En casi todos los dispositivos de nueva generacin tenemos disponible una


cmara con la que se pueden capturar tanto imgenes como vdeos.

Esta captura de contenido multimedia puede ser usado dentro de nuestra


aplicacin y por eso, Corona nos ofrece un API para manejar todo lo
relacionado con la cmara.

Este API no se puede utilizar en el simulador de Corona para Windows, as


que la aplicacin si se desarrolla sobre ese sistema operativo, debe ser
probada directamente en el dispositivo.

media.show (mediaSource, listener [, letable])

Con este mtodo mostramos el interfaz especco, dependiendo de la


plataforma en la que estemos ejecutando la aplicacin, para acceder a la
cmara o a la librera de imgenes.

Por defecto, la imagen se aade a la parte superior de nuestra vista.


Tambin tenemos la posibilidad de almacenarla en cualquier directorio.

Necesitamos establecer un listener para manejar el objeto que nos


devuelva el mtodo (la imagen).

En Android, para poder utilizar la cmara debemos establecer en nuestro


chero build.settings los permisos necesarios.

settings =
{
android =
{
usesPermissions =
{
"android.permission.CAMERA",
"android.permission.WRITE_EXTERNAL_STORAGE",
},
},
}
- 81 -
Para el caso especico de desarrollar para el iPad, necesitamos especicar
dos parmetros adicionales.

A la llamada de media.show debemos agregar los valores de:

origin - el rectngulo a partir del cual se va a mostrar el popover para


seleccionar la foto. Lo ms normal es usar el botn desde el cual
lanzamos la seleccin de imgenes. (Ej: myButton.contentBounds)

permittedArrowDirections - un array opcional indicando las posibles


direcciones hacia las cuales se extender el popover. Los valores
admitidos son: {up, down, left, right, any}

Mediante el parmetro mediaSource de la llamada al mtodo, vamos a


especicar de dnde vamos a obtener la imagen. Puede contener alguno de
los siguientes valores:

media.PhotoLibrary

media.Camera

media.SavedPhotoAlbum

Debemos indicar el mtodo que se va a hacer cargo de gestionar el nal del


evento de captura de imgenes a travs del parmetro listener.

Este mtodo recuperar el objeto event.target donde quedar almacenada


la imagen que hayamos seleccionado para su uso.

Si no realizamos ninguna modicacin sobre la imagen capturada, esta se


mostrar en la parte superior izquierda de nuestra vista.

Por ltimo nos queda el parmetro opciona letable, mediante el cual


podemos crear un array para especicar donde se va a salvar la imagen
capturada.

- 82 -
Si utilizamos este mtodo, ya no recibiremos el objeto event.target en el
mtodo listener.

El formato de la tabla para el parmetro letable es:

{ baseDir= , lename= [, type=]}

local function onComplete(event)


local photo = event.target
photo.x = 65
photo.y = 250

if photo then
print( "photo w,h = " .. photo.width .. "," .. photo.height )
end
end

local button = display.newRect(120, 240, 80, 70)

local function tomarPhoto( event )


--Comprobamos si el dispositivo tiene cmara
if media.hasSource (media.Camera) then
media.show( media.Camera, onComplete )
end
end

button:addEventListener("tap", tomarPhoto )

Uso del Acelermetro

El acelermetro es uno de los componentes disponible en la mayora de los


dispositivos de ltima generacin capaz de detectar el movimiento del mismo
y aplicarlo para su uso en las aplicaciones.

En Corona, el acelermetro se trata como si fuese un evento global, el cual


vamos a tratar a travs de la clase Runtime.

Con la siguiente sentencia estamos indicando que vamos a capturar los

- 83 -
eventos lanzados por el acelermetro en el mtodo indicado para ello.

Runtime:addEventListener (accelerometer, metodoAccel)

En el listener donde capturamos el evento, podemos acceder a diferentes


valores:

Para poder obtener los diferentes valores segn la posicin del dispositivo,
podemos acceder a las propiedades event.xGravity, event.yGravity,
event.zGravity
Mediante el uso de event.isShake sabremos si el movimiento que ha
realizado el dispositivo es una agitacin.

Con event.deltaTime podremos acceder a los segundos que han


transcurrido desde el ltimo evento de acelermetro.

- 84 -
Ejercicios Tema 7
Ejercicio 1

Vamos a practicar con la API para el manejo de sonidos que nos ofrece
Corona, creando un pequeo reproductor de audio como el que podemos ver
en la siguiente captura:

Lo primero que vamos a hacer es colocar los diferentes objetos que tenemos
en nuestra vista:

local contentWidth = display.contentWidth


local contentHeight = display.contentHeight

local texto = display.newText ("El audio est parado", contentWidth/2,


contentHeight 50)

local botonPlay = display.newImage ("botonStart.png", 100, contentHeight 150)


botonPlay.width = 50
botonPlay.height = 50

local botonPause = display.newImage ("botonPause.png",160, contentHeight


150)
botonPause.width = 50
botonPause.height = 50

local botonStop = display.newImage ("botonStop.png", 220, contentHeight - 150)


botonStop.width = 50
- 85 -
botonStop.height = 50
Si ejecutamos nuestra aplicacin podremos observar los 3 botones y el texto
que nos servir de indicador para mostrar el estado de la cancin.

Lo siguiente que haremos ser crear el audio que vamos a reproducir:

local musica = audio.loadStream ("music.mp3")

Cargamos el audio que vamos a usar en la variable musica para poder


acceder a ella a travs de los diferentes eventos que capturaremos al
interactuar con los botones.

El siguiente paso es crear los eventos para los botones y, en funcin de la


accin de cada uno se debe completar el cdigo que falta:

local function pulsarPlay (event)


-- COMPLETAR
-- Reproduce el audio
-- Si el audio est pausado, lo contina
end

local function pulsarPause (event)


-- COMPLETAR
-- Pausa la reproduccin del audio
end

local function pulsarStop (event)


-- COMPLETAR
-- Detiene la reproduccin del audio
-- Coloca su reproduccin al principio del audio
end

botonPlay:addEventListener ("tap", pulsarPlay)


botonPause:addEventListener ("tap", pulsarPause)
botonStop:addEventListener ("tap", pulsarStop)

Aparte, en cada uno de los mtodos, debemos actualizar el estado del texto
para indicarnos en qu situacin est la reproduccin.

Para nalizar el ejercicio, vamos a especicar el tiempo que llevamos


reproducido y el tiempo total del audio. Para ello debemos crear una variable

- 86 -
para llevar la cuenta del tiempo reproducido, as como el texto donde
pondremos los detalles:

local tiempoTranscurrido = 0

local textoTiempo = display.newText ("Total reproducido "..


(tiempoTranscurrido/1000).. " / "..(audio.getDuration(musica)/1000), 70,320)

Usamos el mtodo audio.getDuration que nos devuelve el tiempo total del


audio que le pasemos por parmetro. Como el nmero devuelto es en
milisegundos, lo dividimos entre 1000 para obtener los segundos
correspondientes.

El tiempo transcurrido lo podemos controlar a travs de un timer que se


ejecute cada segundo y podamos controlar dentro de lo diferentes eventos
que hemos creado anteriormente.

local reproducido

reproducido = timer.performWithDelay (1000, function ()


tiempoTranscurrido = tiempoTranscurrido +1
textoTiempo.text = "Total reproducido "..tiempoTranscurrido.. " / "..
(audio.getDuration(musica)/1000)
local isChannel1Playing = audio.isChannelPlaying( 1 )
if not isChannel1Playing then
tiempoTranscurrido = 0
timer.pause (reproducido)
end
End
,
-1
)
timer.pause(reproducido)

A travs de este timer, cada segundo, vamos incrementando la variable que


controla el tiempo de nuestra aplicacin, actualizamos el texto y
comprobamos si el audio sigue reproducindose, es decir, no ha llegado al
nal para reiniciarlo.

Por ltimo, crea el cdigo necesario para controlar el comportamiento


del timer dentro de cada uno de los eventos (play, pause y stop)

- 87 -
EJERCICIO 2

Vamos a mezclar en este ejercicio dos de los temas aprendidos hasta la


fecha, la reproduccin de audio vista en este tema y el manejo de colisiones
del motor fsico de Corona.

Se debe crear una interfaz como la siguiente:

Todos los objetos de la interfaz se podrn arrastrar a lo largo de la vista,


excepto el crculo rojo que ser nuestro objeto master.

Cada uno de los cuadrados representar un tipo diferente de audio y un


canal diferente.

Si uno de los rectngulos entra en contacto con el crculo, debe empezar a


sonar en loop su sonido asociado. Una vez lo separemos debe parar de

- 88 -
sonar.

NOTAS:

-Recuerda que, a los objetos que creamos se le pueden aadir parmetros


segn nuestra conveniecia:

rectangulo1.pistaAudio = audio1

rectangulo1.canal = 1

-Para el movimiento arrastrando puedes capturar el evento touch de los


objetos.

EJERCICIO 3

Realizar una aplicacin que nos permita capturar una imagen a travs de la
cmara del dispositivo. Una vez capturada, mostrarla en un tamao reducido.
Permitir, al tocar la imagen capturada, que esta, se amplie ocupando todo el
ancho y alto de la pantalla.

- 89 -
Tema 8
Gestin de Mapas y GPS

Mapas

La funcionalidad MapView, permite al desarrollador incorporar uno o ms


mapas de Google en su aplicacin.

Permite a su vez realizar diferentes tipos de acciones utilizando la


informacin proveniente del mapa y comparndola con diferentes parmetros
del dispositivo, como puede ser su situacin.
Mapas

Se pueden marcar puntos de inters en el mapa e incluso utilizar


herramientas de geocoding (traduccin de coordenadas de latitud/ longitud
en la direccin fsica ms cercana.

MapView slo est disponible para su uso en dispositivos y, por lo tanto, no


funciona sobre el simulador.

Para poder probar esta caracterstica se debe hacer sobre un dispositivo


con sistema operativo iOS, sobre el simulador del XCode o sobre un
dispositivo Android.
Mapas

Para poder probarlo sobre Android, se deben denir los permisos de


Internet y de localizacin el chero build.settings de nuestro proyecto.

- 90 -
settings =
{
android =
{
usesPermissions =
{
-- Required by the MapView to fetch its contents from the Google Maps servers.
"android.permission.INTERNET",

-- Optional permission used to display current location via the GPS.


"android.permission.ACCESS_FINE_LOCATION",

-- Optional permission used to display current location via WiFi or cellular service.
"android.permission.ACCESS_COARSE_LOCATION",
},
usesFeatures =
{
-- If you set permissions "ACCESS_FINE_LOCATION" and "ACCESS_COARSE_LOCATION" above,
-- then you may want to set up your app to not require location services as follows.
-- Otherwise, devices that do not have location sevices (such as a GPS) will be unable
-- to purchase this app in the app store.
{ name = "android.hardware.location", required = false },
{ name = "android.hardware.location.gps", required = false },
{ name = "android.hardware.location.network", required = false },
},
},
}

myMap = native.newMapView( Xcenter, Ycenter, width, height )

Mediante esta instruccin, creamos una vista de mapa en nuestra


aplicacin situada centrada en las coordenadas especicadas (Xcenter,
Ycenter) y con el tamao indicado (width, height)

Este constructor nos devuelve un objeto Corona, el cual puede ser


tratado como cualquier otro dentro de nuestra vista.

Con estas caractersticas podemos conseguir funcionalidades no


permitidas dentro de las aplicaciones nativas de Apple, como mover el
mapa o transformarlo en un objeto fsico.

- 91 -
Atributos del Mapa

myMap.mapType = standard | satellite | hybrid

Modicando el atributo mapType, podemos elegir entre las diferentes


vistas de mapa que tenemos disponibles.

En este caso, contamos con tres opciones. La vista de mapa normal


(standard), la imagen desde el satlite (satellite) o la mezcla de los dos
estilos (hybrid).

El estilo por defecto es standard.

myMap.isZoomEnabled = true | false

Modicando esta propiedad del mapa determinamos si es posible


realizar las acciones gestuales (pinch) para ampliar y reducir la vista
del mapa.

El valor por defecto es true.

myMap.isScrollEnabled = true | false

Esta propiedad nos indica si le permitimos al usuario hacer scroll


sobre la vista del mapa.

El valor por defecto es true.

myMap.isLocationUpdating = true | false

Con esta opcin indicamos si se muestra o no la posicin actual del


usuario.

Cuando activamos esta propiedad este valor se ir actualizando


constantemente en el mapa segn se vaya moviendo el dispositivo
fsicamente.

- 92 -
El valor por defecto es false.

isVisible = myMap.isLocationVisible

Se trata de una propiedad de solo lectura la cual nos indica si la


posicin del usuario se encuentra dentro de la regin que estamos
mostrando en ese momento en nuestra vista del mapa.

Este valor est basado en una aproximacin, por lo que puede llevar
a errores cuando la posicin est en los lmites del mapa.

Funciones del Mapa

latitude, longitude = myMap:getAddressLocation (Direccin a buscar)

Con esta funcin obtenemos las coordenadas (longitud y latitud) de la


direccin que pasemos por parmetro.

Estas coordenadas se obtienen a travs de una peticin HTTP sobre


Google maps.

Aparte de direcciones, podemos usar como parmetros sitios


destacados y el servicio de Google se encargar de localizarlos (Torre
Eiel, Liberty Statue).

Esta informacin nos puede servir para colocar un marcador en el


mapa, para volver a centrar el mapa en la localizacin deseada o para
llevar a cabo cualquier funcin que incluya el uso de un par de
coordenadas.

myLocation = myMap:getUserLocation ()

Esta sentencia contiene una tabla con la informacin detallada de la


posicin del usuario.

Los valores que podemos encontrar dentro de esta tabla son los
siguientes:

- 93 -
longitude | latitude | altitude | accuracy | time | speed | direction | isUpdating

El ltimo parmetro nos indica si en el instante que capturamos la


localizacin del usuario, est se est actualizando.
myMap:setRegion (latitude, longitude, latitudeSpan, longitudeSpan, isAnimated)

Movemos la parte visible de nuestro mapa a una nueva localizacin


declarada por los parmetros latitude y longitude.

Con los valores de latitudeSpan y longitudeSpan denimos el nivel de


zoom sobre el centro de nuestra regin.

El ltimo parmetro nos indica si la transicin hacia la nueva regin se


realizar mediante una animacin o de golpe (true / false).

myMap:setCenter (latitude, longitude, isAnimated)

Mediante esta funcin movemos la regin actual de nuestro mapa a


una nueva cuyo centro es el par de coordenadas (latitude y longitude)
que introducimos por parmetro.

El ltimo parmetro es un valor booleano el cual nos indica si la


transicin a la nueva regin se hace automtica o mediante una
animacin.

myMap:addMarker (latitude, longitude, { title = Titulo, subtitle = Subttulo})

Mediante el uso de esta funcin agregamos un marcados en las


coordenadas indicadas.

La tabla que usamos como tercer parmetro, nos indica el ttulo y el


subttulo del popup que saldr al hacer click sobre el marcador en el
mapa.

myMap:removeAllMarkers()

Funcin para eliminar todos los marcadores que tengamos dentro de


nuestra vista de mapa.

- 94 -
Geocoding

Un par de coordenadas de latitud/longitud pueden ser transformadas, en


una direccin aproximada.

Para ello, internamente, nos conectaremos a los servidores de Google para


transformar esta informacin.

Esta conexin no depende de nosotros, por lo que, el rendimiento de


nuestra aplicacin puede verse resentido dependiendo del estado de los
servidores de Google.

Para utilizar esta funcionalidad dentro de los mapas, lo primero que


debemos hacer es poner nuestra aplicacin a escuchar el evento
mapAddress.

Con el uso de la funcin

myMap:nearestAddress (latitude, longitude, resultHandler)

obtendremos una llamada de tipo asncrono sobre la funcin que hayamos


denido en resultHandler.

Los parmetros devueltos por el evento son los siguientes:

event.street - el nombre de la calle


event.streetDetail - el nmero de la calle (u otros datos sobre la localizacin)
event.city - la ciudad o el pueblo
event.cityDetail - informacin adicional sobre la ciudad
event.region - el estado o la provincia
event.regionDetail - la regin por debajo del estado o la provincia
event.postalCode - el cdigo postal
event.country - el nombre del pas
event.countryCode - la abreviacin estndar del pas

- 95 -
event.isError - indica si la conexin nos devuelve algn tipo de error

Un ejemplo para la captura del evento sera el siguiente:

local function mapAddressHandler( event )


if event.isError then
native.showAlert("Error", "mapView Error: " .. event.errorMessage , {"OK"})
else
native.showAlert("Correcto", "La localizacin est en: " .. event.city .. ", " ..
event.country , {"OK"})
end
end

myMap:nearestAddress( 38.898748, -77.037684, mapAddressHandler )

- 96 -
Ejercicios Tema 8

Ejercicio 1

En este ejercicio vamos a utilizar los mapas nativos gracias a la funcionalidad


MapView que nos ofrece Corona. En muy pocas lineas podremos utilizar
mapas completamente funcionales en nuestra aplicacin.

Hay que sealar que Corona trata los mapas como otro objeto ms de
nuestra aplicacin por lo que podremos aplicarle si queremos cualquier
funcionalidad tpica de tratamiento de imgenes como rotar el mapa o
moverlo por la pantalla.

Con la siguiente lnea crearemos y mostraremos un mapa:

local mapa = native.newMapView( 0, 0, 320, 420 )

Los parametros de la funcion newMapView son los puntos de posicin del


mapa y su tamao.

En nuestro caso lo colocariamos en el punto de origen (0,0) con un tamao


de (320,420)

Para comprobar los distintos modos de vista que poseen nuestros mapas
vamos a crear tres botones en la parte inferior de nuestra aplicacin.

local rectanguloRojo = display.newRoundedRect (60,425,80,40, 20)


rectanguloRojo:setFillColor (1, 0, 0)
local rectanguloVerde = display.newRoundedRect (160,425,80,40, 20)
rectanguloVerde:setFillColor (0, 1, 0)
local rectanguloAzul = display.newRoundedRect (260,425,80,40, 20)
rectanguloAzul:setFillColor (0, 0, 1)

Una vez creados los botones, les aadiremos los manejadores para controlar
los eventos de pulsado, y estos controladores cambiaran el tipo de vista del
mapa.

local function pulsarBotonRojo(event)


if(event.phase == "began") then
mapa.mapType = "standard"
end
end

local function pulsarBotonAzul(event)


if(event.phase == "began") then
- 97 -
mapa.mapType = "satellite"
end
end
local function pulsarBotonVerde(event)
if(event.phase == "began") then
mapa.mapType = "hybrid"
end
end

-- Agregamos los eventos que controlarn cuando pulsemos un botn


rectanguloRojo:addEventListener ("touch", pulsarBotonRojo)
rectanguloVerde:addEventListener ("touch", pulsarBotonVerde)
rectanguloAzul:addEventListener ("touch", pulsarBotonAzul)

Ampliacin 1

Como ampliacin vamos a reutilizar los botones ya creados para comprobar


otras de las funciones que nos ofrecen los mapas nativos.

Uno de los botones deber centrar el mapa en la regin en la cual nos


situemos.

Otro deber colocar una marca en el centro del mapa.

El ltimo botn deber eliminar todas las marcas que hayamos colocado
anteriormente

Ejercicio 2

Otra opcin para mostrar mapas es utilizar la Google Maps app.

Para utilizar este servicio, es tan fcil como llamarlo de la siguiente manera:

system.openURL("comgooglemaps://")

Otra de las principales cualidades de Google Maps es el conocido Street


View al cual podriamos llamar de la siguiente manera:

system.openURL("comgooglemaps://? center=40.765819,-
73.975866&zoom=14&views=traffic&mapmode=streetview")

- 98 -
Para asegurarnos de que Google Maps no va a dejarnos colgados por
cuestiones ajenas a nuestra aplicacin, podemos asegurarnos de que google
maps ha funcionado, y en caso de fallo redirigir a Apple Maps de la siguiente
manera:

local didOpenGoogleMaps =system.openURL("comgooglemaps://?


daddr=San+Francisco, +CA&saddr=cupertino")

if ( didOpenGoogleMaps == false ) then --defer to Apple Maps


system.openURL("http://maps.apple.com/?daddr=San+Francisco,
+CA&saddr=cupertino")
end

Ampliacin 2

Prueba a modicar las direcciones para crear tus propios recorridos y


mostrarlos al pulsar un botn. Esto suele ser muy aplicado a la hora de
querer mostrar al publico como llegar a ciertos eventos o ocinas.

- 99 -
Tema 9
Diseando la interfaz de usuario

Interfaces
Mediante podemos acceder a diferentes caractersticas nativas del
dispositivo donde estemos ejecutando nuestra aplicacin.

Podemos acceder con una simple lnea de cdigo a las alertas del
dispositivo, campos para creacin de formulario, vistas de carga... etc.
Interfaces

Activity Indicator

native.setActivityIndicator (state)

Mediante esta funcin indicamos si el indicador de actividad o


indicador de carga est activo o no (true o false respectivamente).

Este indicador no se activar hasta que el bloque donde est


contenida la llamada al mtodo se haya ejecutado por completo.

Todos los eventos de toque se anulan una vez mostremos el


indicador ya que quedar por encima de todos los objetos contenidos
en nuestra vista.

Para su mejor funcionamiento, se aconseja hacer las llamadas para


mostrar/ocultar el indicador desde mtodos diferentes.

native.setActivityIndicator( true )

-- oculta el indicador despus de 2 segundos

timer.performWithDelay( 2000, function()


native.setActivityIndicator( false )
end, 1)

- 100 -
Alertas

native.showAlert (title, message [, buttonLabels [,listener]])

Mediante la llamada a este mtodo mostramos una alerta, del tipo


denido en el dispositivo, con el ttulo y el mensaje pasados por
parmetro (title, message).

Mientras se muestra la alerta, el programa sigue en ejecucin en


background, pero todas las interacciones del usuario quedan
bloqueadas hasta que no se oculte la alerta.

buttonLabels se trata de una tabla donde denimos cada uno de los


botones que aparecern en la alerta. Se debe incluir al menos uno.

El primer botn denido estar resaltado y ser tomado como el


botn por defecto.

El mximo nmero de botones permitidos en una alerta es de 6.

El mtodo que denamos como listener ser ejecutado cuando el


usuario pulse cualquiera de los botones de la alerta.

Dentro del evento capturado podemos acceder a diferentes


propiedades. Una de ellas sera event.action, la cual nos devuelve lo
sucedido con la alerta.

Los valores para event.action son, clicked, si el usuario ha pulsado


alguno de los botones y cancelled, si la alerta se ha eliminado con el
mtodo native.cancelAlert().

local function onComplete( event )


if "clicked" == event.action then
local i = event.index
if 1 == i then
-- No hacemos nada, se cierra la alerta
elseif 2 == i then
-- Abrimos una URL cuando se pulsa el segundo botn
system.openURL( "http://viveahora.travel" )
end
end

- 101 -
end

local alert = native.showAlert( "Vive Ahora", "Agencia de viajes", { "OK", "Ms


Info" }, onComplete )

native.cancelAlert (alert)

Cancelamos la alerta pasada por parmetro en este funcin.

Por ejemplo, podramos ocultar una alerta, pasado un tiempo


determinado.

Fuentes

native.newFont (name [,size])

Creamos un objeto de tipo fuente, el cual puede ser posteriormente


asignado a un campo de texto nativo o a una caja de texto.

Tambin se puede usar como parmetro en el momento de la


creacin de objetos de texto con display.newText().

El parmetro name especica el nombre de la fuente alojada en el


dispositivo nativo. Se puede obtener una lista de todas las fuentes
disponibles ejecutando el mtodo native.getFontNames().

Aparte podemos usar constantes como native.systemFont y


native.systemFontBold.

Campo de Texto

native.newTextField (Xcenter, Ycenter, width, height [,listener])

Crea un campo de texto de una sola lnea para introducir texto en las
coordenadas especcas con el tamao indicado.

Las propiedades que se pueden modicar de un campo de texto son:

object.align - puede ser cualquier de los valores left, center o


right.
object.font - la fuente para el campo de texto

- 102 -
object.hasBackground - es true cuando el campo de texto tiene
fondo y false si es transparente.
object.size - el tamao del texto.
object.text - cadena que contiene el texto del campo.

En el parmetro listener podemos especicar la funcin para manejar


cuando el usuario introduce texto en el campo.

Tambin podemos manejar el campo de texto aparte, capturando


sobre el objeto el evento userInput.

local defaultField

local function textListener( event ) if event.phase == "began" then


elseif event.phase == "ended" then

elseif event.phase == "ended" or event.phase == "submitted" then

elseif event.phase == "editing" then

end
end

defaultField = native.newTextField( 150, 150, 180, 30 )


defaultField:addEventListener( "userInput", textListener )

Campo de Texto Multilnea

native.newTextBox (Xcenter, Ycenter, width, height)

Creamos un campo de texto multilnea con scroll para mostrar texto.

Tenemos disponibles las mismas propiedades y los mismos mtodos


que usamos para los campos de texto.

Web Popups

native.showWebPopup (x, y, width, height, url [,options])

Con este componente podemos incorporar a nuestra aplicacin


pequeas vistas a pginas web.

Denimos la coordenada de nuestra vista donde se va a crear (x y) y

- 103 -
el tamao que ocupar (width, height)

En el parmetro url denimos la pgina web que vamos a cargar en


el contenedor.

- 104 -
Ejercicios Tema 9
Ejercicio 1

Para este primer ejercicio, el primer paso va a ser crear una aplicacin como
la siguiente:

Para ello creamos un fondo blanco, colocamos una imagen a gusto en el


centro de la aplicacin y un texto a pie de pantalla para indicar la accin que
debe realizarse.

El cdigo para esto sera el siguiente:

local contentWidth = display.contentWidth


local contentHeight = display.contentHeight
local fondo=display.newRect(contentWidth/2,contentHeight/2,380,480)
fondo:setFillColor(1,1,1)
local logo=display.newImage("imagina.jpg",contentWidth/2,contentHeight/2)
local cuenta = display.newText("Pnchame!!!",contentWidth/2 ,
(contentHeight/2) + 90,nil,25)
cuenta:setFillColor(0,0,0)

Una vez tengamos esto hecho pasaremos a asociarle a la imagen un mtodo


manejador del evento touch como hemos aprendido en temas anteriores y
a dicha accin le diremos que ejecute una Alerta.

Quedara de la siguiente forma:

local function pulsarLogo(event)


native.showAlert("Alerta","Quieres que te redirijamos a la web?",
{"Si","No"},yesPressed)
end

logo:addEventListener ("touch", pulsarLogo)

Como podemos ver, solo hemos dado opcin para dos botones .

El botn No , no har nada, y el de S abrir una pgina web en nuestro


navegador predeterminado. El mtodo listenerAlert deber controlar que
botn ha sido pulsado y actuar en consecuencia.

- 105 -
local function yesPressed(event)
if("clicked"==event.action) then
local i = event.index
if (i == 2) then
--nothing
elseif (i == 1) then
system.openURL( "http://www.imaginaformacion.com" )
end
end
end

A continuacin, para aadir reforzar los conocimientos aprendidos, vamos a


utilizar un Activity Indicator para crear un tiempo de espera. Para saber
cuanto falta, utilizaremos el texto ya creado anteriormente donde indicaba
pnchame para expresar en segundos el tiempo restante para poder
interactuar.

El cdigo sera el siguiente:

local cargando = display.newText("Cargando...",95,100,nil,25)


cargando:setFillColor(0,0,0) native.setActivityIndicator(true)
timer.performWithDelay(1000,function()
cuenta.text="...2"
end)
timer.performWithDelay(2000,function()
cuenta.text="...1"
end)
timer.performWithDelay(3000,function()
native.setActivityIndicator(false)
cargando.text=""
cuenta.text="Pinchame!!!"
end)

Ampliacin 1

Aade un campo de texto debajo de la imagen donde coloques la direccin a


cargar por el Popup, en caso de no haber escrito ningn texto, al pinchar en
la imagen deber aparecer otra alerta indicando que necesitas introducir una
direccin web.

- 106 -
Ampliacin 2

Crea una nueva aplicacin con un campo de texto multilnea y un botn


imprimir por consola. El funcionamiento de la aplicacin ser el siguiente. Al
pulsar el botn imprimir se deber comprobar que el campo de texto, tenga
texto. En caso de no tener, se emitir una alerta avisando al usuario. En
caso de tener texto debers imprimir el texto del campo por consola.

- 107 -
Tema 10
Entrada y Salida

Ficheros

Todos los documentos relacionados con la aplicacin se encuentran


guardados en directorios internos de la propia aplicacin a los cuales no se
puede acceder desde otras aplicaciones.

En determinados directorios de la aplicacin, tenemos permisos de lectura y


escritura, por lo que podemos almacenar y recuperar datos de estos cheros
segn convenga para nuestra aplicacin.

Las rutas para cada uno de los cheros son nicas dentro de nuestra
aplicacin.

Para la creacin de rutas utilizamos la siguiente funcin:

local path = system.pathForFile (filename [, baseDirectory])

Nos devuelve la ruta del chero especicado como primer parmetros.

Podemos denir en el segundo parmetro a partir de qu directorio base se


crear la ruta solicitada.

Por lo general, los cheros deben estar almacenados en alguno de estos 3


directorios:

system.DocumentsDirectory - directorio usado para aquellos


cheros que deban permanecer almacenados entre las diferentes
ejecuciones de la aplicacin.

system.TemporaryDirectory - los cheros almacenados en este


directorio no aseguran seguir guardados en siguientes ejecuciones de
la aplicacin.

system.ResourceDirectory - es el directorio donde se encuentran


todos los cheros relacionados con la aplicacin (imgenes, sonidos...).

- 108 -
Para la lectura de cheros utilizaremos la librera io provista por Lua.

Esta librera nos permite abrir cheros especicndole la ruta en la que se


encuentran.

Ejemplo para leer un chero situado en nuestro directorio de documentos.

local path = system.pathForFile( "data.txt", system.DocumentsDirectory )


local file = io.open( path, "r" )
if file then -- nil if no file found
local contents = file:read( "*a" )
print( "Contenido de " .. path .. "\n" .. contents )
io.close( file )
end

Aseguraos de colocar el chero de texto en el directorio correcto.

En el ejemplo anterior hemos obtenido la ruta del chero el cual vamos a


leer, especicando el nombre del chero y el directorio base donde poder
encontrarlo.

Mediante la funcin io.open procedemos a abrir el chero para su lectura.

Esta funcin, aparte de recibir la ruta con el chero, podemos indicarle el


modo de apertura de ese chero. Las opciones son:

r - modo lectura. Es el definido por defecto


w - modo escritura.
a - escribe, pero aadiendo el contenido al ya existente en el fichero.
r+ - modo actualizacin. Todos los datos anteriores se guardan
w+ - modo actualizacin. Todos los datos anteriores son borrados
a+ - modo actualizacin. Todos los datos anteriores se guardan y slo se puede
escribir al final del fichero.

Ejemplo para escribir en un chero situado en nuestro directorio de


documentos.

- 109 -
local path = system.pathForFile( "data.txt", system.DocumentsDirectory )

-- io.open opens a file at path. returns nil if no file found


local file = io.open( path, "r" )
if file then
-- read all contents of file into a string
local contents = file:read( "*a" )
print( "Contenido de " .. path .. "\n" .. contents )
io.close( file )
else
-- create file b/c it doesn't exist yet
file = io.open( path, "w" )
local numbers = {1,2,3,4,5,6,7,8,9}
file:write( "Alimntame con datos
\n", numbers[1], numbers[2], "\n" )
for _,v in ipairs( numbers ) do file:write( v, " " ) end
file:write( "\nNo quedan datos
\n" )
io.close( file )
end

En el ejemplo anterior hemos seguido los mismos pasos que para leer de
chero, solo que esta vez hemos utilizado el mtodo write.

Con el mtodo system.pathForFile seleccionamos el directorio donde se


crear o modicar nuestro chero.

Es muy importante no crear, modicar o escribir cheros en el directorio


ResourceDirectory pues cuando la aplicacin se lanza se comprueba la
integridad de la aplicacin. En caso de fallo de integridad tu app no se
lanzar a ejecucin y ser detectado como malware.

Para escribir un salto de linea se utilizar el carcter especial \n

Operaciones de manipulacin implcitas:

io.close([le]) equivalente a le:close( ), si no especicamos un chero


cerrar el chero de salida por defecto

- 110 -
io.ush( ) equivalente a le:ush, libera los buses de escritura en un chero
io.input([le]) llamado con el nombre de un chero, abre dicho chero en
modo texto y lo asocia al manejador por defecto, llamado con el manejador
de chero simplemente asocia dicho manejador al denido por defecto. En
caso de error esta funcin propaga el error en vez de devolver un cdigo de
error.

io.lines([lename]) abre el chero en modo lectura y devuelve un iterador


con el cual podremos recorrer todas las lineas de dicho chero. A
continuacin un ejemplo:
for line in io.lines(filename) do body end
io.open(lename [, mode]) explicado anteriormente.
io.output([le]) similar a io.input pero opera sobre la salida.
io.popen(prog [,mode]) ejecuta el programa prog en un proceso separado y
devuelve un manejador para leer o escribir los datos de dicho programa.
Esta funcin es dependiente del sistema por lo que no esta disponible en
todas las plataformas.
io.read(...) equivalente a io.input( ):read
io.tmple( ) devuelve un manejador para un chero temporal que es abierto
en modo modicar.
io.type(obj) comprueba si el objeto es un manejador valido. Devuelve el
string le si es un manejador abierto , closed le si est cerrado y nil si
no lo es.
io.write(...) equivalente a io.output( ):write.

Operaciones de manipulacin explcita:

le:close( ) cierra los cheros.


le:ush( ) libera los buses de escritura en un chero
le:lines( ) abre el chero en modo lectura y devuelve un iterador con el cual
podremos recorrer todas las lineas de dicho chero.
le:read(...) lee del chero de acuerdo a los formatos:
*n lee un nmero
*a lee el chero entero desde la posicin actual, devolviendo un string
vaco al nal del chero.
*l lee la siguiente linea, devolviendo nil al nal del chero

- 111 -
le:seek([whence] [, oset]) modica y obtiene la posicion del chero
mediante el string whence y el desplazamiento oset, siendo los posibles
valores de whence:
set inicio del chero
cur posicion actual
end nal del chero

le:setvbuf(mode [, size]) modica el modo de buering para un chero de


salida. Hay tres modos de buering:
no : sin buering, el resultado de cualquier operacin de salida se
ejecuta inmediatamente.
full : buering completo, el buer se descarga cuando se llena o
cuando se le pide mediante ush.
line : buering por lineas, el buer se descarga despus de la entrada
de una nueva linea.
le:write(...) escribe el valor de sus argumentos en el chero. Los
argumentos deben ser strings o nmeros.

JSON

Las funciones de manejo de datos mediante JSON estn integradas en


Corona

Recuerda que para utilizar una libreria integrada en corona solo hace falta
utilizar require json y almacenar su valor en una variable local.

JSON es muy similar a una estructura de tablas de Lua. Un ejemplo a


continuacin:

{
"name": "Jack (\"Bee\") Nimble",
"format": {
"shape": "rect,
"width": 1920,
"height": 1080,
"interface": false,
"framerate": 24
}
}

- 112 -
Si tu JSON esta almacenado en un chero .json que tienes en tu directorio,
debers leer dicho chero y almacenarlo en una variable, para ello te
aconsejamos que utilices una funcin como la que te mostraremos a
continuacin:

-- jsonFile() loads json le & returns contents as a string


local jsonFile = function( lename, base )

-- set default base dir if none specied


if not base then base = system.ResourceDirectory; end

-- create a le path for corona i/o


local path = system.pathForFile( lename, base )

-- will hold contents of le


local contents

-- io.open opens a le at path. returns nil if no le found


local le = io.open( path, "r" )
if le then
-- read all contents of le into a string
contents = le:read( "*a" )
io.close( le ) -- close the file after using it
end
return contents
end

Si tu JSON esta almacenado en un string, necesitas decodicarlo, que es


otra manera de decir, transformar mi JSON en una tabla Lua.

Para ello utilizaremos una funcin llamada decode

Utilizando la funcin anterior podemos decodicar el valor de un archivo


JSON a una tabla Lua con el siguiente cdigo:

local json = require "json"

- 113 -
local t = json.decode( jsonFile( "sample.json" ) )

Si tienes una tabla Lua y quieres transformarla en JSON solo tienes que
utilizar la funcin inversa de decode, es decir, encode. A continuacin un
ejemplo:

local jsonString = json.encode( myLuaTable )

En caso de necesitar obtener los JSON de un ordenador remoto o un


servicio web, el proceso ser el mismo que el explicado, solo que
obviamente habr que descargarlos primero.

Base de datos

Corona incluye soporte en todas las plataformas para bases de datos


SQLite.

La API que provee las funciones para utilizar bases de datos SQLite estan
disponibles en luaforge.net/projects/luasqlite/ as como la documentacin se
puede leer en luasqlite.luaforge.net/lsqlite3.html.

Recuerda que al proveer el directorio a la funcion open( ) te asegures de


utilizar system.pathForFile( ). Si intentas abrir directamente con el nombre de
la base de datos, por ejemplo base_de_datos.db no funcionar
correctamente.

A continuacin os mostraremos un ejemplo de como abrir una base de


datos guardada en memoria, crear una nueva tabla, aadir datos y
nalmente mostrar dichos datos en pantalla.

require "sqlite3"
local db = sqlite3.open_memory()

db:exec[[
CREATE TABLE test (id INTEGER PRIMARY KEY, content);
INSERT INTO test VALUES (NULL, 'Hello World');
INSERT INTO test VALUES (NULL, 'Hello Lua');
INSERT INTO test VALUES (NULL, 'Hello Sqlite3')
]]

print( "version " .. sqlite3.version() )

for row in db:nrows("SELECT * FROM test") do

- 114 -
local t = display.newText(row.content, 150, 120 * row.id, null, 16)
t:setTextColor( 1, 0, 1)
end

A continuacin os mostraremos un ejemplo de como abrir una base de


datos guardada en chero y comprobar si una tabla existe antes de crearla.
Importante acordarse de cerrar la conexin con la base de datos al salir

--Include sqlite
require "sqlite3"
--Open data.db. If the file doesn't exist it will be created
local path = system.pathForFile("data.db", system.DocumentsDirectory)
db = sqlite3.open(path)

local function onSystemEvent(event)


if(event.type == "applicationExit") then
db:close()
end
end

--Setup the table if it doesn't exist


local tablesetup = [[CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, content,
content2);]]
print(tablesetup)
db:exec( tablesetup )
--Add rows with a auto index in 'id'. You don't need to specify a set of values because we're
populating all of them
local testvalue = {}
testvalue[1] = 'Hello'
testvalue[2] = 'World'
local tablefill =[[INSERT INTO test VALUES (NULL, ']]..testvalue[1]..[[',']]..testvalue[2]..[['); ]]
local tablefill2 =[[INSERT INTO test VALUES (NULL, ']]..testvalue[2]..[[',']]..testvalue[1]..[['); ]]
db:exec( tablefill )
db:exec( tablefill2 )
--setup the system listener to catch applicationExit
Runtime:addEventListener( "system", onSystemEvent )

- 115 -
Ejercicios Tema 10

Ejercicio 1

Vamos a practicar lo aprendido en entrada/salida de cheros. Para ello


haremos ejercicios utilizando la librera io.

Primero vamos a crear un chero en el que escribir. Para ello debemos de


crear un path en el cual le indicaremos el nombre del chero de la siguiente
manera:

local path = system.pathForFile("miFichero.txt", system.DocumentsDirectory)

Luego vamos a escribir algo en dicho chero:

local le = io.open( path, "w" )


le:write( "Este es mi primer chero.\n")
io.close( le )

Si ahora comprobis el chero veris que contiene lo que le hemos puesto.

A continuacin vamos a aadir ms texto al chero:

le = io.open( path, "a" )


le:write( "Sigo escribiendo en mi chero, cmo me gusta mi chero.\n")
io.close(le)

Y por ltimo vamos a hacer que lea el texto del chero, mostrndose el
contenido por la Terminal:

local le = io.open(path,"r")
local contenido=le:read("*a")
print(contenido)

Qu pasara si en vez de usar el modo a usara el w la segunda vez que


escribimos?Juega con los modos de acceso y comprueba todas las
posibilidades.

- 116 -
Ampliacin 1

Si solo quisiera leer las lineas pares hasta el nal del texto, cmo podra
conseguirlo? Implemntalo.

Pista: utiliza la funciones line para recorrer el contenido.

Ejercicio 2

En este ejercicio vamos a crear una tabla Lua y a partir de ella vamos a
obtener un archivo JSON.

Para ello lo primero es crear nuestra tabla , por ejemplo esta :

local tablaTrabajadores= {{nombre="Paco",puesto="Limpiador",salario="500"},


{nombre="Fulano",puesto="Administrativo",salario="800"},
{nombre="Perico",puesto="Informtico",salario="5000"},
{nombre="Mengano",puesto="Jefe de ventas",salario="1500"}}

Ahora deberemos transformar nuestra tabla lua a un valor JSON , y para ello
utilizamos la funcin encode que nos proporciona Corona.

local json = require "json"


local jsonString = json.encode(tablaTrabajadores)

Por ltimo guardamos el valor obtenido por la funcin en un chero .json


utilizando la librera io como hemos aprendido anteriormente

local path = system.pathForFile("myJSON.json",system.DocumentsDirectory)


local le = io.open(path,"w")
le:write(jsonString)
io.close(le)

Ampliacion 2

Ahora que ya sabemos crear cheros .json a partir de tablas lua vamos a

- 117 -
hacer el paso contrario. Utilizando un .json cualquiera, el que habis creado
antes o cualquiera que descarguis de Internet, decodicarlo a una tabla lua
y luego mostrarlo por consola.

Ejercicio 3

En este ejercicio vamos a crear una base de datos y a insertar unas las.
Para ello primero creamos la base de datos y la tabla en caso de no existir.

require "sqlite3"
local path = system.pathForFile("miBaseDeDatos.db",
system.DocumentsDirectory)
db = sqlite3.open( path )
local function onSystemEvent( event )
if( event.type == "applicationExit" ) then
db:close()
end
end
local tablesetup = [[CREATE TABLE IF NOT EXISTS tablaTrabajadores (id
INTEGER PRIMARY KEY, nombre, puesto, salario);]]
print(tablesetup)
db:exec( tablesetup )

Ahora introduciremos en la base de datos unas las:

local paco =[[INSERT INTO tablaTrabajadores VALUES (NULL, "Paco",


"Limpiador","400" )]]
local manolo =[[INSERT INTO tablaTrabajadores VALUES (NULL, "Manolo",
"Becario","Las gracias" )]]
db:exec( paco )
db:exec( manolo )

Por ltimo las visualizaremos y las mostraremos por la Pantalla:


local titulo = "Trabajadores"
local tit = display.newText(titulo,160,60,null,40)
tit:setFillColor(1,0,1)
--print all the table contents
for row in db:nrows("SELECT * FROM tablaTrabajadores") do
local nombre = "Nombre :"..row.nombre
local puesto = "Puesto : "..row.puesto
local salario = "Salario :"..row.salario
local t = display.newText(nombre, 160, row.id*100, null, 16)
t:setFillColor(1,0,1)
local t1 = display.newText(puesto, 160, 20 + row.id*100, null, 16)
- 118 -
t1:setFillColor(1,0,1)
local t2 = display.newText(salario, 160, 40 + row.id*100, null, 16)
t2:setFillColor(1,0,1)
end
Ampliacin 3

En la siguiente ampliacin deberis eliminar solo a uno de los trabajadores y


editar el otro trabajador modicando su puesto y su salario.

Mostrar el contenido de la base de datos para comprobar que las


instrucciones sobre la base de datos se han ejecutado correctamente.

- 119 -
Tema 11
Composer y Widget

Composer

La API de Composer es una herramienta muy potente y exible.

La estructura de los Composer se basa en crear varias Escenas y


encadenarlas mediante funciones para lograr la estructura navegacional
deseada.

Por defecto, las escenas de nuestro Composer no se eliminan cuando hay


una transicin de escena. Sin embargo, gracias a las libreras ofrecidas por
Corona podemos eliminar las escenas en cada uno de los cambios.
Composer

Para asegurarnos de que cada escena es eliminada en su transicin, en el


archivo principal, main.lua elegiremos la opcin recycleOnSceneChange a
true.

Para cambiar de una escena a otra hay que utilizar el mtodo


Composer.gotoScene( )

Recordar que para utilizar la librera Composer hay que inicializarla

local composer = require "composer"


composer.recycleOnSceneChange = true

Necesitaremos un chero .lua para cada una de las escenas a mostrar.

Para crear la nueva escena deberemos importar la librera composer como


hemos comentado anteriormente y crear la escena con el mtodo
composer.newScene( )

Cada escena deber implementar los mtodos controladores de eventos


para poder viajar entre escenas correctamente.

- 120 -
local composer = require "composer"
local scene = composer.newScene()

-- setup function: function scene:createScene( event )


local img = display.newImage( "image.png" )
self.view:insert( img )
end

scene:addEventListener( "createScene" )

-- cleanup function:
function scene:destroyScene( event )
print( "Called when scene is unloaded." )
end

scene:addEventListener( "destroyScene" )

return scene

Los diferentes eventos que se producen en las transiciones de escenas son


los siguientes

create : cuando la escena aun no existe


show : al entrar la escena en pantalla, tiene dos fases:
will : cuando va a entrar
did : al entrar
hide : al salir la escena de la pantalla, tiene dos fases:
will : cuando va a salir
did : al salir
destroy : al destruir la pantalla
overlayBegan : cuando se llama a la escena mediante el metodo
composer.showOverlay( )
overlayEnded : cuando se esconde la pantalla mediante el metodo
composer.hideOverlay( )

Las funciones bsicas para moverse entre escenas seran las siguientes

composer.gotoScene( sceneName [, options] ) la cual nos traslada a la


escena cuyo nombre coincida con las opciones de transicin elegidas

- 121 -
Las posibles transiciones pueden ser las siguientes:

fade

zoomOutIn

zoomOutInFade

zoomInOut

zoomInOutFade

Flip

FlipFadeOutIn

zoomOutInRotate

zoomOutInFadeRotate

zoomInOutRotate

zoomInOutFadeRotate

fromRight (over original scene)

fromLeft (over original scene)

fromTop (over original scene)

fromBottom (over original scene)

slideLeft (pushes original scene)

slideRight (pushes original scene)

slideDown (pushes original scene)

slideUp (pushes original scene)

crossFade

Otras funciones bsicas son:

composer.getPrevious( ) devuelve el nombre de la anterior escena

composer.getScene( sceneName ) devuelve la escena cuyo nombre


coincida con el parametro sceneName

composer.getCurrentSceneName( ) devuelve el nombre de la escena


actual

- 122 -
Widget

Los widgets son elementos interactivos incluidos dentro de la librera


Widget

Son elementos muy tiles que nos ayudarn a disear interfaces complejas
de forma rpida y sencilla

A continuacin expondremos algunos de los widgets ms comunes y tiles


Widget

Los primeros widgets a mostrar sern el on/o Switch, Radio Button y


CheckBox, los cuales son especializaciones del widget genrico switch
Widget

Como siempre recordar que para utilizar una libreria primero hay que
importarla

El cdigo para implementar el controlador de un switch sera el siguiente

local function onSwitchPress( event )


local switch = event.target
local response = switch.id.." is on: "..tostring( switch.isOn )
print( response )
end

- 123 -
Para crear un Checkbox sera el siguiente:

local checkbox = widget.newSwitch


{
left = 60,
top = 230,
style = "checkbox",
id = "My checkbox widget",
initialSwitchState = false,
onPress = onSwitchPress
}

--Text to show the on/off switch state


checkbox.text = display.newText( tostring( checkbox.isOn ), 0, 0,
native.systemFontBold, 18 )
checkbox.text.x = checkbox.x
checkbox.text.y = checkbox.y - checkbox.text.contentHeight

Para crear un Radio button sera el siguiente:

local radioButton = widget.newSwitch


{
left = 150,
top = 230,
style = "radio",
id = "My radio button widget",
initialSwitchState = false,
onPress = onSwitchPress
}

--Text to show the on/off switch state radioButton.text =


display.newText( tostring( radioButton.isOn ), 0, 0, native.systemFontBold, 18 )
radioButton.text.x = radioButton.x
radioButton.text.y = radioButton.y - radioButton.text.contentHeight

- 124 -
Para crear un On/O Switch sera el siguiente:

local onOffSwitch = widget.newSwitch


{
left = 250,
top = 230,
id = "My on/off switch widget",
initialSwitchState = true,
onRelease = onSwitchPress
}

Para controlar manualmente cualquier switch utilizaremos el mtodo


setState

switch:setState{ isOn = true, isAnimated = true, onComplete = function }

Otro widget bastante recurrente es el button

Deberemos crear un manejador de los eventos para el botn como el que


veremos a continuacin

local function onButtonEvent( event )


local phase = event.phase
local target = event.target
if ( "began" == phase ) then
print( target.id .. " pressed" )
target:setLabel( "Pressed" )
--set a new label
elseif ( "ended" == phase ) then
print( target.id .. " released" )
target:setLabel( target.baseLabel )
--reset the label
end
return true
end

- 125 -
La implementacin del botn quedara de la siguiente manera

local myButton = widget.newButton


{
left = 10,
top = 80,
label = "Default",
labelAlign = "center",
font = "Arial",
fontSize = 18,
labelColor = { default = {100,100,100}, over = {255,255,255}},
onEvent = onButtonEvent
}
myButton.baseLabel = "Default"

El tab bar es otro elemento muy comn en las aplicaciones mviles, su


manejador seria parecido al siguiente

local function onPress( event )


local pressedTab = event.target
print( pressedTab._id.." pressed
")
end

La implementacin de los diferentes botones del tab bar sera as

local tabButtons =
{
{
id = "Tab1",
label = "Tab1",
labelColor = { default = {0,0,0}, over = {1,1,1} },
onPress = onPress,
selected = false
},
{
id = "Tab2",
label = "Tab2",
labelColor = { default = {0,0,0}, over = {1,1,1} },
onPress = onPress,
selected = true
},
--more tabs can follow
}

- 126 -
Para colocar el tab bar en pantalla, podemos utilizar el siguiente cdigo

local tabBar = widget.newTabBar


{
left = 50,
top = 150,
width = 240,
height = 60,
buttons = tabButtons
}

Para seleccionar que tab debe estar seleccionado tenemos la funcin


:setSelected([integer]) donde el parmetro indica el indice del botn que
quedar seleccionado

El ltimo widget que vamos a exponer es el Table View, pero hay muchos
ms widgets que os animamos a seguir estudiando en las APIs de Corona

El widget Table View


visualmente sera como
podemos observar en la imagen
de la izquierda. Una tabla con
diferentes las , las cuales
podemos seleccionar y pinchar.

- 127 -
Para utilizar un Table View necesitaremos crear un manejador tanto de la
tabla como de las las

local widget = require( "widget" )

-- Listen for tableView events


local function tableViewListener( event )
local phase = event.phase
local row = event.target

print( event.phase )
end

-- Handle row rendering


local function onRowRender( event )
local phase = event.phase
local row = event.row

local rowTitle = display.newText( row, "Row " .. row.index, 0, 0, nil, 14 )


rowTitle.x = 160
rowTitle.y = 15
rowTitle:setTextColor( 0, 0, 0 )
end

-- Handle touches on the row


local function onRowTouch( event )
local phase = event.phase

if "press" == phase then


print( "Touched row:", event.target.index )
end
end

- 128 -
A la hora de crear la tabla, primero deberemos crear la tabla como tal, y
luego aadiremos las las a dicha tabla.

-- Create a tableView
local tableView = widget.newTableView
{
top = 100,
width = 320,
height = 366,
maskFile = "assets/mask-320x366.png",
listener = tableViewListener,
onRowRender = onRowRender,
onRowTouch = onRowTouch,
}

-- Create 100 rows


for i = 1, 100 do
local isCategory = false
local rowHeight = 40
local rowColor =
{
default = { 1, 1, 1 },
}
local lineColor = { 0,0,0 }
-- Make some rows categories
if i == 25 or i == 50 or i == 75 then
isCategory = true
rowHeight = 24
rowColor =
{
default = { 0.59, 0.63, 0.71, 1 },
}
end
-- Insert the row into the tableView
tableView:insertRow
{
isCategory = isCategory,
rowHeight = rowHeight,
rowColor = rowColor,
lineColor = lineColor,
}
end

- 129 -
Ejercicios Tema 11

Ejercicio 1

En este ejercicio vamos a crear una aplicacin mediante storyboards que


deber tener un aspecto similar al siguiente.

Para ello utilizaremos adems de los


storyboards un tab bar con las
imgenes que adjuntamos en el
campus.

Primero crearemos el main.lua


indicando que utilizaremos storyboads
y widgets.

local storyboard = require "storyboard" local


widget = require "widget"
storyboard.purgeOnSceneChange = true
storyboard.gotoScene( "scene1", "fade",
400 )

Ahora crearemos el tab bar justo


despus de indicar el cambio de
escena, todo lo que vaya despus de
un cambio de escena se quedar en
ejecucin y no variar por dicho
cambio.

-- lo que pongamos por debajo de la transicin no ser afectado por ella


local tabButtons =
{
{
width = 32,
height = 32,
defaultFile = "icon1.png",
overFile = "icon1-down.png",

label = "Botn 1",


selected = true,

- 130 -
},
{
width = 32,
height = 32,
defaultFile = "icon2.png",
overFile = "icon2-down.png",

label = "Botn 2",


},
}
-- una vez creados los botones, creamos el tabBar y asociamos los botones
local tabBar = widget.newTabBar
{
top = display.contentHeight - 50,
width = display.contentWidth,
backgroundFile = "tabbar.png",
tabSelectedLeftFile = "tabBar_tabSelectedLeft.png",
tabSelectedMiddleFile = "tabBar_tabSelectedMiddle.png",
tabSelectedRightFile = "tabBar_tabSelectedRight.png",
tabSelectedFrameWidth = 20,
tabSelectedFrameHeight = 52,
buttons = tabButtons
}

Ahora que hemos creado el main, deberemos crear tantos cheros como
escenas queramos en nuestra aplicacin. Para nuestro caso crearemos 3
escenas las cuales cambiarn al pinchar en la imagen.

Solo mostraremos el cdigo de una de ellas, pues visto el funcionamiento de


una escena, vistas las dems.

local composer = require( "storyboard" )


composer.recycleOnSceneChange = true local scene = composer.newScene()
local image, fondo

Creamos el evento controlador de la imagen, para que al pinchar en ella


vayamos a la escena 2

local function onSceneTouch( self, event )


if event.phase == "began" then
composer.gotoScene( "scene2", "slideLeft", 800 )

- 131 -
return true
end
end

Ahora aadimos los controladores para manejar los eventos producidos por
los cambios de escenas

function scene:create( event )


local screenGroup = self.view

fondo = display.newRect(0,0,320,480)
fondo:setFillColor(250,250,250)
screenGroup:insert(fondo)

image = display.newImage("corona.png",30,100) screenGroup:insert( image )


image.touch = onSceneTouch

text1 = display.newText( "Pulsa en la imagen para continuar", 20, 20,


native.systemFontBold, 12 )
text1:setTextColor( 0 )
text1:setReferencePoint( display.CenterReferencePoint )
text1.x, text1.y = display.contentWidth * 0.5, 50
screenGroup:insert( text1 )
end

function scene:show( event )


print( "1: enterScene event" )
image:addEventListener( "touch", image )
end

function scene:destroy( event )


print( "Dile adis a la escena 1" )
return scene

Por ultimo indicamos que controladores estan asociados a los eventos


producidos

scene:addEventListener( "show", scene )


scene:addEventListener( "create", scene )
scene:addEventListener( "destroy", scene )
return scene

- 132 -
Ampliacin 1

En esta ampliacin deberis aadir el resto de controladores para los


eventos lanzados por los cambios de escena, y sacar por consola el estado
en el que se encuentra en cada momento, para as comprender mejor
cuando se producen estos eventos. Prueba tambin a modicar las
diferentes transiciones entre estados.

Ejercicio 2

En este ejercicio vamos a crear una interfaz como la siguiente:

Utilizando la librera widget podemos crear


componentes visuales de forma muy rpida y
sencilla con un buen acabado visual.

Al pinchar en los diferentes botones


cambiaremos el color de fondo de nuestra
aplicacin al color que indica la label de cada
botn.

Para crear un widget lo primero siempre es


importar la librera como vemos en el cdigo.

local widget = require "widget"

Una vez importada la librera crearemos el fondo blanco de nuestra


aplicacin.

local fondo = display.newRect(0,0,320,480)

Y para aadir cada uno de los botones necesitaremos el controlador del


botn

- 133 -
local function onButtonEventAzul( event )
local phase = event.phase
local target = event.target
if ( "began" == phase ) then
print( target.id .. " pressed" )
target:setLabel( "Pressed" )
--set a new label
fondo:setFillColor(0,0,255)
elseif ( "ended" == phase ) then
print( target.id .. " released" )
target:setLabel( "Azul" )
--reset the label
fondo:setFillColor(255)
end
return true
end

Una vez creado el controlador podemos declarar el botn como vemos a


continuacin.

local myButton = widget.newButton


{
left = 70,
top = 80,
label = "Azul",
labelAlign = "center",
font = "Arial",
fontSize = 18,
labelColor = { default = {0,0,0}, over = {0,0,255} },
onEvent = onButtonEventAzul
}

Crea el resto de botones y comprueba su funcionalidad. Juega con las


propiedades que ofrecen los widgets y prueba diferentes combinaciones.

Ampliacin 2

Crea en una nueva aplicacin un Radio Button, un Check Box y un On/Off


Switch y adeles la funcionalidad que veas oportuno.

- 134 -
Tema 12
Motor Fsico - Parte 2

Motor Fsico - Parte 2

En este tema, vamos a entrar en detalles ms complejos sobre el motor


fsico de corona

Ya hemos visto como construir cuerpos sencillos y detectar sus colisiones,


siendo capaces de tratarlas adecuadamente, pero Corona nos permite la
construccin de cuerpos mas complejos utilizando varios cuerpos simples.

Al crear un cuerpo complejo a partir de cuerpos sencillos podemos denir


caractersticas distintas para cada parte. Por ejemplo si construyramos un
lpiz, la goma seria un cuerpo distinto con un rebote mayor que el resto del
cuerpo.

Adems puesto que cualquier forma simple debe ser cncava, cualquier
forma convexa deber formarse con mltiples formas simples

El constructor para crear un cuerpo complejo es el mismo que para crear un


poligono, solo que con ms de un cuerpo

physics.addBody(displayObject, [bodyType, ] , bodyElement1, bodyElement2,...)

Cada body element tendr sus propias propiedades, junto con su forma
denida para detectar las colisiones.

local physics = require ("physics")


physics.start()

local car = display.newImage("big_red_car.png")


roofShape = { -20,-10, 20,-10, 20,10, -20,10 }
hoodShape = { 0,-35, 37,30, -37,30 }
trunkShape = { 0,-37, 37,-10, 23,34, -23,34, -37,-10 }
physics.addBody( car, "dynamic",
{ density= 3.0, friction=0.5, bounce=0.2, shape=roofShape },
{ density= 6.0, friction=0.6, bounce=0.4, shape=hoodShape },
{ density= 4.0, friction=0.5, bounce=0.4, shape=trunkShape }
)

- 135 -
Un sensor es un cuerpo simple o complejo que produce colisiones pero no
interacta con otros cuerpos.

Todos los objetos sean simples o complejos pueden ser sensores si tienen
la propiedad isSensor a true.

Un ejemplo de sensores podra ser la meta en una carrera o las casillas de


un ajedrez.

local rect = display.newRect( 50, 50, 100, 100 )


rect:setFillColor( 1,1,1,1 )
rect.isVisible = false --optional
physics.addBody( rect, { isSensor = true } )

Los cuerpos pueden ser eliminados como cualquier otro objeto de display

myBody:removeSelf()
-- or
myBody.parent:remove( myBody )

Tienen una lista de propiedades que pueden ser modicadas

body.isAwake indica si esta despierto y en simulacin

body.isBodyActive indica si estan activos, la diferencia entre despierto


y activo, es que un cuerpo dormido se despierta por una interaccin
pero uno inactivo no interacciona con nada

body.isBullet si es una bala se tratar como tal y se detectarn


colisiones de forma continua evitando que por la velocidad del objeto
eviten alguna colisin.

body.isSensor indica si el objeto es un sensor

body.isSleepingAllowed indica si tiene permitido entrar en estado


dormido, no suele ser necesario pues el estado despierto dormido
cambia debido a las interacciones con otros objetos

body.isFixedRotation indica si es capaz de girar sobre si mismo o


verse afectado por este tipo de fuerzas

- 136 -
body.angularVelocity indica con un valor numrico su velocidad
angular

body.linearDamping indica con un valor numrico su valor de


amortiguamiento lineal

body.angularDamping indica con un valor numrico su valor de


amortiguamiento angular

body.bodyType indica con un string el tipo de cuerpo que simula.

static no se mueve ni es afectado por el resto de elementos

dynamic es afectado por la gravedad y las colisiones

kinematic son como los estticos pero pueden ser movidos por
fuerzas diferentes de la gravedad. Los objetos que se pueden
arrastrar, suelen ser kinematic al menos durante el tiempo en
el que se ejecute el arrastre

Algunos mtodos muy tiles de los cuerpos son

body:applyForce(fuerzaX,fuerzaY,puntoX,puntoY) aplica una


fuerza lineal sobre el punto que se indica. Muy til si queremos simular
acciones fsicas

body:applyTorque(fuerzaRotacion) aplica una fuerza de rotacion


sobre el centro del objeto

body:applyLinearImpulse(fuerzaX,fuerzaY,puntoX,puntoY) es
como applyForce solo que aplica un solo impulso, es decir, es una
fuerza momentnea. Podra usarse para simular una explosin

body:applyAngularImpulse(impulsoRotacin) igual que


applyTorque pero momentneo.

Cuando hay colisiones globales con objetos complejos se devuelven


valores adicionales enteros indicando cual es el elemento simple que ha
recibido la colisin

- 137 -
event.element1
event.element2

Cuando la colisin es local se crean dos campos adicionales

event.selfElement
event.otherElement

Los joints o articulaciones son objetos que sirven como unin para objetos
complejos a partir de cuerpos rgidos. Por ejemplo, con joints se podran
crear cadenas o marionetas.

Hay varios tipos bsicos de joints, los mas sencillos son los pivot joint con
los cuales puedes unir dos objetos en un mismo punto de unin. un ejemplo
sera una cadena.

Los distance joint los cuales unen dos cuerpos mediante una distancia
ja.

Los piston joint une dos cuerpos mediante un eje de movimiento, como
los pistones del motor de un coche.

Los wheel joint combinan el piston y el pivot joint de manera que aunque
siempre estn a la misma distancia ambos cuerpos se mueven con libertad.

El pivot joint como hemos explicado antes une dos cuerpos por un
determinado punto.

myJoint = physics.newJoint( "pivot", cuerpoA, cuerpoB, 200,300 )

Por defecto, los joint motors tienen una rotacin mxima as como una
velocidad de motor.

myJoint.isMotorEnabled (boolean)
myJoint.motorSpeed
myJoint.motorTorque -- (get-only)

- 138 -
myJoint.maxMotorTorque -- (set-only)

Si se desea podemos restringir el ngulo de rotacin para simular mejor


determinados procesos.

myJoint.isLimitEnabled = true (boolean)

myJoint:setRotationLimits( -45, 45 )
a1, a2 = myJoint:getRotationLimits()

myJoint.jointAngle -- (get-only; value in degrees)


myJoint.jointSpeed -- (get only; value in degrees per second)

El distance joint une dos cuerpos a una distancia ja.

myJoint = physics.newJoint( "distance", cuerpoA, cuerpoB, cuerpoA.x,cuerpoA.y,


cuerpoB.x,cuerpoB.y )

Tiene tres propiedades bsicas

length es la distancia entre los puntos de altura


frequency es la frecuencia de amortiguacin
dampingRatio es un valor entre 0 y 1 siendo 0 sin amortiguacion y 1
amortiguacin crtica

El piston joint une dos cuerpos mediante un eje de movimiento restringido.

myJoint = physics.newJoint( "piston", cuerpoA, cuerpoB, cuerpoA.x,cuerpoA.y,


axisDistanceX,axisDistanceY )

Pueden tener un motor como el pivot joint solo que este es lineal

myJoint.isMotorEnabled (boolean)
myJoint.motorSpeed -- (linear speed, in units of pixels per second)
myJoint.motorForce -- (get-only)

- 139 -
myJoint.maxMotorForce -- (set-only)

Se puede especicar tambin los rangos de movimiento lineal

myJoint.isLimitEnabled = true (boolean)


myJoint:setLimits( 100, 200 )
p1, p2 = myJoint:getLimits()

myJoint.jointTranslation -- (get-only; linear value in pixels)


myJoint.jointSpeed -- (get only; value in pixels per second)
El wheel joint combina el piston y el pivot joint. La principal diferencia con el
piston joint es que los objetos pueden rotar.

myJoint = physics.newJoint( "wheel", cuerpoA, cuerpoB, cuerpoA.x,cuerpoA.y,


axisDistanceX,axisDistanceY )

Tambin dispone de unos motores lineales y rotacionales

myJoint.isMotorEnabled (boolean)
myJoint.motorSpeed -- (linear speed, in units of pixels per second)
myJoint.motorForce -- (get-only)

Los lmites de rango de movimiento se puede editar

myJoint.isLimitEnabled = true (boolean)

myJoint:setLimits( 100, 200 )


p1, p2 = myJoint:getLimits()

myJoint.jointTranslation -- (get-only; linear value in pixels)


myJoint.jointSpeed -- (get only; value in pixels per second)

El touch joint conecta un cuerpo simple con el punto actual de toque en la


pantalla y aade una fuerza hacia dicho punto arrastrable.

touchJount = physics.newJoint( "touch", cuerpo, cuerpo.x, cuerpo.y )

Hay varios atributos a tener en cuenta, entre ellos la fuerza mxima, la


frecuencia de amortiguacin, y el ratio de amortiguacin.

myJoint.maxForce = 10000
force = myJoint.maxForce

- 140 -
myJoint.frequency = 50
frequency = myJoint.frequency

myJoint.dampingRatio = 0.2
damping = myJoint.dampingRatio

- 141 -
Ejercicios Tema 12

Ejercicio 1

Para este ejercicio vamos a crear un nunchaku el cual podremos mover


pinchando sobre este.

Para ello lo primero ser iniciar el motor fsico y crear las paredes de nuestra
aplicacin, quedando algo similar a la imagen.

Para crear las paredes utilizaremos el siguiente cdigo

local physics = require("physics")

physics.start()

local suelo = display.newRect(0,420,320,460)

physics.addBody(suelo,"static",{friction=0.6})

local paredIzq = display.newRect (-100, 0, 101,


display.contentHeight)

local paredDer = display.newRect


(display.contentWidth, 0, 100,
display.contentHeight)

local techo = display.newRect (0, -100,


display.contentWidth, 101)

physics.addBody(paredIzq,"static",
{bounce=0.1,friction=0.1})

physics.addBody(paredDer,"static", {bounce=0.1,friction=0.1})

physics.addBody(techo,"static",{bounce=0.1,friction=0.1})

Una vez ya tenemos creadas las paredes vamos a proceder a crear las
cadenas y las uniones entre ellas, para lo cual el tipo de joint que mejor nos
viene es el pivot joint.

- 142 -
local cadenaJoints={}
local link ={}
for i=1,5 do
link[i] = display.newImage("link.png")
link[i].x = 100
link[i].y = 56 + (i*24)
physics.addBody(link[i],{density=2.0, friction=0.3, bounce=0})
if(i>1) then
prevLink = link[i-1]
cadenaJoints[#cadenaJoints + 1] =
physics.newJoint("pivot",prevLink,link[i],100,46 + (i*24))
end
end

Ahora crearemos los mangos de nuestro nunchaku, para ello utilizaremos el


siguiente cdigo

local nunchaku={}
nunchaku[1] = display.newRect(100,33,20,55)
nunchaku[1]:setFillColor(0.6,0.1,0.1)
physics.addBody(nunchaku[1],{density=1.0, friction=0.3,bounce=0.3})
cadenaJoints[#cadenaJoints+1] =
physics.newJoint("pivot",link[1],nunchaku[1],100,55)
nunchaku[2] = display.newRect(100,222,20,55)
nunchaku[2]:setFillColor(0.6,0.1,0.1)
physics.addBody(nunchaku[2],{density=1.0, friction=0.3,bounce=0.3})
cadenaJoints[#cadenaJoints+1] =
physics.newJoint("pivot",link[5],nunchaku[2],100,200)

Con esto, tendremos creado nuestro nunchaku, pero no seremos capaces de


arrastrarlo ni moverlo, para lograr el movimiento tendremos que crear dos
touch joint, y para manejar los touch joint, necesitamos su controlador.

El controlador quedara de la siguiente manera

local function dragBody(event)


local body = event.target
local phase = event.phase
local stage = display.getCurrentStage()
if (phase == "began") then

- 143 -
stage:setFocus(body,event.id)
body.isFocus = true
if params and params.center then
body.tempJoint = physics.newJoint("touch",
body,body.x,body.y)
else
body.tempJoint =
physics.newJoint("touch",body,event.x,event.y)
end
body.tempJoint.maxForce = 0.7*body.tempJoint.maxForce
elseif body.isFocus then
if (phase == "moved")then
body.tempJoint:setTarget(event.x,event.y)
elseif (phase == "ended" or phase == "cancelled") then
stage:setFocus(body,nil)
body.isFocus = false
body.tempJoint:removeSelf()
end
end
return true
end

El touch joint tiene bastantes parmetros con los que jugar que harn que
nuestro nunchaku se comporte de una manera distinta. Prueba a variar los
parmetros utilizados o incluso aadir nuevos parmetros de los explicados
en la teora.

Para nalizar lo nico que nos queda es asociar el manejador del touch joint
con los mangos de los nunchakus. Lo cual sera de la siguiente manera.

nunchaku[1]:addEventListener("touch",dragBody)
nunchaku[2]:addEventListener("touch",dragBody)

Ampliacin 1

Haz una aplicacin con la cual seas capaz de disparar un can o una bala
mediante el pulsado de un botn. Para ello debers utilizar los mtodos
body:applyLinearImpulse o body:applyForce y comprueba como varia su
comportamiento.

- 144 -
Ampliacin 2

Aprovechando la aplicacin anterior coloca una diana esttica en la pantalla


y utilizando los widgets que creas oportunos elige la direccin y la fuerza que
aplicars a la bala para intentar acertar a la diana.

- 145 -

Das könnte Ihnen auch gefallen