Asteroids: movimiento de la nave con ángulo y velocidad #Programación retro del Commodore 64

Ahora vamos a cambiar el movimiento para que sea algo más complejo, y esté basado en un ángulo o dirección y una velocidad.

Por tanto, además de mantener las coordenadas X e Y, vamos a introducir variables nuevas en "Jugador.asm":

Asteroids - Variables angulo y velocidad

Como se puede observar, aparecen estas variables nuevas:

  • La velocidad del jugador ("jugadorVelocidad").
  • El ángulo del jugador ("jugadorAngulo").

Además, también aparece la tabla "jugadorFrames" que, más una variable, es una estructura de datos (una tabla) para obtener el puntero al "frame" correspondiente en función del ángulo actual. Así, al ángulo 0 le corresponde el puntero 192 que, como está expresado en bloques de 64 bytes, es la posición $3000. Y así sucesivamente: 192×64 = $3000, 193×64 = $3040, 194×64 = $3080, …

Téngase en cuenta que los "frames" de la nave se han cargado, precisamente, a partir de la dirección $3000:

Asteroids - Inc sprites jugador

Esto nos permitirá animar la nave, es decir, nos permitirá cambiar su "frame", en función del ángulo que, a su vez, dependerá de lo que marque el joystick 2.

Bueno, pues vamos al grano. Todo sigue básicamente igual salvo la rutina "actualizaPosicionJugador" del fichero "Jugador.asm". Sus principales cambios son:

  • La posición del joystick 2 no altera de forma directa las coordenadas X e Y, sino las variables ángulo y velocidad.
  • Al mover el joystick 2 a izquierda y derecha se modifica el ángulo; al moverlo arriba y abajo se modifica la velocidad.
  • La velocidad la vamos a limitar al intervalo 0 … 3. La velocidad es el número de pixels que se mueve la nave en cada ciclo del bucle de juego, de modo que más de 3 pixels por ciclo sería una velocidad demasiado rápida, descontrolada.
  • El ángulo lo vamos a limitar al intervalo 0 … 7, porque sólo manejamos ocho ángulos o "frames". Eso sí, después del 7 volvemos a pasar al 0, y al revés.
  • La nueva posición X, Y se calcula a partir de la posición actual, la velocidad y el ángulo. Dotamos para ello una rutina independiente, "calculaNuevaPosicion", porque hacer el cálculo directamente en "actualizaPosicionJugador" la complicaría demasiado.
  • Por supuesto, hay que actualizar la posición con la nueva posición X, Y de la nave. Esto no es nuevo. Pero, además, hay que actualizar su "frame" en función del ángulo. Para ello usaremos la tabla "jugadorFrames".

Y ahora vamos a destriparlo paso por paso:

Cambio en el ángulo y la velocidad:

Este código es esencialmente el mismo que ya vimos en la entrada anterior. La principal diferencia es que en vez de incrementar y decrementar las variables "jugadorX" y "jugadorY", incrementa y decrementa las variables "jugadorVelocidad" y "jugadorAngulo". Por tanto, no merece la pena volver a comentarlo en detalle.

Limitación de la velocidad al intervalo 0 – 3:

Para limitar la velocidad al intervalo 0 – 3 se utiliza este código:

Asteroids - Limitar velocidades

Es decir, si la velocidad es tan baja que ha llegado a 255 (téngase en cuenta que 255 es lo mismo que -1; recordar los números negativos), entonces la volvemos a poner a 0. Y si es tan alta que ha llegado a 4, la volvemos a poner en 3.

Y como la velocidad sólo se incrementa/decrementa de uno en uno, nunca de dos en dos o de de tres en tres, lo anterior impide que baje de 0 o que suba de 3.

Limitación del ángulo al intervalo 0 – 7:

El código es muy parecido al del apartado anterior:

Asteroids - Limitar angulos

La principal diferencia es que cuando el ángulo es tan bajo que llega a 255, es decir, a -1, volvemos a ponerlo en 7 (en vez de 0). Y cuando es tan algo que llega a 8, volvemos a ponerlo en 0 (en vez de en 7).

Por tanto, el ángulo no funciona con un tope inferior (0) y otro superior (7), sino que funciona "cerrando el círculo", pasando de 0 a 7 y de 7 a 0. Esto permite que la nave gire indefinidamente, bien en sentido horario o en sentido antihorario.

Cálculo de la nueva posición X, Y:

El cálculo de la nueva posición se hace en la rutina independiente "calculaNuevaPosicion" para no complicar demasiado la rutina "actualizaPosicionJugador".

La nueva rutina recibe como parámetros de entrada la posición X, Y actual, la velocidad y el ángulo, y devuelve como salida la nueva posición X, Y.

La rutina como tal es sencilla, pero un poco farragosa de implementar. Lo mejor es explicarla con una tabla:

Si el ángulo es Haz esto con X Haz esto con Y
0 grados, frame 0 Dejar X igual Decrementa Y en velocidad
45 grados, frame 1 Incrementa X en velocidad Decrementa Y en velocidad
90 grados, frame 2 Incrementa X en velocidad Dejar Y igual
135 grados, frame 3 Incrementa X en velocidad Incrementa Y en velocidad
180 grados, frame 4 Dejar X igual Incrementa Y en velocidad
225 grados, frame 5 Decrementa X en velocidad Incrementa Y en velocidad
270 grados, frame 6 Decrementa X en velocidad Dejar Y igual
315 grados, frame 7 Decrementa X en velocidad Decrementa Y en velocidad

Los incrementos se hacen con "adc" y los decrementos con "sbc", y hay que manejar bien el acarreo con "clc" (al sumar) y "sec" (al restar).

A modo de ejemplo, este es el fragmento de la rutina correspondiente a 225 grados:

Asteroids - 225 grados

Actualización del frame (animación):

Y lo último, además de actualizar la posición del sprite con la nueva X, Y, es actualizar el "frame" para que la nave apunte en la dirección correcta.

Esto lo hacemos con este código sencillo en la parte final de "actualizaPosicionJugador":

Asteroids - Actualizar frame

Es decir, se carga el ángulo en el registro X y, usando X como índice, se accede a la tabla "jugadorFrames" para obtener el puntero correspondiente al ángulo. Con este dato (y otros necesarios) se vuelve a llamar a "configuracionBasica".

Igualmente se podría haber hecho un simple "sta SPRITE0" para actualizar el puntero del sprite 0 (la nave), pero por aquello de hacerlo igual que en la inicialización del jugador, y por reutilizar algo de código, incurrimos en el pequeño sobrecoste de volver a activar el sprite y actualizar su color innecesariamente.

Resultados:

Los resultados pueden verse en el proyecto Asteroids02, que incluye unas pequeñas trazas en las posiciones de pantalla $0400 y $0401 para conocer la velocidad y el ángulo.

La nave acelera y frena sin problemas. También puede girar. Ahora bien, el giro es demasiado rápido; frenético. No hay manera de controlar esa nave. Ni el mismísimo Neil Armstrong soportaría esos giros.

Asteroids - Giros freneticos

En la siguiente entrada le buscamos una solución.


Código del proyecto: Asteroids02


Editar

Josepzin

No hay comentarios:

Publicar un comentario