Asteroids: colisiones de disparos con asteroides (paso III) #Programación retro del Commodore 64

Una vez que sabemos con precisión qué asteroide es el que ha colisionado, el siguiente paso es animarle una explosión. Esto es lo que vamos a hacer en esta entrada.

Nos queda pendiente, también, resolver el problema de las colisiones de los asteroides con el texto de la derecha. De momento son indistinguibles de las colisiones con los disparos. Esto lo resolveremos más adelante, por fin, moviendo ese texto a la línea inferior.

Hacer una animación de explosión con un asteroide tiene las mismas dificultades que con hacer una animación de explosión con la nave:

  • Hay que detectar la colisión y marcarla con un valor especial en "asteroidesActivos". De momento ese valor es $00.
  • Hay que hacer la animación. La animación no puede hacerse de golpe, pasando todos los "frames" en un ciclo del bucle de juego porque, o bien es imperceptible o, si metemos un bucle de demora, todo el juego se demora y parece que se engancha en la animación. Por tanto, hay que pasar la animación durante varios ciclos del bucle de juego, lo cual se consigue con una variable de retardo ("asteroidesRetardoExplosion") y con una variable para controlar por qué "frame" vamos ("asteroidesExplosionFrame").

Hasta aquí, todo igual que con la nave. Ahora bien, asteroides hay siete, y todos pueden explotar. Por tanto, estas últimas variables que hemos definido tienen que ser tablas. Esto podemos verlo aquí:

Asteroids - Variables explosión asteroides

Luego hay otra particularidad más sutil. Con la nave, marcábamos con $01 el estado activo, y con $00 el estado explotando. Tengamos presente que la nave no puede estar inactiva; siempre está presente en el juego. Sin embargo, los asteroides pueden estar activos ($01) o inactivos ($00). Por tanto, necesitamos un nuevo valor para la situación de explotando. Arbitrariamente, hemos elegido que ese valor sea $02.

Este nuevo valor $02 puede verse en la nueva versión de la rutina "actualizaColisionesAsteroides" que, además, ya no desactiva en SPENA el sprite del asteroide que explota. Y no lo desactiva porque es necesario tenerlo activo para hacer la animación:

Asteroids - Colisiones asteroides con valor 02

No sería necesario cambiar nada más. Sin embargo, por coherencia y claridad del código, vamos a hacer lo mismo con la nave. Es decir, vamos a marcar con $01 el estado activo y con $02 el estado explotando. El estado $00 queda en desuso para la nave, puesto que ésta no puede estar inactiva. Ver la rutina "actualizaColisionesJugador".

Bueno, ya tenemos identificado qué asteroide o asteroides están explotando mediante el valor $02 en la tabla "asteroidesActivos". Ahora, por fin, vamos a hacer la animación.

En el caso de la nave esto lo hacíamos en la rutina "actualizaJugador". En esta rutina verificábamos el estado de la nave (antes $01 vs $00, ahora $01 vs $02) y, en función de esto, actualizábamos el jugador (posición, disparos y colisiones) o animábamos la explosión.

El equivalente de "actualizaJugador" sería "actualizaAsteroides". Ahora bien, esta rutina no tiene un bucle para recorrer los siete asteroides. El bucle está en cada una de las rutinas llamadas por ésta: "actualizaPosicionAsteroides", "actualizaAsteroidesActivos" y "actualizaColisionesAsteroides". Y ese bucle nos haría falta para hacer un tratamiento individualizado de los asteroides, puesto que unos asteroides pueden estar moviéndose y otros explotando.

Podríamos rediseñar "actualizaAsteroides" de arriba abajo, para mover a esta rutina el bucle que permitiría individualizar el tratamiento de los asteroides, y que actualmente está en cada una de las rutinas llamadas. Sin embargo, para no tener que rediseñar mucho, lo que vamos a hacer es meter el control de estado en "actualizaPosicionAsteroides". Si el asteroide está activo se moverá; si está explotando se animará la explosión.

Dado que la parte de movimiento de "actualizaPosicionAsteroides" ya es conocida, nos limitamos a poner aquí la parte de la rutina relativa a la animación. Obsérvese cómo se ejecuta cuando el estado del asteroide es $02:

Asteroids - Explosion asteroides

Básicamente lo que se hace es llamar a la rutina "animaExplosionAsteroide", que recibe el número de asteroide que está explotando mediante el parámetro o posición de memoria "aeaAsteroide". El número de asteroide es necesario para hacer la animación sobre el sprite de ese asteroide, y no sobre otro sprite.

La rutina "animaExplosionAsteroide" es muy parecida a la ya conocida "animaExplosion" de la nave, siendo la principal diferencia que la primera puede trabajar con un sprite u otro, mientras que la segunda sólo trabaja con el sprite de la nave. Su código principal es así:

Asteroids - Anima explosión asteroides

Es decir:

  • Decrementa el retardo del asteroide que ha explotado ("asteroidesRetardoExplosion"). Para identificar el asteroide que ha explotado se utiliza el registro Y.
  • Si el retardo no ha llegado a cero, termina.
  • Si el retardo ha llegado a cero, restaura el retardo a cinco y pasa el siguiente "frame" de la animación.
  • Para saber por qué "frame" va el asteroide que ha explotado, se utiliza la tabla "asteroidesExplosionFrame". Y para identificar el "frame" por el que vamos se utiliza el registro X.
  • Para cambiar el "frame" se utiliza la rutina "configuracionBasica".

Una cosa curiosa que puede llamar la atención del lector, y que no había ocurrido hasta ahora, es que, en ocasiones, tras hacer una llamada a una rutina con "jsr" hacemos un "ldy" o un "ldx" para recuperar un valor. Esto puede verse aquí tras "jsr configuracionBasica" (línea 383):

Asteroids - ldx raro

Lo que está ocurriendo es que "aeaNumeroFrame" tiene el número de "frame" que vamos aplicar. Ese número de "frame" se carga en el registro X para poder obtener el puntero asociado con "lda explosionFrames,x" y pasarlo a la rutina "configuracionBasica".

Pero, al llamar a la rutina "configuracionBasica", cambia el valor del registro X, puesto que las rutinas no nos garantizan que los registros del microprocesador permanezcan constantes. Por tanto, a la vuelta de la rutina volvemos a recuperar el valor del registro X desde "aeaNumeroFrame", puesto que vamos a seguir utilizándolo. Concretamente, necesitamos incrementarlo y guardarlo en "asteroidesExplosionFrame" para la siguiente iteración de la animación.

Hemos visto la animación, pero nos queda lo que ocurre al terminar la animación. Ocurre esto:

Asteroids - Fin animación asteroides

Es decir:

  • Incrementamos en 10 los puntos del jugador.
  • Volvemos a poner a cero el "frame" de explosión del asteroide en cuestión, de modo que si vuelve a explotar la animación vuelva a empezar desde el "frame" correcto.
  • Ponemos el asteroide inactivo ($00), de modo que la rutina "actualizaAsteroidesActivos" lo coja y lo reactive cuando estime oportuno.
  • Y volvemos a leer el registro SPBGCL, igual que hacíamos con SPSPCL en el caso de la nave, para evitar dos explosiones seguidas. Esto es un truco.

Y ahora, ya por fin, y después de tres arduos pasos, hemos conseguido que exploten los asteroides cuando son alcanzados por disparos:

Asteroids - Asteroides explotando

Todo esto puede verse en la versión 16 del proyecto.

En la siguiente entrada moveremos, también por fin, el texto de la derecha a la línea inferior de la pantalla. Queda mejor y, de paso, nos evitamos que los asteroides exploten al tocar ese texto.


Código del proyecto: Asteroids16


Editar

Josepzin

No hay comentarios:

Publicar un comentario