Asteroids: movimiento sencillo de la nave #Programación retro del Commodore 64

Ya tenemos la nave en pantalla. Por tanto, ahora toca moverla con el teclado o con el joystick.

Nosotros lo haremos con el joystick 2 pero, como VICE simula el joystick con el teclado, en última instancia la nave se moverá con el teclado del PC (o joystick 2 del C64 si usáis hardware real).

De momento será un movimiento sencillo. Es decir, si el joystick apunta hacia arriba, la nave se moverá hacia arriba, si el joystick apunta hacia abajo, la nave se moverá hacia abajo, y así sucesivamente. Y sin cambiar de "frame".

Más adelante mejoraremos esto, de modo que al apuntar hacia arriba aceleremos la nave, al apuntar hacia abajo frenemos, y al apuntar hacia los lados giremos. Para esto hemos diseñado los ocho "frames".

Mover la nave ya forma parte del mundo de la actualización, no de la inicialización. Por tanto, nos vamos a la segunda parte del fichero "Asteroids.asm", al bucle de juego:

Asteroids - Bucle de juego

Ahí aparecen básicamente cuatro cosas:

  • Que esperamos hasta que el Raster esté en la línea 255.
  • Que leemos el joystick 2.
  • Que actualizamos el jugador, es decir, lo movemos.
  • Y que volvemos a empezar. Por eso es un bucle.

Quitando el último punto, que es sencillo, lo demás requiere una explicación detallada:

Raster:

El Raster ya sabemos lo que es. Es el rayo con el que el C64, y más concretamente el VIC, va refrescando la pantalla, de arriba abajo y de izquierda a derecha.

El VIC hace esto a la vez que el 6510 ejecuta el programa. Es decir, son procesos que se ejecutan en paralelo. Por tanto, si no los sincronizamos de algún modo, las actualizaciones que el 6510 haga en la pantalla (contenido de la RAM de vídeo, contenido de la RAM de color, sprites, etc.), pueden caer a mitad de un refresco de la pantalla, lo que puede hacer que la actualización no sea limpia, con fluctuaciones.

Por ello, para evitar el parpadeo, se suelen hacer las actualizaciones de pantalla cuando el Raster está fuera de la misma, por ejemplo, en la línea 255. Recordemos que se puede leer en memoria por qué línea va el Raster; y también se puede configurar una interrupción cuando el Ráster llega a una línea X.

Esta medida (esperar a que el Raster esté fuera de pantalla) lleva asociada una cuestión implícita, que conviene aclarar: esto se puede hacer siempre y cuando todo lo que tiene que actualizar el programa, es decir, todos los ciclos de reloj que consume, quepan en un refresco del Raster. Si esto no fuera así, es decir, si el programa fuera tan complejo que todo lo que tiene que ejecutar no cabe en un refresco del Raster, habría que estudiar qué hacer.

Para esperar a que el Raster esté en la línea 255 utilizamos la rutina "meteRetardoRaster" de la librería "LibTemp". Esta rutina se limita a esperar a que el Raster ($d012) llegue a la línea indicada.

Joystick:

El joystick también sabemos lo que es y cómo funciona. Lo vimos en las entradas dedicadas a entrada/salida, más concretamente al CIA1.

Para leer el joystick 2 utilizamos la rutina "leeJoystick2" de la librería "LibJoy", que básicamente se limita a leer el puerto CIAPRA ($dc00) y depositar su valor en una variable ("joy2"). Posteriormente, en función del valor de esa variable, se toman las decisiones de movimiento.

Actualización del jugador:

Y por fin llegamos al objeto principal de la entrada: el movimiento.

En primer lugar, cabe decir que, de momento, actualizar el jugador sólo consiste en moverlo. Pero más adelante habrá que hacer más cosas (disparos, colisiones, etc.). Este es el motivo por el que aparecen dos rutinas ("actualizaJugador" y "actualizaPosicionJugador"):

Asteroids - Actualizar jugador

La primera rutina ("actualizaJugador") se irá completando con más cosas según avance el desarrollo. Y la segunda rutina ("actualizaPosicionJugador") es la rutina de movimiento propiamente dicha:

Asteroids - Mover jugador

Esta rutina sigue la misma estructura para cada uno de los cuatro movimientos posibles (arriba, abajo, izquierda y derecha):

  • Carga una máscara en el acumulador (ej. #Arriba).
  • Hace el AND del acumulador/máscara y el valor leído del joystick 2 ("joy2"). Este AND se hace con la instrucción "bit", es decir, no nos interesa tanto el resultado del AND como los flags que activa.
  • En caso de que no se active el flag Z (instrucción "bne"), salta al siguiente paso y no hace nada más con el paso actual.
  • En caso de que sí se active el flag Z, incrementa o decrementa la variable correspondiente con la coordenada X o Y del jugador ("jugadorX" o "jugadorY").

Por último, para que el cambio en las variables sea efectivo, se vuelve a posicionar el sprite de la nave en pantalla:

Asteroids - Reposicionar jugador

¿Resultado? La nave se mueve arriba, abajo, a izquierda y derecha, en función del joystick 2. Eso sí, de momento no cambia su "frame"; siempre es el mismo.

Ah, y otra cuestión importante. De momento el movimiento en el sentido X se limita a las coordenadas 0 a 255. Más adelante habrá que mejorar esto, ya que ya sabéis que el movimiento en sentido X admite nueve bits (SP0X y el bit 0 de MSIGX).


Código del proyecto: Asteroids01


Editar

Josepzin

No hay comentarios:

Publicar un comentario