Ahorrando memoria: Texturas en formato PVR

0 comentarios
Uno de los principales problemas en la construcción de aplicaciones y juegos para dispositivos móviles, es la escasez de recursos de que disponen. Entre esos recursos, unos más importantes que otros, se encuentra la memoria. Para hacernos una idea del reto que ésto supone, aquí tenéis algunos datos: un iPad dispone de 256Mb, un iPad2 dispone de 512Mb y un iPad3 dispone de 1Gb.

Excepto el nuevo iPad, estamos hablando de niveles de memoria de portátiles de hace más de 10 años pero con unos requerimientos gráficos y de jugabilidad actuales. Además de esos requerimientos, hay que tener en cuenta que en la memoria total del dispositivo también hay que cargar el sistema operativo y demás, con lo que el espacio total todavía es menor. Y para bien o para mal, un buen producto entra, antetodo, "por la vista", lo cual se traduce en un excelente aspecto gráfico, es decir, una buena gestión de las texturas.

Una textura no es más que una imagen aplicada a un polígono o polígonos, pero ¿cuánto ocupa esa imagen memoria? La respuesta es la siguiente:

ESPACIO EN BYTES = ANCHURAxALTURAxNºBYTESPORPIXEL

Hagamos el siguiente ejercicio con el primer iPad: 256Mb disponibles, menos lo que ocupa el sistema operativo, etc etc, se queda en unos 180Mb reales para aplicaciones. Teniendo en cuenta que el dispositivo ejecuta aplicaciones en background que ocupan memoria, nos damos cuenta de que realmente disponemos de una cantidad de memoria todavía menor. Ahora cargamos una animación a pantalla completa (1024x768). Pensemos en una animación basada en una sucesión de imágenes (pongamos 8) en formato PNG. Como dicen los americanos, "this is the math":

ESPACIO(Mb) = 1024x768x4x8 = 24Mb

24Mb para una simple animación: ¡EXCESIVO! Hemos supuesto 4bytes por pixel porque hemos cargado PNG's en formato RGBA con 1byte por canal(4canales, 4bytes). ¿Cual es entonces la solución? Hay diferentes técnicas a aplicar aquí, pero me quiero centrar en el formato de las imágenes. Los chips gráficos de la mayoría de los dispositivos móviles incluyen la tecnología PowerVR, que permite cargar texturas con un consumo de memoria hasta 16veces menor, ¡16 veces!. Pero claro, siempre hay alguna restricción y alguna que otra pega: la calidad. Convertir imágenes en formato png a pvr tiene un coste, pero en la mayoría de casos es asumible.

Muchas de las herramientas que se utilizan en la construcción de juegos permiten generar nuestras texturas en formato pvr, como TexturePacker. Después de trastear con algunas, yo os recomiendo lo siguiente:
  1. Generar las texturas con Xcode (a través de 'texturetool'). Definitivamente la calidad de las imágenes es mejor que TexturePacker
  2. Si queréis haceros una idea de la calidad que vais a perder, instalaros las tools de PowerVR Tech.

M.

Divertap en la radio

0 comentarios

Esta vez no queremos comentar ningún aspecto técnico de la programación. Sólo decir que estaremos en la radio para hablar de Divertap, RitaLaLagartija y desarrollo de apps.

COMRàdio nos ofrece esta oportunidad de poder hablar de este mundo del desarrollador de apps, con bajo o nulo presupuesto. De la dificultad real de tener éxito en las stores y de cómo está siendo un boom todo el desarrollo de aplicaciones móviles en las empresas.

No os perdáis el jueves 30 de Agosto por la mañana en L'Apartament nuestra participación, ya que estaremos regalando camisetas ¡como ésta!


Después nos podréis comentar cualquier cosa que os haya interesado o que os haya parecido una tontería.

"Bitmap Fonts" aplicadas al lenguaje chino

0 comentarios

Una de las cosas que me ha sorprendido y al principio no acababa de entender, es cómo se aplica el concepto de fuentes "bitmap" al idioma chino.


Para aquellos que no estéis familiarizados con este concepto, una fuente "bitmap" es aquella que nos permite, en un entorno gráfico donde todo son texturas (típicamente un juego), "pintar" una cadena de caracteres. La técnica es conceptualmente sencilla: dispongo de un fichero de definición de la fuente (típicamente "mifuente.fnt") y otro fichero que contiene un atlas con los caracteres a utilizar (típicamente "mifuente.png").



Cuando queremos pintar en pantalla, por ejemplo, "HOLA MUNDO", la forma de proceder es la siguiente: se consulta en "mifuente.fnt" dónde está la "H", se va al atlas "mifuente.png", se elije la zona donde está la "H" y se pinta en pantalla; y así sucesivamente con todas las letras. Conclusión: con 2 ficheros podemos pintar los textos que queramos.


