Tutorial de ZX Basic + Fourspriter #26: Adaptando Fourspriter

Vamos a adaptar fourspriter a nuestro juego ya del todo. Ahora mismo lo que nos mosquea es tener que borrar los sprites y luego volver a inicializarlos cada vez que quitamos o ponemos uno. ¿Por qué es esto?

Veamos. Fourspriter sólo actualizará un sprite (restaurar fondo, capturar nuevo fondo, duplicar coordenadas, pintar sprite) si éste está activo. Esto se hace por motivos obvios: no vas a pintar un sprite que no esté activo. Esto funciona bien si vas a tener N sprites siempre activos en pantalla: sólo se tarda el tiempo necesario, y no más. Si sólo tienes 1, ocuparás muy poco tiempo actualizándolo y tendrás más para tu programa.

Sin embargo, esto nos viene muy mal para nuestro programa, ya que el número de sprites activos está fructuando continuamente. Esto provoca que la velocidad del juego sea variable: cuantos menos sprites activos haya (por ejemplo, al entrar en una pantalla sólo hay uno: el del protagonista) más rápido irá el juego. Además está el tema del parpadeo cuando creamos/eliminamos sprites. Como las acciones de tomar fondo, restaurar fondo, etcétera sólo se hacen con los sprites activos, cada vez que activamos un sprite nuevo tenemos que dejar la pantalla “como estaba” (sin sprites) para que los nuevos capturen bien el fondo, y no capturen el cacho de otro sprite en pantalla.

A nosotros estas cosas, como hemos dicho, nos vienen fatal. Por tanto, vamos a modificar nuestro programa y la biblioteca. La modificación que le haremos a fourspriter será muy sencilla: todas las acciones, excepto la de pintar el sprite en sí, se ejecutarán siempre, sin importar que los sprites estén o no activos. O sea, para todos los sprites se estará continuamente tomando y restaurando el fondo, y si están activos, además, se pintarán. Con esto ya no necesitamos borrarlos todos cada vez que introducimos uno nuevo para capturar su fondo: al activarlo, simplemente se empezará a pintar. Las demás operaciones ya se han estado ejecutando y, por tanto, tendrá un fondo correcto siempre. Por tanto, tendremos que quitar casi todos los fsp21BorraSprites y fsp21InitSprites del programa. Lo veremos a continuación.

Lo primero es modificar fourspriter. Abrimos fsp2.1.bas. La idea es eliminar las comprobaciones de “sprite activo” en las funciones que capturan el fondo y borran los sprites.

La rutina de capturar el fondo es init_sprites. Nos vamos con el editor de texto a la misma (puedes usar la función “Buscar” e introducir init_sprites hasta que des con ella si la quieres buscar tú), que empieza en la linea 246. Si miramos por ahí veremos un comentario como este:

;; Primero vemos si el sprite está activo

Y luego hay algunas operaciones en ensamblador. Tenemos que comentar la comprobación: está en las tres siguientes lineas. Tenemos que dejar esta zona del código así:

;; Primero vemos si el sprite está activo
;ld      a,  (de)
;cp      0
;jr      z,  init_adv    ; Si no está activo, nos lo saltamos
inc     de

Ahora tendremos que hacer exactamente lo mismo para la función que borra los sprites (restaura el fondo, esto es). La rutina se llama borra_sprites. Nos vamos a la misma, empieza en la linea 330. Un poco más abajo vemos exactamente el mismo cacho de código para detectar si el sprite está activo que había en la anterior rutina. Igualmente, lo comentamos.

;; Primero vemos si el sprite está activo
;ld      a,  (de)
;cp      0
;jr      z,  borra_adv   ; Si no está activo, nos lo saltamos
inc     de

¡Y listo! Tenemos nuestra fourspriter modificada. Ahora tendremos que modificar nuestro código. Básicamente, eliminaremos todos los fsp21BorraSprites y fsp21InitSprites que no sean los que se hacen al inicializar la pantalla. Hay unos cuantos, pero están todos en bicharracos.bas y boomerang.bas. También hay que cargarse los fsp21DuplicateCoordinatesSprite ya que todo esto se hace automáticamente.

Empezamos por bicharracos.bas. Tenemos la primera ocurrencia al final de la creación de un nuevo bicharraco en el estado BICHESTIDLE. Lo dejamos así (linea 94 y siguientes):

' Mover y activar el enemigo
'fsp21BorraSprites ()
fsp21ActivateSprite (i)
fsp21MoveSprite (i, enX (i), enY (i))
'fsp21DuplicateCoordinatesSprite (i)
'fsp21InitSprites ()

