Vistas de página en total

Mostrando entradas con la etiqueta programación móvil. Mostrar todas las entradas
Mostrando entradas con la etiqueta programación móvil. Mostrar todas las entradas

lunes, 19 de septiembre de 2016

Mi solución para juegos y aplicaciones

En las últimas entradas hemos estado viendo cómo resolver el problema de los distintos tipos de pantalla en los que nuestra aplicación se puede ejecutar. Hemos visto que Corona nos ofrece una pantalla virtual donde situamos nuestros objetos (con un tamaño definido por nosotros) y después Corona se encarga de escalar ese contenido a la pantalla real del dispositivo. Hemos visto que hay varios modos de escalado. Y además, sabemos que el API de Corona, en el objeto display tiene algunas constantes muy útiles. Con todo esto, y con la alineación de la pantalla virtual (que vamos a ver ahora mismo), es posible resolver casi cualquier problema. Nos centraremos en el modo "letterbox" que es el que yo utilizo habitualmente.
Empecemos con la alineación.

Alineación de la pantalla virtual

Como vimos, en modo "letterbox", el escalado puede producir bandas laterales (o superior/inferior) si las proporciones de la pantalla virtual no coinciden con las de la pantalla real. En estos casos Corona por defecto centra la pantalla virtual en la pantalla física, es decir, deja el mismo espacio arriba y abajo, o bien el mismo espacio a izquierda y derecha.
Sin embargo, este comportamiento por defecto se puede cambiar. Para ello, recurrimos al fichero config.lua:

application = {
    content = {
        width = 320,
        height = 480, 
        scale = "letterBox",
        xAlign = "center",
        yAlign = "center",
    },
}

Hemos añadido dos nuevos miembros a la conocida tabla application.content
xAlign indica la alineación horizontal
yAlign indica la alineación vertical
Con estos dos nuevos parámetros podemos cambiar la forma en que Corona sitúa la pantalla virtual dentro de la pantalla física.
El parámetro xAlign puede tomar los siguientes valores:
  • "left"
  • "center"
  • "right"
Y el parámetro yAlign puede tomar los siguientes valores:
  • "top"
  • "center"
  • "bottom"
De esta forma podemos controlar cómo se encaja la pantalla virtual en la física. En unos momento vamos a ver la utilidad de estos dos parámetros.

Solución para los juegos

Para los juegos, yo utilizo siempre el modo letterbox, para no perder información y para no deformar. Como van a aparecer bandas laterales en muchos casos, también utilizo xAlign = "center", yAlign="center" de esta forma me aseguro que el juego propiamente dicho aparece centrado en la pantalla.
¿Qué hago con las bandas laterales? Utilizo las constantes:

display.actualContentWidth
display.actualContentHeight

para poner un rectángulo o una imagen en el fondo que encaje bien con el resto del juego. Este rectángulo no aparecerá si las proporciones del dispositivo son iguales que las de la pantalla virtual.
El juego aparecerá escalado en función de la pantalla del dispositivo sin ninguna deformación.
Esta solución es muy sencilla de implementar y funciona en todos los casos.

Solución para las aplicaciones

Paradójicamente, el caso de las aplicaciones es algo más complejo que el de los juegos (aunque dije que el desarrollo de juegos es más difícil que el de aplicaciones).
En este caso, la aplicación tiene que mostrar una serie de elementos (widgets) en la pantalla y no siempre lo mejor es que salga centrada en pantalla. Por ejemplo, una aplicación que tenga una barra superior con algunas opciones de menú tiene que salir siempre arriba del todo, no vale que salga un poco más abajo por causa de las bandas del letterbox. Igualmente, si tenemos pestañas abajo, éstas tiene que salir abajo del todo.
Mi solución en este caso, es usar de nuevo "letterbox" como modo de escalado (no quiero deformaciones ni pérdida de información), pero en este caso alineo la pantalla virtual a la parte superior. Mi fichero config.lua sería algo así como:

application = {
    content = {
        width = 320,
        height = 480, 
        scale = "letterBox",
        xAlign = "center",
        yAlign = "top",
    },
}

De esta forma consigo que el contenido se visualice a partir de la parte superior de la pantalla. El problema entonces es cómo conseguir rellenar el espacio sobrante por abajo. Lo que hago es, utilizando las constantes:

display.actualContentWidth
display.actualContentHeight

puedo situar los elementos inferiores ajustados a la parte inferior de la pantalla (en función de estas constantes). Y el espacio que sobra en el centro, lo utilizo para los elementos centrales.
Como se puede intuir, la parte central no va a tener un tamaño fijo, sino que dependerá de las proporciones del dispositivo físico.
Normalmente la parte central suele ser una lista de elementos con scroll o algo similar, con lo cual, es fácilmente adaptable a un tamaño variable.
Ya veremos ejemplos de todo esto en futuras entradas.



jueves, 1 de septiembre de 2016

Lua - Parte 5

Estructuras de control

Lua, como casi todos los lenguajes de programación, tiene una serie de estructuras de control que permiten iterar y hacer comprobaciones dentro del código:
  • if
  • for
  • while
  • repeat

IF

La sentencia if permite chequear una o más condiciones:

    if condición1 then
        sentencias1
    elseif condición2 then
        sentencias2
    elseif condición3 then
        sentencias3
    else
        sentencias4
    end

Las condiciones son expresiones cuyo resultado es un boolean, o sea, true o false. Si una expresión es nil se considera false, cualquier otro valor, se considera true. Ejemplos de condiciones:

    3 > 5    -- false
    5 > 1    -- true
    a        -- variable no existente -> nil -> false
    6        -- true
    0        -- true
    "hola"   -- true
    ""       -- true
    nil      -- false

Las partes elseif y else de la sentencia if son opcionales.

Lua no tiene la sentencia switch típica de otros lenguajes de programación, pero se puede sustituir muy fácilmente con la sentencia if.

FOR

Forma general de la sentencia for:

    for variable = start, end, step do
        sentencias
    end

La "variable" es el índice que va cambiando y que se puede utilizar dentro de las sentencias del bucle for. "start" es el valor de inicio y "end" es el valor final (incluidos ambos). "step" es opcional y permite pasar desde start hasta en end en pasos distintos de uno.

Ejemplo:

    for i = 3, 10 do
        print(i)
    end

Otro ejemplo, contando hacia atrás:

    for i = 100, 50, -1 do
        print(i)
    end

WHILE

La sentencia while permite ejecutar un bloque de sentencias mientras se cumpla una condición:

    while condición do
        sentencias
    end

REPEAT

La sentencia repeat permite ejecutar un bloque de sentencias mientras hasta que se cumpla una condición:

    repeat
        sentencias
    until condición

El bloque repeat se ejecuta siempre al menos una vez.

BREAK

La sentencia break permite salirse un bucle. Por ejemplo:

    for i = 100, 50, -1 do
        print(i)
        if i > 80 then
            break
        end
    end

Hay que tener en cuenta que Lua no tiene la sentencia continue, típica en otros lenguajes de programación para ir al principio del bucle.

Lua - Parte 4

Funciones

Todos hemos usado funciones de una u otra forma en muchos lenguajes de programación. En Lua también tenemos funciones y la idea es muy similar a la de los demás lenguajes. Sin embargo, hay algunos matices que es interesante considerar.

En Lua una función se puede definir de varias formas. La más sencilla y quizás la más utilizada es:

    function suma(a, b)
        return a + b
    end

De esta forma, estamos definiendo una función denominada "suma" de ámbito global (o sea, accesible desde cualquier sitio), que acepta dos argumentos, a y b, suma los dos argumentos y retorna el resultado de la suma. Creo que todo esto está bastante claro para todos aquellos que alguna vez han programado en algún lenguaje, no parece haber nada nuevo. Pero quiero destacar el hecho de que la función tiene ámbito global, es decir, que podemos invocarla desde cualquier punto de nuestro programa. Esto ocurre porque no hemos utilizado la palabra clave "local". Si hubiéramos querido definir una función con ámbito local:

    local function suma(a, b)
        return a + b
    end