¿Pero qué pasa con el chino? Si alguna vez habéis intentado averiguar cómo funciona el lenguaje chino, habréis visto que todo son símbolos, y que el contexto de lo que quieres decir es lo que marca utilizar uno u otro símbolo. Hay más de 20.000 símbolos en el chino tradicional, y el nivel de aprendizaje del mismo depende del número de símbolos que sepas. Pero entonces... ¿qué pasa con las fuentes "bitmap"? Pues que el concepto deja de ser aplicable. ¿Por qué? Pues porque no podemos incluir en un único atlas todos los símbolos chinos. La imagen ocuparía "infinito", y todos sabemos que en los dispositivos móviles la memoria es muy limitada. ¿Pero entonces cómo lo hago? Bueno, aquí viene el punto que me costaba entender, ya que intentaba aplicar siempre el concepto de base. La respuesta es: incluye en el atlas sólo los símbolos que vayas a utilizar.


¡OJO! Es evidente que no podrás escribir nada que no esté incluido en los símbolos que hayas incrustado en tu atlas, pero por lo menos la memoria de tu dispositivo móvil lo agradecerá.



Aquí os dejo un par de enlaces de programas que podéis utilizar para generar vuestras fuentes "bitmap" (personalmente os recomiendo el primero)
  1. bmglyph
  2. glyphdesigner

M.

Entendiendo el diseño gráfico para juegos 2D Multidispositivo

2 comentarios

Uno de los principales quebraderos de cabeza en la creación de un juego 2D "mobile", es la decisión de si lo quieres hacer multi-dispositivo. Para aquellos que no sepáis de qué hablo, me refiero a programar el juego una única vez y que funcione en los diferentes tipos de teléfonos móviles y tablets existentes.


Dos de las cosas a tener en cuenta en esta decisión son:

  1. Necesito una tecnología/framework que me permita generar mi código para las diferentes plataformas (iOS, Android, etc)
  2. El diseño gráfico y la programación tiene que estar preparado para todas las resoluciones
En este post me quiero centrar en el segundo punto, ya que es una cosa que parece fácil pero que es un todo un mundo. Y digo todo un mundo, porque personalmente nunca he sabido concretar con los diseñadores cómo tienen que hacer sus gráficos para conseguir la ansiada "caja de pandora", sin que tu vida como programador se convierta en un continuo: if (iphone) else if (ipad) else if (nexus) .... Afortunadamente ¡eso se ha acabado!


A día de hoy, son varias cosas las que hay que tener en cuenta para llegar a buen puerto:

  1. Como diseñador, diseña las pantallas a máxima resolución y luego genera las imágenes para esa resolución
  2. Como programador, programa las pantallas pensando un dispositivo concreto, en la resolución de ese dispositivo, y deja que las herramientas hagan el resto
Tengo que aclarar que cuando hablo de resolución como diseñador, hablo en píxeles, y cuando lo hago como programador, hablo en puntos. En la mayoría de dispositivos un píxel es un punto, pero en los iphone4 e ipadretina no. En estos últimos, por cada punto hay 2 y 4 píxeles respectivamente.


DISEÑO A MÁXIMA RESOLUCIÓN
Puesto que existen diferentes relaciones de aspecto (ancho de pantalla dividido por alto de pantalla) y diferentes tamaños de pantalla (smartphone o tablet) necesitamos un diseño que cubra todo eso. A día de hoy, una resolución de 1536x2384 cubre todos los dispositivos (en modo 'portrait'). Pero no te engañes, no todo el área de ese tamaño es zona "jugable", ya que dependerá del dispositivo. Por ejemplo, en un iphone, tan sólo será jugable un área de 1280x1920. Entonces ¿qué pasa con el resto de espacio de mi photoshop? El resto de espacio es para las zonas muertas que cubrirán los diferentes tamaños de pantalla.
Una vez tengas tu diseño, exporta las imágenes en esa resolución y no curres más de la cuenta... Las herramientas del programador le permitirán generar las típicas resoluciones que existen en la actualidad (actualmente con 3 es suficiente): ipadretina (ipadhd), ipad/iphone4 (hd), iphone (normal).

PROGRAMACIÓN A MÍNIMA RESOLUCIÓN
Como programador, lo primero a hacer es generar las imágenes en esas 3 resoluciones (ipadhd,hd,normal, con herramientas como SpriteHelper). Una vez generadas, lo siguiente es fijar un terminal y resolución. En este post voy a utilizar como referencia un iPhone (320x480, recordad que son puntos) y utilizaré CoronaSDK para explicar los diferentes conceptos. En Corona, la resolución se fija mediante el config.lua width = 320, height = 480, scale = "letterbox" A partir de aquí, todo sucede en 320x480 para cualquier iPhone. Pero, ¿y el resto de dispositivos? Aquí es donde está el kit de la cuestión y la clave para entenderlo todo: el escalado. Efectivamente todo se escala. Es similar a cuando vemos una película en modo "cinemascope 16x9" en la tele pero podemos elegir diferentes escalados. Según lo que elijamos, veréis que hay zonas de la película que desaparecen de la pantalla o que quedan bandas negras alrededor (zonas muertas de las que hablábamos antes). En un juego pasa lo mismo: puedes elegir, principalmente, escalar hacia abajo ("letterbox") o escalar hacia arriba ("zoomEven"). Según lo que elijas, así se verá en el terminal diferente para el que se diseñó. Uno de los principales errores es utilizar la relación de aspecto como factor de escalado, ya que provoca deformaciones y no genera el ansiado "pixel perfect". El factor de escala depende del tipo de escalado que elijamos:

  1. Hacia abajo escalan las anchuras, manteniendo toda la imágen en pantalla. En nuestro caso sería 320 entre XXX, donde XXX es el ancho de la resolución del dispositivo en el que queremos desplegar nuestro juego.
  2. Hacia arriba escalan las alturas, provocando que puedan desaparecer imágenes de nuestra pantalla. En nuestro caso sería 480 entre YYY, donde YYY es el alto de la resolución del dispositivo en el que queremos desplegar nuestro juego.