Como vemos, sólo hemos dejado la llamada que activa el sprite y la que lo coloca en su sitio. Seguimos. Hay un fsp21BorraSprites al terminar el estado BICHESTMURIENDO, para quitarlo de la pantalla (linea 134). Lo dejamos así:

enState (i) = BICHESTIDLE
'fsp21BorraSprites ()
fsp21DeactivateSprite (i)

Y ya hemos terminado con bicharracos.bas. Nos vamos a boomerang.bas. Tenemos llamadas al final de la rutina fireBoomerang, cuando creamos el boomerang. Lo dejamos así (linea 58 y siguientes):

If booMX + booMY <> 0 Then
    booX = pX
    booY = pY
    booFrame = 136
    booState = BOOESTAVANZANDO
    booCt = BOOAVANCE
    'fsp21BorraSprites ()
    fsp21ActivateSprite (2)
    fsp21MoveSprite (2, booX, booY)
    'fsp21DuplicateCoordinatesSprite (2)
    fsp21ColourSprite (2, 71, 71, 71, 71)
    'fsp21InitSprites ()
End If

Como véis, de nuevo hemos comentado la llamada a fsp21BorraSprites, a fsp21DuplicateCoordinatesSprite y a fsp21InitSprites. Ahora sólo nos queda una ocurrencia más: cuando eliminamos el boomerang (lineas 135 y siguientes), que debería quedar así:

If booX = pX And booY = pY Then
    booState = BOOESTIDLE
    'fsp21BorraSprite (2)
    fsp21DeactivateSprite (2)
End If

Si ahora compilamos y ejecutamos veremos que todo el parpadeo ha desaparecido: ahora todo se hace automáticamente de verdad. Soy consciente de que este capítulo es un poco liante, pero me parece interesante que tengamos bien claro que, en muchas ocasiones, tendremos que modificar el código de las bibliotecas que usemos para adaptarlas mejor a nuestro güego. Es lo que tiene programar para 8 bits.

Recapitulando

Vamos a recapitular un poco para que veamos cómo funciona ahora la biblioteca y comprendamos cómo se adapta mejor a nuestro escenario (en el que el número de sprites activos está continuamente cambiando).

Originalmente, la biblioteca trabajaba así:

  1. Inicialmente, sólo el sprite 3 está activo. Los demás sprites, los 0, 1 y 2, están inactivos. Al llamar a fsp21UpdateSprites, la biblioteca sólo restaura el fondo del sprite 3, captura el nuevo fondo, y lo dibuja. No hace nada para los sprites 0, 1 y 2 porque están inactivos.
  2. Si ahora aparece un enemigo, se activará el sprite 0. ¿Qué es lo que ocurre? Pues que el sprite 0 no tiene el fondo que hay en sus coordenadas almacenado, y por tanto si llamamos directamente a fsp21UpdateSprites, la parte de la rutina que restaura el fondo pintara “mierda” (un fondo anterior, o vacío, o lo que hubiera almacenado). Es por eso por lo que, al crear un sprite nuevo, estamos llamando a fsp21InitSprites. Pero, espera: fsp21InitSprites captura el fondo, pero si estamos creando al sprite en una zona donde hay otro sprite, en una o más de sus casillas no habrá fondo: habrá un cacho otro sprite. Es por eso que antes de llamar a fsp21InitSprites tenemos que eliminar los sprites de pantalla con fsp21BorraSprites. Eso ocasiona el pequeño parpadeo que vemos.

Tras las modificaciones, la biblioteca funciona así:

  1. Inicialmente, sólo el sprite 3 está activo. Los demás sprites, los 0, 1 y 2, están inactivos. Sin embargo, al llamar a fsp21UpdateSprites, la biblioteca modificada está restaurando el fondo de los cuatro sprites, capturando el nuevo fondo de los cuatro sprites, pero sólo dibuja el sprite 3.
  2. Si ahora activamos el sprite 0 (cuando aparece un enemigo), este sprite ya tendrá su fondo capturado correctamente, ya que esto se ha estado haciendo continuamente aunque dicho sprite estuviera desactivado. Por tanto, no hay que hacer nada. La próxima llamada a fsp21UpdateSprites lo seguirá procesando correctamente, y ahora también se dibujará el sprite 0, ya que ahora está activo.

¿Véis la diferencia y la conveniencia de realizar estos cambios? Espero que sí. Si no, preguntad.

Podéis descargar el paquete que trae la fourspriter y los archivos bicharracos.basboomerang.bas ya modificados y el feoncio.tap generado para que veáis lo bien que se ve ahora. En el próximo capítulo vamos a ver cómo meter pantallas completas comprimidas, y así nos podremos hacer un bonito marco para el juego y una pantalla de presentación y otra para el final.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: