Asteroids: colisiones de la nave con los asteroides #Programación retro del Commodore 64

Ya tenemos una nave que se mueve y dispara y muchos asteroides. El siguiente paso será detectar la colisión de la nave con los asteroides. La colisión de los asteroides entre sí no la tendremos en cuenta.

En caso de que la nave colisione con los asteroides, lo que haremos será animar una explosión y reducir las vidas de la nave o jugador.

Por tanto, lo primero es diseñar la explosión. La explosión no es más que una secuencia de "frames" que diseñaremos con el editor de sprites de CBM prg Studio. No hace falta definir otro fichero de sprites. El mismo fichero "Sprites.spt" que hemos utilizado hasta ahora nos vale, puesto que cargaremos todos los "frames" (8 x nave, 1 x asteroides y 3 x explosión) uno detrás de otro en memoria.

El diseño de la explosión puede verse aquí ("frames" 10, 11 y 12):

Asteroids - Explosión

Como en ocasiones anteriores, habrá que exportar los doce "frames" al fichero "Sprites.bin" e importarlo desde "Recursos.asm". Como esto no es nada nuevo, no abundaremos más en ello.

Sí es importante, en cambio, ampliar las variables del jugador, de modo que definamos una nueva tabla "explosionFrames" para referenciar con comodidad los "frames" de la explosión (201 – 202), igual que hiciéramos en su momento con los "frames" de la nave (192 – 199):

Asteroids - Frames explosión

Ahora hay que detectar las colisiones y reaccionar ante ellas. Pero lo primero es detectarlas. Para ello dotamos una nueva rutina "actualizaColisionesJugador", que deberemos llamar desde la actualización del jugador:

Asteroids - Actualiza colisiones jugador - Llamada

Y lo que hace la rutina "actualizaColisionesJugador" es más o menos sencillo:

Asteroids - Rutina actualiza colisiones

Es decir:

  • Lee el registro SPSPCL = $d01e, que es el registro que señaliza las colisiones entre sprites.
  • Analiza si el bit 0 de SPSPCL está activo. En caso de estar activo, ello significa que la nave (sprite 0) se ha visto involucrada en una colisión con otro sprite (necesariamente un asteroide, porque no hay más sprites).
  • En caso afirmativo, es decir, si la nave ha chocado con un asteroide, llama a la rutina "animaExplosion", que es la encargada de hacer la animación.

Por su parte, la nueva rutina "animaExplosion" de momento es sencilla. En entradas posteriores la complicaremos. Hace esto:

Asteroids - Anima explosión

Es decir:

  • Utilizando el registro Y como índice, va leyendo las entradas de la tabla "explosionFrames", es decir, va leyendo los punteros a los "frames" de la explosión ("lda explosionFrames,y").
  • Utilizando la rutina "configuracionBasica", va cambiando el puntero de la nave o, lo que es lo mismo, va cambiando su "frame". Esto mismo se podría hacer con un simple "sta SPRITE0" (SPRITE0 = $07f8).
  • Repite lo anterior hasta haber recorrido todos los frames de la animación.

Si probáis esto, veréis la animación de la explosión es prácticamente imperceptible. ¿Cuánto puede tardar un súper C64 en hacer un bucle de tres iteraciones y además en código máquina?

Total, tenemos que meter un bucle de demora como éste, ¿no?

Asteroids - Bucle demora

A estas alturas ya deberíamos saber que un bucle de demora como ese no funciona, porque no sólo ralentiza la animación / explosión, sino que ralentiza todo el juego. Ahora parece que el juego se engancha en la explosión:

Asteroids - Explosión enganchada

La solución es la misma que aplicamos a la nave y los disparos: un retardo para la explosión. Es decir, una nueva variable "jugadorRetardoExplosion" que, partiendo de un valor N (típicamente 5), va descontando uno en cada iteración del bucle de juego, y, cuando llega a cero, produce el cambio de "frame", además de volver a ponerse al valor inicial N. Así hasta pasar todos los "frames" de la animación.

De este modo, la presencia en pantalla de cada "frame" de la explosión se prolonga durante N ciclos del bucle de juego, en vez de hacer pasar todos los "frames" (la animación completa) en un único ciclo. Y sin ralentizar nada más.

Lo anterior, a su vez, nos lleva a la conveniencia de definir una nueva variable "jugadorActivo" (el lector atento la habrá visto aparecer, aunque comentada, unas cuantas imágenes más arriba) que, además de ser análoga a "disparosActivos" o "asteroidesActivos", nos permitirá controlar si el jugador está vivo ($01), en cuyo caso hay que moverlo y actualizarlo, o si el jugador está explotando ($00), en cuyo caso sólo hay que animar una explosión.

Pero todo esto lo describiremos en detalle en la entrada que sigue, así que de momento comentamos el retardo, documentamos algunos comentarios, y nos despedimos hasta que podamos explotar en condiciones

🙂
.

Asteroids - Bucle demora comentado

En la versión 11 del proyecto podremos ver todo lo descrito.


Código del proyecto: Asteroids11


Programación Retro del Commodore 64


“Programación Retro del Commodore 64” es un blog sobre el hardware, el sistema operativo, y la programación del Commodore 64. Y más específicamente sobre programación en ensamblador.

Pretende ser un blog con información de calidad, y referencia en español de la programación retro de esta maravillosa máquina.