A modo de ilustración, os pongo una figura de nuestro diseño de iPhone comparado con un NexusOne:

Por último os dejo un enlace a un template de proyecto de corona donde ilustra todo lo explicado:

https://www.dropbox.com/s/mmlfxont1uo5oqj/UniversalBuildSkeleton.zip
y un enlace con más información sobre este tema:
http://www.coronalabs.com/blog/2010/11/20/content-scaling-made-easy/

M.




Desarrollo en iOS con Cocos2D+LevelHelper+SpriteHelper

4 comentarios

Ahora que estamos a punto de sacar al mercado nuestro producto Rita la lagartija, merece la pena echar la vista atrás y repasar lo que ha sido el proceso de desarrollo de esta historia interactiva para niños (aká, "cuento infantil").


Y es que cuando uno se embarca en la construcción de un proyecto de estas características, lo primero que le viene a la mente es: "¿Qué voy utilizar que me facilite la vida?". Comienza pues el proceso, bien llamado "googlear", en el que básicamente pasan por delante de tus ojos decenas de webs, blogs, referencias, preguntas, respuestas, etc etc etc. Idealmente, la solución a la pregunta pasa por el siguiente timeline:


  1. Anotar referencias de herramientas y frameworks
  2. Descargar dichas referencias y frameworks
  3. Evaluarlas
  4. Decidir con quién te casas...


Puesto que nunca se tiene tiempo infinito, al final has de hacer una apuesta y arriesgarte con algo sin estar completamente seguro (a no ser que ya tengas experiencia en el uso de varias de ellas). Para ello uno se hace básicamente tres preguntas: ¿Para qué mercado lo voy a publicar (AppStore, GooglePlay, etc)? ¿Para qué terminales lo quiero desarrollar (Smartphone, Tablet, etc)? ¿Qué tipo de tecnología necesito?


En nuestro caso las respuestas son: 1. iOS, 2. iPad, 3. OpenGL. El punto 1 y 2 lo dominamos sin problemas, pero el punto 3 es donde estamos más flojos. Basado en estas premisas, nuestra decisión ha sido la de utilizar Cocos2D como framework de desarrollo de nuestro cuento. Sin duda, una gran experiencia teniendo en cuenta nuestras carencias y el resultado.


Cocos2D es un framework de desarrollo basado en OpenGL mediante el cual se pueden implementar la mayoría de juegos y aplicaciones 2D sin ningún tipo de problemas. Incorpora soporte para el motor de físicas Box2D que es perfecto si lo necesitas. La curva de aprendizaje es baja y te permite implementar bastantes de las interactividades que este tipo de proyectos necesitan, además de ser fácilmente extensible, ya sea en funcionalidad o complejidad gráfica (OpenGL).


Pero claro, Cocos2D no deja de ser un framework de desarrollo, pero una vez revisado el material gráfico para el proyecto, te das cuenta que necesitas alguna herramienta para construir las diferentes escenas (en nuestro caso, del cuento interactivo). Con la experiencia de LevelSVG y CocosBuilder, hemos decidido utilizar LevelHelper y SpriteHelper.


Estas dos herramientas te permiten definir visualmente el aspecto que van a tener tus escenas. Es como reconstruir el archivo PSD de Photoshop original pero orientado a Cocos2D. Digo el archivo PSD de Photoshop porque normalmente los diseñadores e ilustradores utilizan esta herramienta para construir y transmitir su material.


Ambas herramientas son de pago, aunque su precio es pequeño en comparación con lo que aportan. El autor da un soporte muy valioso, respondiendo al e-mail casi al momento en caso de duda. LevelHelper te permite definir las escenas y las características de los elementos que forman parte ellas (físicos o no), además de incorporar características comunes en este tipo de juegos/aplicaciones (animaciones y parallaxes). Aunque tiene algunas carencias, como el soporte para UI's, la herramienta evoluciona muy rápidamente en el tiempo. SpriteHelper te permite generar los atlas de imágenes (Sprite Sheets) tan valiosos para un buen rendimiento de tu juego/aplicación (es una herramienta similar a TexturePacker o Zwoptex, menos potente, pero imprescindible para usar LevelHelper).


Para acabar, que nadie se piense que mediante el uso de Cocos2D,LevelHelper y SpriteHelper las cosas se mueven o interactúan sólas. ¡La lógica del juego/aplicación la construyes tú!

M.