sábado, 24 de enero de 2015

Colisiones

Existen 3 tipos:

collision

Para estar a la escucha de una colisión de este tipo, el evento se deberá llamar "collision". Este incluye las fases: "began" y "ended", que significan los momento de inicio y roptura del contacto.

preCollision

 Este evento se llama, justo antes que los objetos entren en contacto o interactúen.

postCollision

Este evento se llama, justo después que terminó la intracción entre objetos.

Manejo de Colisiones

Manejo Global

local crate1 = display.newImage( "crate.png", 100, 200 )
physics.addBody( crate1, { density = 1.0, friction = 0.3, bounce = 0.2 } )
crate1.myName = "first crate"

local crate2 = display.newImage( "crate.png", 100, 120 )
physics.addBody( crate2, { density = 1.0, friction = 0.3, bounce = 0.2 } )
crate2.myName = "second crate"

local function onCollision( event )

    if ( event.phase == "began" ) then

        print( "began: " .. event.object1.myName .. " and " .. event.object2.myName )

    elseif ( event.phase == "ended" ) then

        print( "ended: " .. event.object1.myName .. " and " .. event.object2.myName )

    end
end

Runtime:addEventListener( "collision", onCollision )
 
 
Manejo Local
 
 
local crate1 = display.newImage( "crate.png" )
physics.addBody( crate1, { density=3.0, friction=0.5, bounce=0.3 } )
crate1.myName = "first crate"

local crate2 = display.newImage( "crate.png" )
physics.addBody( crate2, { density=3.0, friction=0.5, bounce=0.3 } )
crate2.myName = "second crate"

local function onLocalCollision( self, event )

    if ( event.phase == "began" ) then

        print( self.myName .. ": collision began with " .. event.other.myName )

    elseif ( event.phase == "ended" ) then

        print( self.myName .. ": collision ended with " .. event.other.myName )

    end
end

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

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

Física

Corona incluye un motor de física que no requiere de amplios conocimientos previos en física para poder utilizarlo.

Para comenzar a trabajar con física, hace falta instanciar de esta manera:

local fis = require( "physics" )
 
Algunas funciones de la física son:
 

  • fis.start() — Inicia el motor de física o continúa si estaba en pausa. Debes iniciar la física antes de agregarla a cualquier elemento.
  • fis.pause() — Pausa la simulación de física.
  • fis.stop() — Destruye la simulación de física. Si sólo quieres detenerla, debes usar fis.pause().
Opciones de simulación de física 

physics.setGravity() Establece los componentes en x y y del vector de gravedad, en unidades: m/s². Por default es ( 0, 9.8 ) para simular la gravedad del planeta tierra, apuntando hacia abajo en el eje de las Y.

Cuerpos
El mundo de la física en Corona se basa en la interacción de cuerpos físicos. Corona trata a los objetos como cuerpos físicos.

Con el simulador de física activado, los objetos continuarán su estado normal en x y y, rotación, entre todas sus propiedades. Pero, si el objeto es de tipo "dinámico", el motor de física "luchará" contra los intentos de moverlos manualmente, según la fuerza de gravedad y colisiones por ejemplo.

Nota: Cuando eliminas un objeto con object:removeSelf() o display.remove(), esto elimina el objeto de la pantalla y también detiene la simulación física. Sin emargo, si deseas sólo reitarlo como elemento físico, pero que se siga viendo en pantalla, puedes usar: physics.removeBody().

Creando cuerpos

Para crear cuerpos, se hace de la siguiente manera:

physics.addBody( object, { properties } )
 
Las propiedades que puedes utilizar son:
 
Density
 
La densidad se multiplica por el área del cuerpo para determinar su masa. Este
parámetro se basa en el valor estándar 1.0 del agua. Así que los materiales que sean más ligeros
que el agua (como la madera) tienen una densidad menor a 1.0, y los más pesados (como la roca)
tiene una densidad por encima de 1.0.
 
 
Friction

La fricción nunca debe ser negativa. Un valor de 0 significa que no tiene fricción y 1.0
significa una fuerte fricción. El valor default es de: 0.3.

Bounce

El rebote determina la velocidad a la que un objeto regresa tras una colisión.
Los valores mayores a 0.3 suelen rebotar mucho, y un objeto con rebote de 1.0, rebotará por siempre.
Por ejemplo, Si un elemento lo tirán en el piso, rebotará casi a la misma distancia desde
la que fue soltado. Valores de rebote mayores a 1 son válidos, y estos tomarán impulso
trás cada rebote que realice. el valor por default es de 0.2, lo que hace los objetos
"algo rebotables". 

--Ejemplo 1
 
local crate = display.newImage( "crate.png", 100, 200 )
physics.addBody( crate, { density=1.0, friction=0.3, bounce=0.2 } )

local balloon = display.newImage( "balloon.png", 200, 200 )
physics.addBody( balloon, { density=0.1, friction=0.1, bounce=0.4 } )
 
 
 -- Ejemplo 2

local crate1 = display.newImage( "crate1.png", 100, 200 )
local crate2 = display.newImage( "crate2.png", 180, 280 )

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

physics.addBody( crate1, crateMaterial )
physics.addBody( crate2, crateMaterial )


Tipos de cuerpos

dynamic

Estos cuerpos se pueden mover manualmente, pero son afectados totalmente por la física, colisiones y gravedad.

static

Estos cuerpos no se mueven, y simulan las masas físicas como la tierra. Estos cuerpos sólo pueden chocar contra cuerpos dinámicos y nunca con otros estáticos.

Dos formas de usarlos:

--Forma 1

physics.addBody( triangle, "static", { density=1.6, friction=0.5, bounce=0.2 } )
 
--Forma 2
 
physics.addBody( triangle, { density=1.6, friction=0.5, bounce=0.2 } )
triangle.bodyType = "static"
 
 
Formas de cuerpos 


Cuerpos rectangulares

Por default, todos los cuerpos físicos son rectangulares. Los bordes del rectángulo
rodean la imagen. Si la imagen tiene transparencias, estás también estarán dentro del rectángulo.
 
--Ejemplo
local platform = display.newImage( "platform.png", 600, 200 )
physics.addBody( platform, { density=1.0, friction=0.3, bounce=0.2 } ) 
  
Cuerpos circulares

Los cuerpos circulares se crean agregando el parámetro de radio. Esto funciona para pelotas, rocas y otros objetos que pueden tener aspecto circular. Los óvalos no existen, sólo puedes simularlos con polígonos.

--Ejemplo
local ball = display.newImage( "ball.png", 100, 100 )
physics.addBody( ball, { radius=50, density=1.0, friction=0.3, bounce=0.2 } )
 
 
 Cuerpos polígonos

Estos cuerpos pueden crearse con coordenadas en x,y de cada punto del objeto.


Sensores
Cualquier cuerpo puede ser un sensor, la gran diferencia de estos, es que no interactúan con otros cuerpos, pero al colisionar con otros, lanzan un evento de colisión, sin embargo pasan por encima de ellos.



--Forma 1
physics.addBody( goal, "static", { isSensor=true } )

--Forma 2
physics.addBody( goal, "static" )
goal.isSensor = true

 Balas

Las balas en videojuegos deben ser tratadas con características diferentes dada su peculiaridad:

local bullet = display.newCircle( 100, 100, 10 )
physics.addBody( bullet, "dynamic", { radius=10 } )
bullet.gravityScale = 0

--Make the object a "bullet" type object
bullet.isBullet = true

bullet:setLinearVelocity( 800,0 )
 
 
  
Funciones en los cuerpos físicos


SetLinearVelocity

Establece los componentes x, y para ejercer fuerza lineal en el cuerpo, en pixeles por segundo.

