Autor Tema: Crazy Balloon para C-64  (Leído 2045 veces)

josepzin

Crazy Balloon para C-64
« en: Octubre 17, 2013, 04:59:56 »
dancresp ha publicado un "despiece" de este juego en el foro de Zona de pruebas: Crazy Balloon para C-64

Se pueden descargar el ejecutable y código fuente desde los archivos adjuntos, pero si quereis estar seguros de tener la última versión mejor vais al enlace ZdP.



EL JUEGO
Este videojuego arcade fue desarrollado por Taito en 1980.

En este juego de habilidad debemos controlar un globo desde un punto inicial a un punto final, evitando tocar los distintos obstáculos del laberinto. Obtenemos puntos en función del tiempo invertido en completar el recorrido.

Controles:
Utiliza el joystick en el puerto-2 para controlar el globo.
Pulsa el botón para iniciar la partida.


BLOQUES
Se ha dividido el listado en 9 bloques:
- Declaración de las matrices. Llamada a rutinas principales.
- Control de nuestro globo: posición, animación y llegada a la meta. Descontar tiempo.
- Perder una vida / Fin juego.
- Pasar nivel y sumar puntos.
- Pantalla de presentación.
- Poner el laberinto en pantalla y posicionar el globo.
- Inicializar variables, matrices y SPRITES.
- Rutinas varias.
- DATA con los datos de los SPRITES, relación globo/cordel, posiciones de inicio y final del globo, y obstáculos extra.


COMO FUNCIONA
Todo el programa ocupa 109 líneas.

A continuación indico el principio de las distintas partes del programa:
10 - Definimos las matrices del juego.
50 – Llamada a la rutina (3000) que carga los SPRITES y inicializa variables y matrices.
80 – Vamos a la presentación del juego.
100 – Guardamos la variable TIME en F, descontamos el tiempo (T) y leemos el estado del joystick.
105 – Movemos el globo en función de la posición del joystick.
125 – Control de la animación del globo y cálculo de la posición del globo relativa al cordel.
150 – Controlamos que el globo haya llegado a la zona de la meta.
190 – Estabilizamos la velocidad del tiempo calculando el tiempo transcurrido desde la línea 100.
195 - Si los SPRITES no ha colisionado con nada vuelve a 100.
200 - Ponemos el color de los SPRITES a gris y reproducimos un sonido (5400)
205 - Se descuenta una vida y se borra del marcador.
250 - Final de partida. Se muestra un texto y se hace una pausa antes de volver a la presentación.
300 - Al pasar de nivel reproduce un sonido.
305 - Se incrementa el número de nivel (NN) y el de laberinto (N), volviendo a 1 si es mayor de 3.
310 - Se suman puntos en función del tiempo invertido y se muestran en el marcador.
2000 – Pantalla de presentación del juego.
2030 – Queda en espera hasta pulsar el botón del joystick del puerto 2.
2200 - Muestra la pantalla que indica el nivel y hace una pausa.
2500 – Rutina que se encarga de mostrar el laberinto en pantalla.
2550 - Si el nivel > 3 pone los obstáculos extra.
2600 - Posiciona el globo en la posición de inicio del nivel.
3000 - Cambia los colores de pantalla.
3005 - Carga los SPRITES desde las líneas DATA que empiezan en 9000.
3010 - Rellena de 0 los últimos 5 filas de cada SPRITE.
3015 - Inicializa variables que referencian a los POKE más usados.
3020 - Se guardan en la matriz B$ los distintos segmentos que forman los laberintos.
3040 - Cargamos distintas matrices: Posición globo, puntos de inicio/fin y obstáculos extra.
3060 - Inicializamos las posiciones del chip de sonido.
3100 - Inicializamos la matriz B$ con los datos de los 3 laberintos.
5000 - Rutina que muestra la pantalla de asteriscos con un espacio en el centro.
5050 - Rutina que colorea un asteriscos aleatorio de la pantalla.
5100 - Rutina de borrado de la pantalla.
5200 - Rutina LOCATE. CY=Fila, CX=Columna, T$=Texto.
5300 - Rutina USING para los marcadores. F=valor a mostrar.
5400 - Rutina de sonido. Reproduce 3 tipos de sonido. 1=Inicio, 2=Fin y 3=Pinchazo.
9000 - DATA con los datos de los SPRITES en formato de 16x24 pixels.
9500 - Posiciones del globo respecto el palo en función de la animación (A).
9510 - Posiciones Inicio horizontal/vertical y Final horizontal/vertical según el laberinto (N).
9600 - Posiciones de los obstáculos extra en función del nivel (NN) y laberinto (N).