En este caso, sólo podríamos invocarla desde el módulo en el que estamos (ya hablaremos de módulos en una entrada posterior, de momento adelanto que un módulo es un fichero Lua con funciones y otros elementos de código).

Otro tema interesante a destacar es que los parámetros, a y b, no declaran un tipo. Es decir, podemos invocar a la función "suma" con dos valores o varialbes cualquiera, de cualquier tipo. Lo normal será invocarla con dos números, pero nada nos impide utilizar otros tipos (eso sí, probablemente tendremos un error de ejecución, por ejemplo al invocar la función "suma" con dos strings).

Destacar también que la función no declara el tipo retornado. Retornará un valor numérico porque la sentencia "return" devuelve la suma de sus dos parámetros, pero realmente el lenguaje no obliga a retornar ningún tipo concreto. De hecho (reconozco que esto es algo enrevesado), la función podría retornar en un caso un número y en otros casos un string.

Por último no quiero olvidar que una función podría no retornar ningún valor. Para ello podemos utilizar la palabra clave "return" simplemente o bien llegar al final de la función sin retornar ningún valor.

Funciones dentro de una tabla

Como vimos al hablar de las tablas, una función puede ser un miembro de una tabla:

    local table = {
        add = suma,
    }

O bien:

    local table = {
        add = function(a, b) return a + b end,
    }

Retorno de múltiples resultados

Una función puede retornar más de un resultado:

    function statistics()
        return a, b, c
    end

Estos múltiples resultados se recogen de la siguiente forma:

    local x, y, z = statistics()

Número variable de argumentos

Una función no sólo puede retornar múltiples resultados, si no que también puede aceptar un número variable de argumentos:

    function guarda( ... )
        print( arg[1], arg[2], arg[3] )
    end

Los argumentos se recogen en la lista predefinida arg. El operador # nos permite conocer el número de argumentos que se han pasado a la función:

    function guarda( ... )
        for i = 1, #arg do   -- más adelante veremos los bucles
            print( arg[i] )
        end
    end

También podemos tener un número mínimo de argumentos a una función y los demás variables:

    function guarda( a, b, ... )
        print( a, b, arg[1], arg[2], arg[3] )
    end

Lo importante es que los tres puntos (argumentos variables) siempre tienen que ir al final.

Más sobre tablas y funciones