object:setLinearVelocity( 2, 4 )
 
GetLinearVelocity
 
Obtiene los componentes x, y de la fuerza ejercida, en pixeles por segundo.
 
local vx, vy = object:getLinearVelocity()
print( "Linear X velocity = " .. vx )
print( "Linear Y velocity = " .. vy )
 
 
applyForce
 
Se aplica una fuerza con componentes x, y en punto seleccionado relacionado con la pantalla.
Por ejemplo, si se aplica una fuerza, justo en el centro de un objeto, este se desplazará en línea recta
 
object:applyForce( 500, 2000, object.x, object.y )
 
  
 
  


















lunes, 19 de enero de 2015

Eventos e interacción

Tap / Touch / Multitouch

Tap

Los eventos Tap son los más comúnes y básicos en la interración del usuario con la aplicación. Un tap ocurre cuando el usuario toca la pantalla y la suelta inmediatamente sin mover el dedo de la pantalla. 

local caja = display.newImage("caja.jpg")
caja.width=100; caja.height=100;
caja.x = 100; caja.y = 100


function toque(event)
    transition.to(caja, { x=200 })
end

caja:addEventListener( "tap", toque )


Las propiedades del "event" en un tap son:
  • event.target — Hace referencia al objeto que fue "tappeado".
  • event.name —nombre del evento tap, será "tap".
  • event.numTaps — número de taps que se dieron. Para ser tomados en cuenta tienen que darse en menos de un segundo. Con el uso de esta propiedad podemos usar doble taps. (if event.numTaps = = 2)
  • event.x / event.y — coordenadas x & y de la posición donde el dedo hiz tap.
A diferencia de los eventos touch, los eventos tap no tienen una propiedad pahse, ya que el tap incluye desde que se toca hasta que se suelta, no necesitas de fases, ya que no hace diferencia.


Touch

Los eventos Touch permiten una mayor interacción del usuario con la pantalla. Con este evento se puede detectar cuando el usuario acaba de tocar la pantalla y cuando la suelta. Además puedes seguir el rastro del dedo en la pantalla. Estas son las cuatro fases (phases):
  • "began" — Incida que un touch ha iniciado en la pantalla.
  • "moved" — Indica que un touch se ha movido por la pantalla.
  • "ended" — Indica que un toch ha concluído (El dedo se separó de la pantalla).
  • "cancelled" — Indica que el sistema ha cancelado el evento touch (no confundirlo con "ended").

------

Ya que vimos la función translate, veamos a detalle de que se trata:
Esta función te permite ejecutar una acción como: mover, rotar, desvanecer, o escalar en un tiempo determinado.

transition.to( target, params )

Los parametros generales son:

time Especifíca la duración de la transisión en milisegundos.
delay Especifíca el retraso en segundos, antes que la transición comience. Default es 0.
delta Si es true, especifíca que se aplica a partir de su estado actual.
iterations Número de iteraciones que tendrá la transición. 0 o -1 hacen que la transición itere para siempre.


transition Specifies the easing function used for the transition. See Easing Functions.


Otros parámetros específicos:


move x, y Mueve el objeto a las coordenadas que se especifícan.
rotate rotation Rota el objeto según el ángulo de rotación dado.
fade alpha Desvanece el objeto de su alpha actual a la que se especifíca.
scale xScale, yScale Escala el objeto al especifícado.
resize width, height Cambia su tamaño al que se especifíca.


Ejemplo:

transition.to( myObject, { time=2000, rotation=45, yScale=2, alpha=0.5 } ) 
 

 
Eventos en transiciones:

onStart Función que se llama cuando inicia la transición.
onComplete Función que se llama cuando se completa la transición.
onPause Función que se llama cuando se pausa la transición.
onResume Función que se llama cuando una transición pausada, continúa.
onCancel Función que se llama cuando una transición activa, es cancelada.
onRepeat Función que se llama cuando una transición termina una iteración.

