Artículo de Dani Crespo publicado en RetroWiki. Adaptado y publicado por Konamito.
En esta entrega vamos a ver como montar el nudo de desarrollo y como se controlan los enemigos del juego.
Algunas rutinas han sufrido algún cambio para optimizar el código, que a su vez, incrementa su velocidad. Algunas pierden en claridad pero ganan en velocidad y reducen la memoria que ocupa el juego.
Como veremos, las principales rutinas se han puesto al principio del programa, ya que el intérprete BASIC las encuentra más rápidamente al hacer un GOTO o un GOSUB, y por consiguiente aumenta la velocidad.
NUDO PRINCIPAL DE DESARROLLO
Desde la línea 10 hasta la 600 se ha montado el nudo principal de desarrollo, que es el lugar desde donde iremos llamando al resto de rutinas.
Funcionamiento del nudo
- 010 – Matriz de información de los enemigos. Esta línea solo se ejecuta una vez.
- 100 – Llamada a la subrutina (7000) que activa el SCREEN 1 y cambia los atributos de color de las letras y números.
- 110 – Llama a la subrutina (3000) que muestra la pantalla de instrucciones e inicializa algunas variables del juego, como el número de vidas o los puntos.
- 190 – Llama a la subrutina (7400) que imprime los marcadores de récord y puntos.
- 200 – Llama a las subrutinas que se encargan de cargar los gráficos del nivel (6000), sus atributos de color (6100), los gráficos de los enemigos (6200), su posición (6400) y la posición de la puerta de salida y el nombre de la pantalla (6600).
- 210 – Llama a la rutina (1000) que se encarga de mover a los enemigos.
- 220 – Resta el tiempo disponible para acabar el nivel. Si se acaba salta a la línea 400.
- 230 – Se borra el punto correspondiente en la barra de tiempo.
- 300 – Si se pulsa la tecla «Escape» sale del juego, saltando a la línea 500.
- 310 – Cierra el bucle principal volviendo a la línea 210.
- 400 – Se resta una vida (variable W), se reinicia el tiempo y si quedan vidas se salta a 200 para volver a cargar el nivel.
- 430 – Si no quedan vidas, se hace un bucle que se encarga de esconder a los SPRITES poniendo su posición vertical a 209.
- 460 – Final de la partida. Salta a 110 para volver a mostrar la pantalla de presentación.
- 500 – Aquí se llega al pulsar la tecla «Escape» y se llama a la subrutina (7200) que vuelve al modo texto en SCREEN 0.
- 600 – Para el programa en BASIC.
RUTINA DE PANTALLA DE PRESENTACIÓN
En la línea 3000 comienza la rutina que se encarga de mostrar la pantalla de presentación e inicializar algunas variables del juego. Como se puede ver, se ha puesto una simple, de ejemplo.
Las variables usadas son
- P – Puntos del juego.
- S – Record del juego.
- L – Nivel actual.
- T – Tiempo restante.
- W – Número de vidas de Willy.
RUTINA DE LOS MARCADORES
Esta rutina está ubicada en la línea 7400 y se encarga de mostrar el marcador de los puntos.
RUTINA DE CARGA DE ENEMIGOS
El MSX permite controlar hasta 32 SPRITES simultáneamente en pantalla.
Por un lado, en la VRAM hay una zona de 2048 bytes, comprendida entre la posición 14336 y la 16384, donde se pueden almacenar hasta 256 gráficos de 8×8 para ser usados en los SPRITES.
Por otro lado hay otra zona de 128 bytes, desde la posición 6912 a la 7039, donde se guarda la información de los 32 SPRITES, agrupando los bytes de 4 en 4. En ellos se va guardando la posición vertical, horizontal, gráfico del SPRITE y color.
Si el SPRITE es de 16×16, cada 4 gráficos consecutivos se considerarán un único gráfico, empezando por el superior izquierdo, inferior izquierdo, superior derecho y inferior derecho.
Codificación de los datos
Entre las línea 9015 y la 9022 se han introducido los gráficos del enemigo del primer nivel. Cada dos líneas contienen un gráfico de 16×16 con una de sus animaciones.
En la línea 9024 se ha introducido el número de enemigos y sus datos correspondientes, en grupos de 7 valores en el DATA.
Formato de la codificación
Controlar cada enemigo requiere 7 valores, con el siguiente formato:
1º- Color del enemigo.
2º- Posición inicial horizontal, en pixels.
3º- Posición inicial vertical, en pixels. Una forma de calcular el valor es: posición en caracteres * 8 – 1.
4º- Velocidad del enemigo en pixels. Se recomienda los valores 1, 2, 4, 8. Si el movimiento inicial es hacia la izquierda, el valor debe ser negativo.
5º- Posición mínima horizontal. Al llegar a este valor cambia su dirección hacia la derecha.
6º- Posición máxima horizontal. Al llegar a este valor cambia su dirección hacia la izquierda.
7º- Primera animación al aparecer. 0 si va a la izquierda y 8 si va a la derecha. Este parámetro se podría obviar.
Funcionamiento de la rutina
Esta rutina está ubicada en la línea 6400, y está preparada para mover a los enemigos horizontalmente. Cada enemigo dispone de cuatro animaciones, dos hacia la derecha y dos hacia la izquierda.
Los enemigos tienen un tamaño de 16×16 pixels, con lo que cada animación ocupa 32 bytes. Las cuatro ocupan un total de 128 bytes y se almacenan consecutivamente a partir de la posición 14336 de la VRAM.
En 6440, una vez cargados los gráficos, se lee de una línea DATA la cantidad de enemigos que se han de mostrar, y se almacena en la variable N, y a continuación va leyendo tantos grupos de 7 valores del DATA como indica N, y los va guardando en la matriz E. Al acabar coloca a los enemigos en su posición correspondiente pasando los valores a la VRAM.
Como ya tenemos los datos de los enemigos cargados, ahora toca moverlos.
RUTINA DE MOVIMIENTO DE ENEMIGOS
Si el MSX no tiene problemas para controlar hasta 32 SPRITES mediante programas en código máquina, al usar BASIC el número decae considerablemente. Así pues, en este programa el número máximo de enemigos a mover lo limita el tamaño de la matriz E, que debe ser un múltiple de 7. Ahora es 21, con lo que permite almacenar hasta 3 SPRITES. De todas formas, el BASIC no permite grandes alegrías, e intentar mover más producirá una perdida de rendimiento fatal.
Funcionamiento de la rutina
La rutina empieza en la línea 1000 y ocupa solo 13 líneas de código.
Vamos a ver como funciona:
- 1000 – Ponemos en la variable D el valor de VRAM donde está el primer SPRITE a controlar, y en la variable A el primer valor en la matriz E.
- 1010 – Inicio de un bucle que se repetirá tantas veces como enemigos marque la variable N.
- 1020 – Para evitar repetir sumas varias veces posteriormente, cargamos los resultados en varias variables. O – Dirección/Velocidad del enemigo, X – Posición horizontal, G – Animación actual. Para terminar, modificamos la posición horizontal del enemigo.
- 1030 – Si el enemigo se dirige a la izquierda, salta a 1060.
- 1040 – Si el enemigo llega a la posición horizontal máxima, invierte el valor de O, y en lugar de sumar, restará. Modifica la orientación de la animación (variable M).
- 1050 – Salta a 1070.
- 1060 – Si el enemigo llega a la posición horizontal mínima, invierte el valor de O, y en lugar de restar, sumará. Modifica la orientación de la animación (variable M).
- 1070 – Pone en el valor del SPRITE correspondiente la nueva posición horizontal.
- 1080 – Cambia la animación.
- 1090 – Pone en el valor del SPRITE correspondiente el gráfico a presentar. Con esto conseguimos la animación.
- 1100- Sumamos 4 a la variable D para apuntar al siguiente SPRITE, y sumamos 7 a la variable A para apuntar a los siguientes valores de la matriz E.
- 1110 – Si quedan más enemigos a mover, vuelve a la línea 1020.
- 1120 – Sale de la rutina y vuelve al nudo principal de desarrollo.
En la rutina, ciertas variables se tratan como valores enteros, poniendo un %, para acelerar los cálculos, ya que se realizan más rápidamente con números enteros que con números reales.
Ahora mismo solo aparece un enemigo en pantalla, como en el juego real, pero si sustituimos el valor 1 de la línea 9024 por un 2 y añadimos 7 valores, aparecerán dos enemigos.
Por ejemplo:
9024 DATA 2,11,93,55,2,71,127,9,4,93,23,1,71,127,9
Aparece un nuevo enemigo por encima del anterior moviéndose más lentamente.
RESUMEN Y COMENTARIOS
En este nuevo listado se han realizado algunos cambios destinados a mejorar el rendimiento del programa, como puede ser agrupar varias instrucciones en una misma línea, o a usar variables enteras en lugar de valores reales.
La rutina de movimiento ha sido depurada para conseguir el mejor rendimiento posible. Cronometro en mano, conseguí reducir de 10 segundos a 7 segundos el ciclo de recorrido de un enemigo.
Hasta ahora, tanto el aspecto gráfico como la velocidad del juego es igual al «Manic Miner» original. Queda la parte más compleja, tanto a nivel de programación como de rendimiento, que es la que corresponde a Willy, el protagonista. Esto lo veremos en la siguiente entrega.
Olvidé decir que por algún motivo que desconozco, pero comprobado en varios MSX, al usar el modo SCREEN 1 y ponerlo a 32 columnas, la de más a la izquierda queda recortada. Así, solo utilizo 31, con lo que el juego es 8 pixels más estrecho que el original.
El listado, provisional, de todo este montaje queda así.
Para terminar, todo este desarrollo se ha programado en un MSX-2 Philips VG-8235 y se ha probado en un Toshiba HX-10. El listado se ha impreso en una impresora matricial Brother M-1109. A lo retro, como dios manda.
que cracks!!! yo de crio soñaba con poder programar juegos en mi MSX2. con 8 años, lo maximo que conseguí fue un círculo que cambiaba de colores, y hacer una tubería o algo parecido…y bien orgulloso que me siento!!!