Ya he dicho varias veces que una función puede ser un miembro de una tabla. Esto es muy importante y se utiliza mucho en Lua. Una de las ventajas de esta construcción es que de esta forma no se crean funciones globales. Podríamos resolver también este problema con la palabra "local", pero en este caso el acceso a la función sería únicamente local, sin embargo, las funciones dentro de una tabla son accesibles desde cualquier punto del programa, pero de una forma que podría ser similar a los namespaces o packages de otros lenguajes (como C# o Java). Por ejemplo:

    myobject = {
        add = function(a, b) return a + b end,
    }

Para invocar a esta función haríamos:

    myobject.add(3, 5)

De esta forma estamos añadiendo un "namespace" a la función. Y no sobreescribiría a esta otra función que tiene el mismo nombre, pero está en otro "namespace":

    utils = {
        add = function(a, b) return a .. b end,
    }

Otra forma equivalente de añadir la función a la tabla sería:

    myobject = { }
    function myobject.add(a, b) return a + b end

Tablas, funciones y objetos

Lo que hemos visto sobre tablas y funciones hará pensar a algún lector en objetos y en programación orientada a objetos. Sin embargo, la forma que hemos visto de meter una función en una tabla no es realmente un objeto. El motivo principal es que la función no es "consciente" de en qué objeto (tabla) está, de hecho, no tiene acceso a otros datos de la tabla. Veámoslo con un ejemplo:

    myobject = {
        dato = 3,
    }
    function myobject.calcula(a) return dato + a end

En este caso tenemos una tabla con dos miembros: un número "dato" y una función "calcula".
Si intentamos invocar a la función "calcula":

    myobject.calcula(5)

Obtendremos un error similar al siguiente:

    attempt to perform arithmetic on global 'dato' (a nil value)

Esto se debe a que no existe una variable global llamada "dato" y por tanto su valor es nil, lo cual provoca un error al intentar sumarlo con el argumento "a". La variable "dato" de la tabla no es accesible a la función.

Podríamos resolverlo de la siguiente forma:

    myobject = {
        dato = 3,
    }
    function myobject.calcula(a) return myobject.dato + a end

Pero tenemos que reconocer que no es una forma muy elegante de acceder a la variable dato (ya que dependemos del nombre que demos a la tabla, en este caso, "myobject").

Otra solución, tampoco muy elegante por cierto, sería pasar como argumento a la función la propia tabla (reconozco que esto es todavía peor):

    myobject = {
        dato = 3,
    }
    function myobject.calcula(this, a) return this.dato + a end

    myobject.calcula(myobject, 5)

Aunque esta solución es incluso más horrible que la anterior, me permite introducir la solución que propone Lua para estos casos.

    myobject = {
        dato = 3,
    }
    function myobject:calcula(a) return self.dato + a end

Y para invocar a esta función:

    myobject:calcula(6)

Es una sintaxis un poco extraña, pero fácil de comprender. En primer lugar, para añadir la función a la tabla utilizamos dos puntos, en lugar de un punto como hemos hecho hasta ahora. También utilizamos dos puntos para invocar a la función. Los dos puntos indican a Lua que tenemos que necesitamos un parámetro intrínseco, denominado "self", y que es la propia tabla donde está la función. Este parámetro lo pone Lua (sin que hagamos nada y de forma similar al parámetro arg que Lua introduce en las funciones con número variable de argumentos).

En una entrada posterior trataré el tema de la programación orientada a objetos en Lua, donde veremos cómo podemos tener objetos reales en nuestros programas, a pesar de que Lua no es realmente un lenguaje orientado a objetos. Tendremos que hacer unas construcciones especiales, siguiendo un determinado patrón para conseguirlo.

Closure de una función

El closure de una función es un término que suele ser difícil de comprender de partida, salvo que se haya utilizado previamente en otros lenguajes como javascript.
En pocas palabras, el closure de una función son las variables y funciones que existen en su scope. Cuando una función está dentro de otra función, la función interna tiene acceso a todas las variables de la función externa. A esto se le conoce como lexical scope.
Estos dos conceptos que parecen a primera vista muy sencillos, se complican un poco, como ahora veremos.

    local function external(paramExt)        local varExt = paramExt + 1        local internal = function(paramInt)            local varInt = paramInt + varExt + paramExt        end        return internal    end

    local f = external(5)
    print( f(4) )

Este es un ejemplo bastante complejo, si no se tiene costumbre de manejar funciones como objetos. Voy a tratar de explicarlo despacio.
En primer lugar, tenemos una función llamada external que devuelve otra función llamada internal. Hasta aquí no hay nada extraño. Sin embargo, la función internal utiliza variables e incluso parámetros (varExt y paramExt) que pertenecen a la función external. Y nos podemos preguntar: ¿Cuánto valen esa variable y ese parámetro cuando mucho más abajo llamamos a la función f? Pues bien, esa variable y ese parámetro tienen los valores que tenían cuando llamamos a la función external. Es decir, paramExt vale 5 y varExt vale 6. Por tanto, la función f, que devuelve la suma de esos dos objetos más el parámetro paramInt, devuelve 5 + 6 + 4, o sea, 15.
La variable varExt y el parámetro paramExt son el closure de la función internal, y cuando se le invoque más adelante, tendrá acceso a esos valores de su closure. Cada vez que invocamos a la función external y recibimos una función como resultado, esa función tendrá asociado el closure correspondiente.



miércoles, 24 de agosto de 2016

Lua - Parte 2

Variables, valores y tipos

Lua es un lenguaje tipado dinámicamente. Para los que saben javascript, esto es sencillo de entender. ¿Qué significa que un lenguaje es tipado dinámicamente? Es muy sencillo. En lenguajes como Java, cuando se declara una variable hay que declarar su tipo, int, float, String o lo que sea, y esa variable sólo podrá almacenar valores del tipo declarado (o bien de una clase derivada).
En lenguajes tipados dinámicamente, como Lua, una variable puede contener un valor de cualquier tipo, o dicho más exactamente, puede apuntar a valores de cualquier tipo. Además, es posible que una variable que apunte a un valor de un tipo, más tarde apunte a un valor de otro tipo.
Por ejemplo:

    contador = 14

Estamos declarando una variable que se llama contador y que apunta a un valor de tipo numérico que vale 14. Se observa que no hemos declarado ningún tipo para la variable.
Más adelante podríamos hacer:

    contador = "43"

Ahora, la misma variable contador apunta a otro valor, esta vez de tipo string.

Tipos de datos en Lua:

  • nil - indica que la variable no ha sido inicializada (también se puede asignar nil a una variable explícitamente).
  • boolean - puede ser true o false.
  • number - cualquier número, entero o real. Lua utiliza punto flotante de doble precisión para todos los números.
  • string - cadena de caracteres.
  • function - un bloque de código que se puede invocar.
  • table - es el tipo más complejo que tiene Lua. Más adelante veremos espcíficamente las tablas.
Una variable se puede declarar en cualquier lugar simplemente asignándole un valor:

    contador = 14

Cuando se declara una variable de esta forma, tiene un ámbito global y existirá durante toda la ejecución del programa. Podremos acceder a esta variable desde cualquier punto del programa. Si queremos que el recolector de basura elimine la memoria ocupada por la variable, tenemos que asignarle nil:

    contador = nil

Se dice que el ámbito o scope de esta variable es global. Pero también existe un ámbito de bloque, por ejemplo dentro de una función:

    function calculate()
        local total = 7
    end

Al poner local, la variable total tiene ámbito de bloque: sólo existe dentro de la función, y desaparecerá cuando retorne la función. El recolector de basura eliminará la memoria ocupada por la variable cuando retorne la función (incluso aunque no le asignemos nil).
Se recomienda siempre utilizar local para las variables, excepto cuando deseemos que una variable tenga ámbito global. Cuando dentro del programa se utiliza una variable (sin usar local), Lua busca en el ámbito local para ver si existe, si no existe, busca en el bloque superior y así sucesivamente hasta llegar al ámbito global. Si no existiera, la variable se crea. El rendimiento será muy superior si declaramos todas las variables local, para evitar la cadena de búsquedas de Lua. Además, todos sabemos que las variables globales no son buenas, porque es muy fácil cometer un error y sobreescribirlas en algún lugar del programa sin darnos cuenta.
También hay que tener en cuenta que cuando declaramos una variable local en un bloque, esta variable se utiliza en el bloque aunque exista otra con el mismo nombre en un bloque externo o bien en el ámbito global. Por ejemplo:

    contador = 3
    function incrementar()
        local contador = contador + 1
    end
    -- aquí el valor de contador es 3

Hay una forma de acceder directamente a una variable global, aunque tengamos variables locales con el mismo nombre y además, evitando la cadena de búsqueda de Lua:

    contador = 3
    function incrementar()
        local contador = contador + 1
        _G.contador = _G.contador + 1
    end
    -- aquí el valor de contador es 4

Lua almacena todas las variables globales en una tabla llamada _G, por tanto podemos acceder a cualquier variable global a través de esta table.

Las variables locales de bloque no sólo se pueden utilizar dentro de una función, también se pueden utilizar en otros bloques como if o bucles.

En Lua se pueden realizar asignaciones múltiples:

    local x, y = 3, 4

Esto permite realizar hacer un swap de dos variables de una forma muy sencilla:

    x, y = y, x

Expresiones y operadores

Los operadores y expresiones en Lua son muy similares a los de otros lenguajes de programación.
Operadores matemáticos:
  • + suma
  • - resta o negativo
  • * multiplicación
  • / división
  • % módulo
  • ^ exponenciación
Operadores de comparación (retornan true o false):
  • == igualdad (si los tipos no son iguales, retorna false)
  • ~= desigualdad
  • < menor que
  • > mayor que
  • <= menor o igual que
  • >= mayor o igual que
Operadores lógicos:
  • and
  • or
  • not
Los operadores lógicos consideran que false y nil son false, y todos los demás valores son true.
Los operadores and y or hacen una evaluación con corto-circuito, es decir, si el primer valor de un and es false, no evalúa el segundo, y si el primer valor de un or es true, no evalúa el segundo.

Operador de concatenación:
  • .. concatenación de strings y números
Operador longitud:
  • # longitud de un array (veremos este operador cuando estudiemos las tablas, porque un array es una tabla en Lua)











martes, 2 de agosto de 2016

Instalación de Corona

Existen dos versiones del simulador, una para Windows y otra para MacOS. Con la versión para Windows podremos ejecutar nuestro programa en el simulador y podremos generar la versión para Android únicamente (no podremos generar la versión para iOS en Windows debido a restricciones de Apple). Con la versión para MacOS igualmente podremos ejecutar nuestro programa en el simulador y generar la versión para Android, pero además, podremos también generar la versión para iOS. Por lo tanto, si necesitamos generar para iOS tendremos que disponer de un ordenador con MacOS. Vale cualquier modelo, ya que Corona no tiene unos requisitos especiales. También existe la opción de alquilar un Mac en la "nube". Por ejemplo MacinCloud permite alquilar un Mac y trabajar de forma remota en él. Los precios son bastante razonables, como por ejemplo, 1 dólar por hora o 20 dólares al mes, sobre todo si sólo lo necesitamos para generar la versión para iOS (algo que podemos realizar en unos pocos minutos, ya que el desarrollo lo podemos hacer prácticamente en su totalidad en un PC Windows).

También es importante indicar que para generar el APK de Android no necesitamos instalar el SDK de Android, ya que Corona se encarga de generar nuestro APK remotamente (como ya veremos). Esto nos ahorra muchas complicaciones y seremos capaces de hacer nuestro primer programa para Android en pocos minutos. Sin embargo, para generar para iOS es necesario instalar XCode, el IDE de Apple (el cual es gratuito).

Antes de instalar Corona, es necesario instalar un editor de texto para editar los ficheros Lua. En principio vale cualquier editor, por ejemplo, Notepad++ en el caso de Windows, y TextEdit en el caso de Mac. Sin embargo, yo recomiendo Sublime Text, un editor muy potente, multiplataforma, que además tiene un plugin especial para Corona SDK. Con este plugin tendremos opciones de autocompletado, no sólo para Lua, sino también para el API de Corona. Además, podremos lanzar y depurar nuestros programas desde el propio editor. No es un editor gratuito, pero realmente puede merecer la pena. He leído en algún sitio que la versión de evaluación de Sublime la renuevan indefinidamente si se va solicitando cada vez que caduca, pero esto sólo es un rumor.

Lo primero que tenemos que hacer para trabajar con Corona es instalar el simulador.

Instalación de Corona en Windows

Entramos en la web de Corona: https://coronalabs.com/, introducimos nuestro mail (1), para que ellos sepan quién se ha descargado Corona y pulsamos en Download Free SDK (2).


Si no nos hemos registrado antes, es el momento. Para registrarnos simplemente tendremos que dar una cuenta de mail y una clave.

Inmediatamente entraremos en la página de descargas. Seleccionaremos la versión para Windows (1) y pulsando el botón Download (2) se descargará el fichero .msi instalador para Windows. 

En la página de descargas también tenemos disponibles para descargar las versiones que ellos llaman Daily builds. Son versiones últimas de lo que están desarrollando ahora mismo. Normalmente no es necesario utilizar estas versiones, y vale con la versión oficial. Pero en algunas ocasiones añaden alguna funcionalidad muy importante o corrigen algún error que para nosotros es importante, y entonces sí merece la pena utilizar la última Daily build y no esperar a que saquen la siguiente versión oficial (que suele ser cada varios meses).

El siguiente paso es instalar Corona en nuestro PC. Para ello, damos doble click sobre el fichero .msi que hemos descargado. Daremos permiso para ejecutar el instalador:


Seguiremos las instrucciones del instalador paso a paso, ya que no hay opciones importantes, salvo el directorio de instalación, que dejaremos el directorio por defecto.

Y ya lo tenemos. Es muy sencillo instalar Corona SDK para Windows, como hemos visto. En la siguiente entrada del blog realizaremos un sencillo ejemplo para comprobar que todo ha ido bien.

Instalación de Corona en MacOS

Entramos en la web de Corona: https://coronalabs.com/, introducimos nuestro mail (1), para que ellos sepan quién se ha descargado Corona y pulsamos en Download Free SDK (2).


Si no nos hemos registrado antes, es el momento. Para registrarnos simplemente tendremos que dar una cuenta de mail y una clave.

Inmediatamente entraremos en la página de descargas. Seleccionaremos la versión para Mac (1) y pulsando el botón Download (2) se descargará el fichero .dmg instalador para MacOS. 



En la página de descargas también tenemos disponibles para descargar las versiones que ellos llaman Daily builds. Son versiones últimas de lo que están desarrollando ahora mismo. Normalmente no es necesario utilizar estas versiones, y vale con la versión oficial. Pero en algunas ocasiones añaden alguna funcionalidad muy importante o corrigen algún error que para nosotros es importante, y entonces sí merece la pena utilizar la última Daily build y no esperar a que saquen la siguiente versión oficial (que suele ser cada varios meses).

El siguiente paso es instalar Corona en nuestro Mac. Para ello, damos doble click sobre el fichero .dmg que hemos descargado y aceptamos la licencia:


Arrastramos Corona SDK a la carpeta de Aplicaciones:


Y ya lo tenemos. Es muy sencillo instalar Corona SDK para MacOS, como hemos visto. En la siguiente entrada del blog realizaremos un sencillo ejemplo para comprobar que todo ha ido bien.

jueves, 14 de julio de 2016

Quiero hacer apps y juegos para móviles

Este blog va a estar dedicado a la programación de aplicaciones y juegos para móviles utilizando Corona SDK.

Desde que aparecieron los primeros smartphones, mucha gente ha tenido ideas para desarrollar un juego o una aplicación para estos dispositivos. Pero hay varios problemas a los que hay que enfrentarse, sobre todo si no se tiene mucha experiencia en este mundo del desarrollo para móviles.

El primer problema al que nos enfrentamos es que no existe una única plataforma o sistema operativo para móviles. Nos encontramos con al menos, dos grandes plataformas: iOS y Android. También podríamos incluir Windows Phone, pero a día de hoy, no está tan expandido como las otras dos.

Las aplicaciones para Android se desarrollan en Java y se utiliza Android Studio como IDE. Las aplicaciones para iOS se desarrollan en Swift (o bien en el antiguo Objective-C) y se utiliza XCode como IDE. Ambos entornos son completamente diferentes, tienen APIs muy distintos y requieren de una especialización importante para desarrollar aplicaciones o juegos de una complejidad media.

Podríamos pensar que lo mejor es centrarse en una de las plataformas, Android o iOS, especializarse en ella y desarrollar nuestra idea sólo para esa plataforma. Si con el paso del tiempo, empieza a tener éxito, habría que plantearse desarrollarla de nuevo para la otra plataforma. Esto tiene algunos inconvenientes: Nunca sabemos si nuestra idea va a tener éxito en una plataforma y quizás empecemos por la opción errónea, además, quizás el éxito está asociado al momento actual. Os voy a contar mi experiencia. Hace unos cuatro años, desarrollé un juego para Android (Retro Kong Jungle), tuvo un éxito inicial inesperado para mí. En pocos meses llegó a las 50000 descargas. Entonces me planteé desarrollarla de nuevo para iOS, pero la falta de tiempo para aprender el nuevo entorno y la inexperiencia, hicieron que esto se retrasara hasta 3 años. Cuando por fin me decidí a hacer el desarrollo del juego para iOS, me llevé la gran sorpresa que prácticamente no tiene descargas (Retro Kong Jungle). Conclusión, las cosas hay que hacerlas en su momento, no dejarlas para después. Si cuando desarrollé el juego inicialmente lo hubiera hecho para las dos plataformas, quizás la historia hubiera sido muy distina. Nunca lo sabré.

Una solución por la que optan algunos desarrolladores es la aplicación Web. Se trata desarrollar la aplicación y publicarla en un servidor web, pero haciéndola responsiva, es decir, adaptada a dispositivos móviles. Ésta no es una mala solución para algunas aplicaciones (por supuesto no para todas), y desde luego, no es válida en absoluto para juegos. Creo que este asunto, no merece más explicación.

Por suerte, existen herramientas multiplataforma, las cuales con una única base de código fuente, permiten el despliegue en múltiples plataformas móviles.

Pero hay muchas diferencias entre todas estas plataformas, y cada una tiene sus ventajas e inconvenientes si comparamos con implementar un desarrollo distinto para cada plataforma.

El primer tipo de herramientas está basado en HTML-Javascript-CSS. No se trata de aplicaciones web, si no de herramientas en las que se programa en estos lenguajes y generan una especie de navegador web embebido en la aplicación. A diferencia de la aplicación web de toda la vida, estas aplicaciones no se ejecutan online, si no que se ejecutan localmente. El código javascript que controla la aplicación lleva el flujo de toda la aplicación en el propio móvil, sin necesidad de conectarse a un servidor web para cargar las páginas. El ejemplo más típico de estas herramientas es PhoneGap. La gran ventaja de estas herramientas es que se utilizan lenguajes muy conocidos para los desarrolladores. El problema es que desde javascript no se puede acceder a todos los recursos nativos de cada plataforma, además no es una solución para desarrollar juegos.

Otro tipo de herramientas, como Xamarin, permite desarrollar en un único lenguaje de programación y ofrece unas librerías en cada plataforma de forma que el API sea común. También ofrecen otros APIs específicos de cada plataforma, y por lo tanto, casi siempre habrá que desarrollar un porcentaje, más o menos elevado de la aplicación, específicamente para cada plataforma. La gran ventaja es la utilización de un lenguaje de programación y de APIs comunes. Pero obliga a desarrollar partes de la aplicación para cada plataforma.

Por último, tenemos las herramientas que traducen el código fuente común a cada plataforma. Este es el caso de Corona SDK. En el caso de Corona, no se utilizan widgets nativos para la interfaz de usuario, sino que dibujan en la pantalla utilizando OpenGL. De esta forma, el resultado en cada plataforma es prácticamente igual. Lo cual es una ventaja, pero también se podría considerar un inconveniente, ya que los usuarios de cada plataforma están acostumbrados a utilizar ciertos widgets. Por ejemplo, una aplicación Corona que ponga un botón, tendrá el mismo aspecto tanto en Android como en iOS. La gran ventaja es que, además de utilizar un lenguaje común, se pueden desarrollar todo tipo de aplicaciones multiplataforma rápidamente, así como juegos.

Este blog está dedicado a Corona SDK, e iremos viendo poco a poco sus características. Haremos ejemplos desde lo más sencillo hasta aplicaciones completas. Aprenderemos el lenguaje de programación que utiliza. Y también, veremos algunas herramientas útiles que utilizaremos constantemente en el desarrollo para móviles: editores de texto, bitmaps, vectorial, audio, etc.

Espero que este blog os ayude a empezar en el mundo de la programación móvil de una forma sencilla y sobre todo, divertida. Yo creo que el desarrollo tiene que ser algo divertido. El programador que no se divierte programando, quizás debería reflexionar un poco sobre su trabajo, porque la programación es algo muy divertido, y si además, hacemos videojuegos, mucho más.

Por último, sólo una advertencia. Aunque voy a explicar el lenguaje de programación de Corona SDK, doy por supuesto que tenéis unos conocimientos mínimos de programación. No voy a explicar lo que es un if o un bucle. No hacer falta ser expertos programadores, pero sí hace falta cierta base mínima.