miércoles, 14 de enero de 2015

Display Objects

Dentro de Corona vas a utilizar: Propiedades, Funciones. Algunas ya están creadas para ser utilizadas, y otras tu las puedes crear. Aquí tienes las más utilizadas, puedes encontrar la lista completa aquí:

http://docs.coronalabs.com/api/library/display/index.html

Nota: Las propiedades se acceden mediante un punto (".") . Las funciones mediante dos puntos (":")
[objeto].[propiedad]
[objeto]:[funcion]


Propiedades


display.contentWidth: Obtiene el ancho de la pantalla del dispositivo en el que estás desarrollando.

display.contentHeight: Obtiene el alto de la pantalla del dispositivo en el que estás desarrollando.

Propiedades para crear gráficos:


Display Group display.newGroup()
Standard Image display.newImage()
Dynamically-Selected Image display.newImageRect()
Text display.newText()
Animated Sprite display.newSprite()
Rectangle display.newRect()
Circle display.newCircle()
Rounded Rectangle display.newRoundedRect()
Line display.newLine()
Polygon display.newPolygon()
Embossed Text display.newEmbossedText()
Container display.newContainer()
Snapshot display.newSnapshot()
Particle Emitter display.newEmitter()

Ejercicio: Utilizar propiedades para crear textos, gráficos e imágenes.

Para crear un gráfico debes asignarlo a una variable local (Así vas a crear los objetos en Corona). Ejemplo:
local mi_grafico = display.newImage("unafoto.png")



Texto

display.newText("Hello World!", 0, 0, native.systemFont, 16);

"Hello World!" -> Texto que vas a mostrar
0 , 0 -> Coordenadas x & y, respectivamente
native.systemFont -> Fuente a utilizar
16 -> Tamaño de fuente


Imagen

diplay.newImage("mi_imagen.jpg",50,50);

"mi_imagen.jpg" -> Ruta de la imagen
50,50 -> Coordenadas x & y, respectivamente

Imagen en Rectángulo

display.newImageRect("mi_imagen.png",300,100);
"mi_imagen.jpg" -> Ruta de la imagen
300,100 -> Ancho y alto del rectángulo respectivamente

Nota: Para mover elementos como la imagen en rectángulo y la gran mayoría de elementos. Debes agregar la coordenada al objeto en 'x' y 'y' . Por ejemplo si quiero colocar el objeto img en las coordenadas (200,350) se hace de la siguiente forma:

local img = display.newImageRect("mi_imagen.png",300,100)
img.x = 200
img.y = 350

Rectángulo

display.newRect( x, y, width, height )
 
 
Círculo
 
display.newCircle( xCenter, yCenter, radius ) 

xCenter, yCenter -> Coordenadas del centro del círculo
 
 
Rectángulo con bordes redondeados
 
display.newRoundedRect( x, y, width, height, cornerRadius ) 

Líneas

display.newLine( x1, y1, x2, y2)
 
x1,y1 -> Coordenada de inicio
x2,y2 -> Coordenada final
 
 




Algunas propiedades y funciones útiles
 
Anclas
 
Las anclas de un objeto controlan la aplicación de geometría a estos.
Se pueden específica con: objeto.anchorX y objeto.anchorY.
Por default en todos los objetos son: (0.5,0.5)
 
 
 

 
----- 
 
 

mi_imagen.alpha = 0.5 [Para hacer transparencias]
mi_circulo:setFillColor(r,g,b) [r,g,b son números decimales entre 0 a 1]

object:setFillColor( gray )
object:setFillColor( gray, alpha )
object:setFillColor( red, green, blue )
object:setFillColor( red, green, blue, alpha )
 
 

mi_rectangulo:setStrokeColor( 1, 0 ,0 ) [r,g,b son números decimales entre 0 a 1]
mi_rectangulo.strokeWidth = 5 [Grosor de los border, utiliza sólo enteros]
 
