Lección 04 – Tiles a partir de imágenes

Aventuras en Megadrive: Tiles a partir de imágenes

Es difícil hacer un juego creando los tiles «a mano», desde el código es realmente incómodo. Lo habitual es utilizar un programa que nos permita crear pixel-art y usar las herramientas del SGDK para para crear tiles a partir de imágenes.

NORMAS

  • El tamaño de la imagen debe ser divisible por 8 (p.e. 64×32 ok, 67×31 no).
  • La profundidad de color de una imagen debe ser máximo de 4bpp (16 colores).
  • El primer color de la paleta de una imagen se usa para la transparencia del fondo.
  • El número de colores en pantalla debe ser, como máximo, de 64 colores.
  • Debemos indicar cada imagen en el archivo RES correspondiente.
  • Debemos llevar la cuenta de cuantos tiles hemos cargado en VRAM para no machacar una imagen con otra.

 

Lo vemos con un ejemplo. Vamos a cargar una imagen en memoria, el SGDK descompondrá la imagen en tiles, crearemos una paleta de colores a partir de la imagen y la mostraremos.

Captura

Empecemos. Crea un proyecto nuevo. Copia esto en el main.c o bien cógelo del primer ejemplo de mi github.

#include "genesis.h"
#include "resources.h"

int main()
{
  //para llevar la cuenta de tiles en VRAM
  u16 ind;

  //recoge la paleta de la imagen y la asigna a la PAL0
  VDP_setPalette(PAL0, moon.palette->data);

  //reserva las primeras 16 posiciones de la VRAM, de la 0 a la 15 (ind = 16)
  ind = TILE_USERINDEX;

  //carga la imagen en VRAM y la dibuja en pantalla en la posición (3,3)
  VDP_drawImageEx(PLAN_A, &moon, TILE_ATTR_FULL(PAL0, 0, 0, 0, ind), 3, 3, 0, CPU);
  
  //incrementa ind para 'apuntar' a una zona de VRAM libre para futuras tiles
  ind += moon.tileset->numTile;

  while(1)
  {
    VDP_waitVSync();
  }

 return 0;
}

 

No compiles todavía. Ahora crea una carpeta llamada res que cuelgue de la carpeta del proyecto actual. Descarga esta imagen en esa carpeta. Llámala moon.png

moon

Ahora hemos de preparar el archivo RES. En la carpeta res, crea un archivo de texto llamado ‘resources.res’. Abre el archivo y escribe:

IMAGE moon "moon.png" 0
  • Esto define la variable moon, que es usada en el main.c para referirse al recurso. Podemos llamarla como queramos, no hace falta que se parezca al nombre del archivo aunque sí recomendable.
  • Además le decimos al SGDK cual es el recurso y dónde está (en este caso «moon.png» en la propia carpeta res. Opcional: podemos crear subcarpetas y poner la ruta hasta el archivo para tenerlo todo mejor organizado.
  • Finalmente el cero significa que no usamos compresión de datos. No tocaremos este tema por ahora.

Graba los cambios. Ahora compila el proyecto (MAY+F9). Si todo va bien:

  • Aparecerá un archivo ‘resources.h’ en la carpeta RES.
  • En la carpeta OUT, que se creará al compilar el proyecto, además de la ROM, tendremos a su vez otra carpeta RES. Dentro encontraremos un archivo ‘resources.o’, que es el bitmap procesado por el SGDK.
  • Por supuesto carguemos la rom en un emulador para ver que carga la imagen y la muestra correctamente.

Ahora veamos un poco más el código:

#include "resources.h"

Fuerza al SGDK busca el archivo .res y genera el archivo .h correspondiente (si no existe). El SGDK procesará la imagen para crear tiles a partir de ella. Si has elegido otro nombre para el archivo RES, deberás cambiar el .H también.

u16 ind;

Crea una variable llamada ‘ind’ (índice). Esta variable llevará la cuenta de cual es la primera tile libre en VRAM. Cada vez que cargamos una imagen, la incrementamos en tantas tiles como hemos necesitado para cargar dicha imagen en memoria.

De esta forma no machacamos las tiles de otras imágenes que podríamos haber cargado previamente. Y se cargan consecutivamente en VRAM.

El SGDK lleva la cuenta de cuantas tiles ocupa cada imagen, así que si una imagen ocupa ‘x’ tiles:  ind = ind + ‘x’

Ojo que ‘ind’ no tiene porqué ser 0 (siguiendo la norma de C una variable recién creada puede apuntar a una zona de memoria con basura). Así que lo primero es inicializarla, lo típico será:

ind = 0;       o bien      ind = 1;

Esto hacer que empecemos a meter los tiles de la imagen en VRAM a partir de la primera o segunda posición de VRAM.

Con ciertas funciones si hacemos ind = 0, podríamos encontrarnos con efectos poco deseables. Veremos uno en la segunda parte de esta lección.

En este ejemplo, en cambio, pondré:

ind = TILE_USERINDEX;

Esto último reserva los primeros 16 tiles de la VRAM, coloca en esas posiciones tiles planos con los colores de la primera paleta. Si usamos tiles planos, ya los tenemos, por ejemplo los tiles del fondo. Esto es meramente didáctico.

Seguimos con la explicación del programa:

VDP_drawImageEx(PLAN_A, &moon, TILE_ATTR_FULL(PAL0, 0, 0, 0, ind), 3, 3, 0, CPU);
ind += moon.tileset->numTile;

Cargamos la imagen en VRAM y la mostramos en pantalla:

  • En el plano A.
  • Con la paleta 0 (la primera).
  • Sin invertir ni en plano horizontal ni vertical.
  • En la posición (3,3). recordemos que hablamos en tiles, no en píxels.
  • Incrementamos ‘ind’ tanto tiles como tiles ha generado el SGDK al cargar la luna

Tras esto podemos cargar otra imagen, y sus tiles irán en memoria a continuación. Lo veremos en la siguiente entrada.

 

GITHUB

El código de esta lección, y de todas las demás, lo podrás encontrar en mi github:

https://github.com/danibusvlc/aventuras-en-megadrive