APUNTES FINALES
Si hay lenguajes de programación orientados a objetos, el C-64 tiene un lenguaje BASIC orientado a POKES.

Este detalle y el engorro de conocer tanta dirección ha sido el que ha hecho que nunca me decidiera a programar nada para él.

Por otro lado, sabía que su BASIC era muy limitado, pero al intentar programar una versión del “JawBreaker” descubrí que también es muy lento, y esto limita el desarrollo de cualquier juego que se quiera hacer, ya que, simplemente, no tira.

Así que me decidí ha hacer una versión de un juego que siempre me ha gustado y que en el fondo es muy simple. Solo hay que controlar el globo, y aprovechar la capacidad del hardware para detectar la colisión de un SPRITE con cualquier cosa que haya en pantalla.

Este es mi primer programa con el C-64 y la verdad es que el reto ha sido muy interesante, la experiencia bastante decepcionante y el resultado muy satisfactorio.

Es una lástima que tan buen hardware vaya acompañado de un BASIC tan cutre.

Principales descartes respecto al original:
- Como el juego original es vertical, he colocado los marcadores a la derecha.
- En la versión original los laberintos son 26x26 caracteres, pero aquí han quedado de 25x26. He optado por eliminar una fila poco significativa. Tampoco aparece el marco gris.
- No hay elementos móviles o scroll en varias direcciones. Me he limitado a poner obstáculos extra.
- No hay zonas con puntuación variable. Aquí solo se puntúa al finalizar el nivel, en función del tiempo.

Por el resto, creo que se ha respetado la filosofía general del juego al 100%.



Sorteando las complicaciones
Con un BASIC tan limitado, casi cualquier paso que das requiere documentarte a fondo para saber como hacerlo, lo que por norma general significa conocer distintas direcciones de memoria para definir, mover o ocultar los SPRITES, cambiar colores, leer el joystick, acceder a la memoria de video, gestionar el sonido, etc. Números y más números que hacen que sea un engorro hacer nada con él.

El C-64 permite usar hasta 8 SPRITES de 21x24 pixels, pero aquí necesitaba llegar a los 26x24, con lo que me he visto obligado a dividir el globo en dos partes. Un SPRITE es la esfera del globo, y después hay 7 SPRITES más con las distintas animaciones del cordel. Mediante las matrices DX y DY se en todo momento donde hay que situar el globo respecto al cordel.

Para reducir código y teniendo en cuenta que el globo está partido en dos partes, los 8 SPRITES que he definido son de 16x24 pixels, y las últimas 5 filas de cada uno las relleno con un bucle y así no ocupan espacio en los DATA.

Por otro lado, como no hay una posición fija donde colocar los SPRITES, he aprovechado los últimos bytes de los primeros 16KB ara alojarlos allí (a partir de 15616), teniendo en cuenta que el VIC “crea” una paginación mediante bloques de 64 bytes para identificarlos con un valor entre 0 y 255. Y como cada SPRITE ocupa 63 bytes, se “pierde” un byte en cada uno.
Si el programa fuera más largo, el código BASIC sobrescribiría los datos de los SPRITES y si se ejecutara el programa al definir los SPRITES se sobrescribiría el propio programa en BASIC.

El control del globo tiene que ser muy preciso, y me he decidido a controlarlo con el joystick en el puerto 2. En la posición de memoria 56320 hay el valor del estado.

El movimiento del globo se realiza de 2 en 2 pixels. Por un lado el movimiento es suave, pero por el otro puede dar la sensación que es lento. El balanceo del globo ayuda a evitar esta sensación.

Para detectar las colisiones he aprovechado las facilidades que ofrece el hardware, ya que cuando un SPRITE toca un pixel de cualquier cosa que hay en pantalla, la posición 53279 tiene un valor distinto de 0. En si, cada bit de esta posición de memoria corresponde a la colisión de uno de los 8 SPRITES que puede manejar. También permite controlar la colisión entre SPRITES pero para este juego no ha sido necesario.

Y para facilitarme las cosas, he desarrollado una serie de rutinas que me permiten hacer borrados de una parte de la pantalla, imprimir valores numéricos en una posición indicada rellenando con 0 a la izquierda, o imprimir un texto en una posición de la pantalla

Para mejorar el rendimiento he guardado el valor de ciertos POKE en variables, ya que el C-64 es más rápido accediendo al valor de una variable que reconociendo un valor directamente. Así, las principales direcciones que manipulo están almacenadas en variables.