object:setStrokeColor( red, green, blue, alpha ) 

sábado, 10 de enero de 2015

Otros objetos y grupos

Sobre la barra de estadodisplay.setStatusBar(display.HiddenStatusBar);
display.setStatusBar(display.DefaultStatusBar);
display.setStatusBar(display.DarkStatusBar);
display.setStatusBar(display.TranslucentStatusBar);

Grupos

Los grupos sirven para organizar objetos y guardar relaciones entre ellos.

Existen dos maneras de utilizarlos: Inline y Directos

Inline
local myGroup = display.newGroup()

--create object in 'myGroup'
local myImage = display.newImage( myGroup, "image.png" )

Directo
local myGroup = display.newGroup()

--create object on the stage (default)
local myImage = display.newImage( "image.png" )

--insert object into 'myGroup'
myGroup:insert( myImage ) 


Orden de los objetos

En orden del código, los primeros objetos en aparecerán detrás en la pantalla del dispositivo.

Nombres de varialbles

Los nombres pueden contener letras y números, no símbolos, tildes ni espacios.

Eliminar objetos

Para eliminar objetos de un grupo:

Directo

display.remove( myObject )

--OR

myObject:removeSelf()

--OR

myGroup:remove( myObject )  --group array index also valid

Sin embargo ninguno de estos métodos libera la memoria. Para evitar mal uso de memoria, debes eliminar toda referencia de la variable al objeto, esto se logra estableciendo la referencia como nil.

display.remove ( myObject )
myObject = nil  --set reference to nil!

--OR

myObject:removeSelf()
myObject = nil  --set reference to nil!

--OR

myGroup:remove( myObject )
myObject = nil  --set reference to nil!

En grupo

display.remove( myGroup )
myGroup = nil

--OR

myGroup:removeSelf()
myGroup = nil
 

Comentarios 

Para comentar una línea sólo debes agregar al principio doble guión:

--Esto es un comentario
--local h = display.newImage("mico.png");

Y para bloques de comentarios:

--[[
Este es un comentario
dividido
en varias líneas.
]]

Configuración

Todos los proyectos de Corona SDK contiene un archivo config.lua con toda la configuración respecto a la aplicación:

width | height : Ancho y alto de la resolución principal.

scale: Determina la escala y ajuste a las diferentes resoluciones de los dispositivos. Existen 4 diferentes valores que puede llevar este atributo:

  • "letterbox" : El área de contenido se adapta a la pantalla de manera proporcional. Esto puede ocasionar líneas negras a los costados.
  • "zoomEven": El área de contenido se adapta a la pantalla de manera proporcional. Para evitar las líneas negras, el área de contenido excede los border para llenar la pantalla.
  • "adaptative": Se adapta a las resoluciones. No recomendable para principiantes.
  • "zoomStretch": Se adapta a las pantallas de los dispositivos estirando o comprimiendo elementos. No recomendable.

xAlign | yAlign: Por default el contenido esta centrado en la pantalla. Sin embargo, si requieres alinear el contenido respecto a algún lado puedes cambiarlo utilizando:
  • xAlign: "left", "center", "right"
  • yAlign: "top","center","bottom"

Selección dinámica de imagen

Si deseas hacer que tu aplicación se vea bien en dispositivos Retina, Corona lo hace por ti. Sólo debes crear diferentes versiones de acuerdo a la resolución que necesitas e indicarle en el archivo config.lua incluyendo: imageSuffix

Dentro de este atributo debes colocar dentro de corchetes el sufijo que elijas, seleccionar la proporción a la que es equivalente y todas las imágenes que sean de alta resolución agregarles ese sufijo. Ejemplo:

imageSuffix =
{
    ["-small"] = 0.375,
    ["@2x"] = 1.5
}

Frame Rate(fps)

Por default son 30 frames por segundo, pero puedes establecerlo en 60. Sólo son válidos 30 y 60. Cualquier otro será ignorado.