10-Aventuras en Megadrive: Sprites

DATOS TÉCNICOS

  • Los sprites se colocan en el plano de Sprites.
  • La posición en pantalla de un sprite viene dada en píxels y no en tiles.
  • El plano de sprites es un plano fijo, no puede tener scroll.
  • Podemos tener un máximo de 80 sprites.
  • Podemos tener hasta 20 sprites por línea horizontal.
  • Podemos controlar el orden en el que se dibujan los sprites.
  • Los sprites se almacenan y construyen con tiles, igual que los fondos. Por tanto podemos usar tiles tanto para hacer fondos como para hacer sprites.
  • Un sprite puede ser construido con un solo tile (1×1)=(8×8 píxels), pero también con varios tiles, con un máx de (4×4) tiles=(32×32 píxels).
  • SGDK nos permite utilizar multi-sprites de hasta 16×16 tiles, para crear sprites enormes.
  • Una imagen de un sprite debe, por tanto, ser divisible por 8.

La forma de cargar un sprite en VRAM y dibujarlo es muy parecida a lo que hemos hecho con los planos/fondos. Pero hay algunas diferencias.

Para tener acceso a las funciones de manejo de sprites del SGDK añade:

#include "sprite.h"

Has de reservar memoria para guardar los sprites en la VRAM antes de usarlos.

SPR_init(max_num_sprites, tamaño_en_vram, buffer_descompresión);

Recordemos que se guardan como tiles. Si no tenemos claro los parámetros de esta función, escribiremos lo siguiente (equivale a usar los valores por defecto del SGDK):

SPR_init(0,0,0)

Antes de cargar un sprite, deberemos cargar su paleta (igual que hacíamos con los planos). Usaremos SPR_addSprite() para cargar los sprites en memoria. Tal y como hacemos con los planos, usaremos TILE_ATTR() para indicar la paleta, si lo mostramos invertido, etc.

Al contrario que con un fondo, los sprites irán cambiando su posición e incluso su aspecto, ya que pueden estar animados. El VDP de Megadrive por defecto mantiene los sprites frame tras frame, no los borra. Esto es, si un sprite cambia de posición o de animación, esto se hace (calcula) en el lado del procesador (en el famoso Motorola 68000), el VDP no se entera si no se lo decimos explícitamente.

La forma de hacer esto es usar  SPR_update(), normalmente en el bucle principal:

...

while(TRUE)
{
SPR_update();

VDP_waitVSync();
}

...

 

ZONA VISIBLE E INVISIBLE

Internamente para la MD el plano de sprites tiene normalmente 512×512 píxels, siendo el punto sup-izq de la pantalla el (128,128). EL SGDK toma ésta coordenada como (0,0) para facilitarnos la vida. Sabiendo que la resolución habitual es 320x224px, el SGDK nos permite tratar los sprites sabiendo que si su x=[0 .. 320] y su y=[0 .. 224], estos estará en la zona visible de la pantalla:

TV

Por tanto un sprite en (-20,300) no será visible. Tampoco uno situado en (450, 200).

Internamente, la MD no permite valores superiores a 512 para las coordenadas de un sprite. Si el valor la coordenada es superior a 512, es como si volviera a partir de 0. Por tanto un sprite en (300,815) equivale a (300, 815-512 = 303)=(300, 303).

 

¿Por qué tener un área superior a la parte visible de la pantalla?

Cargar sprites (que al final son tiles) en VRAM implica gastar tiempo. Normalmente no vamos a mostrar todos los sprites de una fase nada más comenzar. Por ejemplo, habrán enemigos que salgan al principio, otros al final, habrán sprites para el decorado, etc.

Podemos copiar esos tiles al principio de la fase en VRAM, dejando los sprites que no estamos usando fuera de pantalla, a la espera de usarlo en un momento determinado.

Para estos sprites fuera de pantalla no cuenta el límite de 20 por línea, aunque sí cuentan para el máximo total de sprites, 80, que no podemos sobrepasar estén visibles o no.

Otro uso más mundano, es tener sprites que entren y salgan de la pantalla, por ejemplo una nave que suba y baje en un mata marcianos. Parece una tontería, pero existían sistemas que no permitían esto en la época, si un sprite se salía por la derecha de la pantalla aparecía por la izquierda p.e., así que el programador tenía que controlar esto manualmente.

 

ARCHIVO RES

La forma de indicar al SGDK dónde están los sprites es similar, utilizaremos de nuevo un archivo RES aunque los parámetros son diferentes:

SPRITE nombre_variable "recurso.png" tiles_ancho tiles_alto FAST  veloc_ani

nombre variable: variable que usaremos en el main.c
recurso.png: el nombre del archivo (opcional: poner la ruta si está en subcarpetas)
tiles_ancho y tiles_alto: indicaremos aquí cuantos tiles tiene el sprite.
FAST: tipo de compresión, lo dejamos así de momento
veloc_ani: tiempo entre cada frame del sprite

Si el sprite son p.e. 32×16 pixeles, en [tiles_ancho] y [tiles_alto] pondremos 4 y 2 respectivamente ( 32/8 = 4  ,   16/8 = 2).

Para guardar las distintas animaciones de un personaje, normalmente se utilizan  spritesheets (hojas de sprites). Se trata de una imagen con todos los posibles sprites de . Ya sea quieto, corriendo, atacando, explotando… un ejemplo con Sonic

Captura9

En este caso [tiles_ancho] y [tiles_alto] serán respectivamente 6 y 6 (hay que contar los cuadritos que hay dentro del cuadro rojo).

La posición en pantalla de un sprite viene indicada por el punto sup-izq de dicho cuadro.

Es decir, los pies de Sonic estarán en distinta posición, hay que tener esto en cuenta a la hora de situar el sprite en pantalla.

Siguiendo con la explicación, todos los sprites de Sonic estarán en un cuadro 6×6:

Captura10

En realidad, internamente, la MD está manejando más de un sprite, ya que el máximo se supone que es 4×4 tiles por cada sprite. Para ello debemos usar multi-sprites.

El SGDK nos ahorra ese dolor de cabeza. Lo vemos en la siguiente entrada.

 

 

Anuncios