Para conseguir una velocidad constante he usado la variable de sistema TIME. En 100 me guardo el valor en T y en 190 compruebo si se ha modificado el valor en 7, esperando en caso negativo.

Respecto al sonido, he estado haciendo pruebas y he visto que es muy potente, pero como soy un inútil y es el tema que menos me gusta me he limitado a cumplir el expediente. Simplemente algo suena. De todas formas, nuevamente el hecho de tenerlo que hacer todo a base de POKES no ayuda.

El laberinto
En el juego hay 3 laberintos distintos de 25x26 caracteres. A lo bruto esto supondría que cada pantalla ocupara 650 bytes más el código BASIC necesario para visualizarlos. Yo he optado por codificar los datos y he conseguido dejar las distintas pantallas en unos 100 bytes.

Teniendo en cuenta que la pantalla es, básicamente una sucesión de tiras de asteriscos o de espacios en blanco, y que cada fila tiene 26 columnas... que coincide con el número de letras, las pantallas se definen con una sucesión de letras, que sucesivamente y alternativamente imprimen asteriscos o espacios en blanco en función del valor de la letra.

Se ha seguido esta codificación:
- Las letras corresponden a un número. Así, la A=1, F=6, M=13, T=20 y Z=26, por ejemplo.
- “0” indica el final de la fila.
- “*” cambia el carácter a imprimir, ya que a veces una fila empieza con asteriscos y otras con espacios.
- “3” a “9” se usan para mostrar los distintos fragmentos de la salida y la meta. Están guardados en la matriz B$.

Así, con la sencilla rutina que va de las líneas 2500 a 2545 se imprime el laberinto correspondiente de una forma razonablemente rápida.

Y entre 2550 y 2570 hay otra sencilla rutina que se encarga, a partir del nivel 4, de poner obstáculos extra en el laberinto para complicar el recorrido. Hay un total de 4 variantes por laberinto, que son acumulativos. Esta información se guarda en la matriz O$ con un formato de grupos de 2 letras. Cada letra corresponde a la posición “Y” y “X” de cada asterisco extra.

A destacar que la zona de juego ocupa 34 caracteres, con dos columnas vacías a derecha, izquierda y entre el laberinto y los marcadores.

Conclusiones
El C-64 es uno de los sistemas más farragosos de programar debido a un BASIC muy simple, que obliga a usar los POKE para todo, incluso para cosas tan simples como cambiar el color de fondo de la pantalla. Si a esto le añadimos que es muy lento en general y tratando números en particular, el cóctel es decepcionante.

Así:
He programado el VIC-20, que tiene un mal BASIC y no permite usar SPRITES.
He programado el C-64, que tiene un mal BASIC y permite usar SPRITES.
He programado el C-16, que tiene un buen BASIC y no permite usar SPRITES.
Falta programar el C-128 que tiene un buen BASIC y permite usar SPRITES. A ver que sale...


Para terminar, decir que el programa ha sido desarrollado íntegramente en un C-64 real y un Datassette.
La imagen del disquete se ha pasado a tarjeta SD y al PC posteriormente mediante un interface 1541-III.
Posteriormente he usado el “PRG Starter” junto con el VICE para extraer el “.PRG”, y el “Commodore Program Studio” para obtener el listado.


Pues nada más, solo me queda esperar que os guste.

Os invito a probarlo.

« última modificación: Octubre 17, 2013, 05:08:38 por josepzin »
 

Bieno

Re:Crazy Balloon para C-64
« Respuesta #1 en: Octubre 17, 2013, 08:33:03 »
Pues habrá que probarlo  :)
 

Baron Ashler

  • Desarrolladores
  • Commodorero
  • ******
  • Mensajes: 40
  • SHIFT+RUN/STOP
    • Ver Perfil
    • Kabuto Factory
Re:Crazy Balloon para C-64
« Respuesta #2 en: Octubre 21, 2013, 13:53:42 »
Buenas  :)

Acabo de probarlo y me quito el sombrero ante dancresp. Va muy bien y es calcado a la recreativa original  8)

Estoy de acuerdo con él en que el basic del C64 es un poco farragoso a la hora de comenzar, pero a poco que lo domines resulta bastante satisfactorio ;) ... eso si, velocidad no mucha, la verdad... como prueba mi primera versión de A.R.C.O.S. que pulula por ahí, que va a cosa de 1 frame por segundo. Si quieres velocidad tienes que tirar de compilador, cosa que he hecho para la segunda versión que ya va en camino :D ... al final, he conseguido hacer una ñapa para que el Blitz Compiler se trague mi código y ahora va el juego que se las pela  ;D