martes, 30 de abril de 2013

Programando para Android - 3. El mapa

El colega kpacha me hace una pregunta muy interesante en el capítulo anterior y merece un mínimo análisis.
Me dice que eso de guardar el mapa en un archivo de imagen podría ocupar demasiado espacio comparado con almacenarlo en un archivo de texto plano, que tiene un byte por casilla y encima se puede comprimir.

Puede ser, porque el archivo de mapa de bits probablemente deberá tener al menos 3 bytes por cada píxel, uno para cada componente de color (RGB) otra para el canal alfa y vete a saber qué más y no podríamos aprovechar la compresión jpg porque necesitamos píxels "perfectos". Aunque sí podríamos usar compresiones tipo zip.

Para empezar aviso que en realidad la gracia de hacer el mapa con una imagen no es el espacio, es que se pueden "dibujar" las plataformas muy cómodamente con cualquier editor de imagen. Yo las he hecho con el Gimp y es escandalósamente rápido con la herramienta lápiz.

Pero sí es verdad que si se tratase de un juego con muchísimos mapas o que fuesen muy grandes podría empezar a notarse el espacio ahorrado. Así que he hecho uno de los mapas en txt a ver qué pasa.


Son 28 columnas y 15 filas. Aquí podéis ver los archivos que he hecho para comprobar el tamaño:


El excel lo he hecho para crear más rápido el de texto, pero está claro que no sale a cuenta, ocupa mucho más incluso comprimido. En formato csv comprimido mejora pero no alcanza a los otros.

El tamaño 1KB que marca es inexacto, hay que ir a propiedades de cada archivo o bien abrir nuestra querida consola de comandos:


Donde podemos ver que la cosa está más reñida de lo que parece.
map3.png es el archivo original que uso en el progama. Son 240 bytes sin hacer nada especial. No está nada mal y es mejor que el mapa.txt (450B) sin comprimir y mejor que el csv comprimido.
Entonces vemos que el mapatxt.zip es bastante mejor y que nos ahorra una buena proporción de espacio. Sería el momento de comprimir el png pero vemos que map3png.zip... ¡Ocupa más que sin comprimir! Lo cual nos da la idea de que el formato png lleva incorporadas compresiones lossless bastante buenas.
Entonces parece que ocupa menos el txt comprimido... pero hay algunas opciones en el formato png para ahorrar información en la cabecera del archivo. Si al guardar desactivamos todas estas opciones ganamos muchos bytes:


Así el archivo de 28x15 = 420 píxels se queda en 145 Bytes. Que ya está muy bien. Seguro que podríamos inventar algún formato para mejorar esos números, supongo que aún estamos lejos de la entropía mínima. Pero también habría que programar toda la lectura y análisis del archivo mientras que ahora es una única línea.

Incluso hay una opción para minimizar aún más el png, que sería usar color indexado. Si indicamos que solo va a haber un máximo de 8 colores se reduce la cantidad de bits por píxel y se consigue que ocupe 130B.

Además este minimapa tipo png se puede usar directamente dentro del juego para diferentes cosas como un "mapa en pantalla" superpuesto para que el jugador se ubique. También como previsualización en una hipotética pantalla de selección de niveles. Pero sobre todo pintar las plataformas con el ratón me ha convencido desde el principio.

Más cosas, he retocado el control de juego para hacerlo más estándar y he dibujado los controles en pantalla y las monedas. También he cambiado imágenes y el recorrido, los parámetros físicos del personajes y otros detalles...


6 comentarios:

  1. Pues ya sabes.
    Necesitaría sprites de la resolución que quieras pero que se vean bien al redimensionarlos a 32x32 píxels. Y puestos a pedir iría bien dibujos en las diferentes posiciones parado, saltando, ciclo de andar o de correr, disparar... es un poco pronto porque aún no sé si llevará arma o no pero siempre se podría añadir, no?

    ResponderEliminar
  2. Vaya... y yo pensando que ibas a colaborar...

    http://i219.photobucket.com/albums/cc12/sirkillsalotlol/TROLLS-TROLLS-EVERYWHERE-1.jpg

    ResponderEliminar
  3. como decía:

    (4,27)1A
    (7,1)1X
    (9,1)1X,(9,3)1B
    (11,1)9X
    (11,1)9X

    sirve para describir este mapa de 28x15 completamente y en sólo 50 bytes. y todavía es muy mejorable

    ResponderEliminar
  4. fe de ratas: en mi anterior comentario había un typo... el mapa se describiría así

    (4,27)1A
    (7,1)1X
    (9,1)1X,(9,3)1B
    (11,1)9X
    (12,1)9X
    (13,1)9X

    ... y sí, son 60bytes en vez de 50.

    ResponderEliminar
  5. fe de ratas 2: me acabo de dar cuenta de que no he corregido todos los fallos... espero q no os pongáis muy quisquillosos con el tema de las posiciones, pero es q inicialmente lo había preparado para una rejilla de 30x15 y se me han escapado algunas cosillas como por ejemplo el posicionamiento del objeto A.

    para el caso es lo mismo, pq lo q importa aquí es el peso de la descripción...

    ResponderEliminar
  6. Esa codificación del texto que propones es cierto que está muy bien para que ocupe menos pero sería un peñazo para el diseño de niveles. Lo típico será unas 30 fases y deberían de estar muy bien planificadas para que sean entretenidas, moderadamente difíciles, etc. Para ello habrá que ir testeando muchas variantes y luego ir haciendo muchos pequeños cambios. Para eso es mucho más visual crearlo en modo imagen o al menos con el texto expandido con los espacios.

    Por otra parte si tengo 30 fases que en vez de ocupar 150B ocupan 50B... ahorro 3KB en total. Cualquiera de los sonidos o imágenes incluidos en el juego va a ocupar más que eso. Las apps vienen ocupando de un MB para arriba.

    Pero si al final resulta que quiero ahorrarme esos 3KB siempre puedo convertir los pngs a ese formato o similar aunque solo fuera para la exportación final.

    ResponderEliminar