lunes, 30 de mayo de 2016

VOLCADO DEL BUFFER CON LDI (III): TABLAS DE SPRITES Y CONTROL DEL PROTA



En esta entrada voy a explicar cómo se realiza el control de los sprites. Para poder hacer esto, necesitamos unas tablas que nos digan las características del sprite, su posición y toda la información necesaria.

Estas tablas se encuentran en ATABLAS.ASM.
En este ejemplo voy a manejar al PROTA, al disparo (si existe) y a 6 enemigos.

Aquí vemos una tabla tipo de un sprite enemigo:



El significado de cada byte de la tabla es el siguiente:

byte 0: Coordenada Y del sprite
byte 1: Coordenada X del sprite
byte 2: Ancho del sprite en caracteres
byte 3: Alto del sprite en líneas dividido por dos.
Si un sprite tiene un tamaño de 3 caracteres de ancho por 3 de ancho, el byte 3 valdrá 3             caracteres*8 líneas que tiene cada caracter dividido por 2, osea: 12. Se divide por dos por el  método que usamos para imprimir el sprite.
byte 4 y 5: Dirección donde se guarda el gráfico a imprimir con la fase actual
byte 6: Pausa que se hace cuando cambiamos antes de cambiar la fase (o frame) a un sprite. Si no se    pone  pausa, parece que va bailando y si se pone demasiada, parece que va patinando.
byte 7: Fase actual del sprite
byte 8 y 9: Gráfico de la primera fase del sprite.
byte 10: Número de fases que tiene el sprite menos 1.
byte 11: Número de pixels que se mueve el sprite en la coordenada Y. Siempre tienen que ser pares.
byte 12: Número de pixels que se mueve el sprite en la coordenada X. Siempre tienen que ser pares.
byte 13: Tamaño que tiene el sprite para cambiar de fase. Si pasamos de la fase 1 a la fase 2, tenemos que saber cuánto ocupa el sprite y así sumarlo a la fase anterior.
byte 14 y 15: Gráfico del sprite mirando a la derecha
byte 16 y 17: Gráfico del sprite mirando a la izquierda
byte 18: Anchura del sprite en pixels. Esto lo uso para saber cuando llegamos al límite derecho de la   pantalla y así darle la vuelta y cambiar el sentido de movimiento. Este dato lo podemos hallar dividiento por dos el byte 2, pero así es más rápido y ocupa muy poco.
byte 19: Este byte se usa para que el sprite vaya a la mitad de velocidad (el esqueleto que sale arriba   del todo). Si el bit 7=1 (10000000b=128) es que este sprite va a la mitad de velocidad que el prota.

No te asustes con toda esta información. A medida que se vaya usando en el programa lo iré explicando más exhaustivamente.

CONTROLANDO AL PROTA






Lo primero que hacemos es cargar IX con el inicio de la tabla del prota.
Como vimos en otra entrada, las teclas pulsadas se guardan en JOY+1.
Si el bit 1 de este valor es uno, es que la tecla izquierda está pulsada.
Al pulsar la tecla izquierda, el sprite se tiene que mover para la izquierda y además poner el gráfico mirando en esta dirección...si no lo está ya. Para eso usamos HORIEN. Yo no suelo usar direcciones de memoria para guardar variables como tal. Si te das cuenta, directamente pongo:

HORIEN  LD A,0

LD A,n ocupa dos bytes, por lo que mi variable se va a guardar en HORIEN+1.

Si HORIEN+1 vale cero, es que está mirando a la derecha, por ello tenemos que meter el gráfico de la izquierda y si vale cero, ya está metido, así que nos ahorramos este paso.

Antes de saltar a INICIO, en contenida ponemos al prota mirando a la derecha:




Con OR A sabemos si vale cero o no. Si vale cero, incrementamos A y actualizamos la variable HORIEN+1 para saber que ya está mirando para la izquierda. Metemos el gráfico de la izquierda y llamamos a METEG, que está en ARUTINAS.ASM:





Aquí, ponemos a cero el contador de frames del sprite para que no cambie enseguida y metemos el gráfico de la izquierda en el sitio correspondiente de la tabla.

Luego cogemos la coordenada X del sprite (como sé que IX=PROTA, en vez de usar LD A,(IX+1), uso LD A,(PROTA+1) que es más rápido) y miro que no haya llegado al límite izquierdo de la pantalla (coordenada X=0). Si no lo ha hecho, le resto dos y salto a METX1 para que lo guarde en la tabla.

Veamos el control de la derecha:




Básicamente es lo mismo. Si el valor de HORIEN+1 es cero, significa que ya estaba mirando a la derecha, por lo que no cambiamos el gráfico de sentido. Si es uno se procede como cuando se pulsa la tecla izquierda. Luego se mira si hemos llegado al borde derecho (vemos si la coordenada X es el ancho del buffer-16 que es el ancho del sprite en pixels) y si no lo ha hecho le sumo 2 y guardamos la coordenada actualizada.

Después llamamos a la rutina que nos cambia la fase del sprite, ya que se ha movido . Esta rutina se llama GESTFAS y por supuesto, está en ARUTINAS.ASM.

Voy a explicar cómo funciona el tema de las FASES del sprite o FRAMES.
A la hora de mover un sprite y para que la sensación de movimiento sea más real se usan fases. Por ejemplo, nuestro prota tiene 2. Así, al alternarlas mientras se mueve parece que anda.



(Llamaré a la fase con los pies juntos, FASE A y a la de los pies separados, FASE B)

Si echas un vistazo en ASPRITES.ASM verás que los gráficos se guardan en orden de fases



PROTAD1.BIN es la FASE A del prota mirando a la derecha y PROTAD2.BIN es la FASE B.
Esta es la manera de guardar todos los gráficos de los sprites.


Los bytes de la tabla de sprites que controlan las fases son:
  • Byte 6: es una pausa que se hace para que no cambie de fase cada vez que se mueve el sprite. En este caso cambia cada 3 veces que se mueve. Esto es para que el efecto de movimiento sea más "real".
  • Byte 7: aquí se guarda el número de la fase en curso. Cuando es igual al número total de fases-1, se pone otra vez a cero.
  • Byte 10: número total de fases -1
  • Bytes 4 y 5: En estos bytes se guarda la dirección donde está el gráfico del sprite que se tiene que imprimir. 
  • Bytes 8 y 9: En estos se guarda la dirección del primer gráfico del sprite.
  • Byte 13: guarda los bytes que ocupa cada gráfico del sprite. Cada fase.
Empezamos con la FASE A. El byte 7=0 y no tenemos que hacer pausa. En FASE miramos si ya estamos en la última fase (byte 10). Si no es así, seguimos en LA3 con lo que incrementamos el contador de fase (byte 7) y sumamos al gráfico que tenemos que imprimir el tamaño del mismo. Osea, a la FASE A le sumamos 64, que es lo que nos ocupa el gráfico y lo guardamos otra vez en los bytes 4 y 5 para que se imprima ese gráfico, que no es otro que FASE B.
Si tuviera más fases esto se repetiría con la FASE C, FASE D, FASE E... Cuando el contador (byte 7) sea igual al número total de fases -1 (byte 10) pasaríamos a FASDER. Aquí se pone a cero el contador y en los bytes 4 y 5 se mete la primera fase del sprite (FASE A) que está guardada en  los bytes 8 y 9.


RUTINA GESTFAS



En cuanto al contador de pausa que se gestiona en GESTFAS funciona como sigue:

Lo primero que hacemos es ver si hay que cambiar la fase, ya que como comenté más arriba, no conviene cambiarla cada vez que se mueve el sprite. En este caso se cambia cada tres veces.
Metemos en A la pausa lo incrementamos y hacemos AND 3. Esto es un contador que cada tres veces vale cero.

 Los valores que puede tener son los siguientes:

0=00000000b
1=00000001b
2=00000010b
3=00000011b
4=00000100b

Como hacemos AND 3 (00000011b), el registro A sólo va a ser distinto de cero cuando valga 1,2 o 3. Si vale 4 al hacer el AND nos queda cero. Por lo que el contador vuelve a empezar y podemos cambiar de fase. Esto es una manera de usar contadores más rápida.


Con todo este lío no sé si te habrás dado cuenta de un detalle. El sprite del prota es un gráfico de 2x2 caracteres, por lo que debería ocupar: 2 caracteres de alto * 8 líneas que tiene cada caracter * 2 caracteres de ancho=32 bytes. Pero yo he puesto 64. Esto es porque esta rutina no maneja gráficos, maneja sprites (ya sé que hay controversia con estos términos, pero a mí me gusta esta distinción).
Los sprites son gráficos que se imprimen en la pantalla fusionándose con el fondo. Es decir tienen partes transparentes.Además, al moverse, respetan el fondo. Si te das cuenta, a través del agujero del donut se ven las líneas del fondo, lo mismo que en los bordes. Para conseguir este efecto, necesitamos lo que se llama máscara que nos indica qué parte del sprite es transparente. Esta máscara nos ocupa los mismos bytes que el gráfico. De ahí los 64 bytes.
Todo esto de la máscara se verá más adelante.


Para el control vertical del prota creo que no es necesaria ninguna explicación, más que los comentarios del código.







No hay comentarios:

Publicar un comentario