miércoles, 8 de julio de 2020

Desarrollo de Street Fighter 2 Champion Edition para C64. Parte 3: los sprites

Ahora sí, entramos en el desarrollo del juego puramente dicho. Street Fighter 2 es un juego de lucha uno contra uno que en el apartado de los sprites cuenta con varias peculiaridades: luchadores muy grandes, gran variedad de movimientos especiales o movimientos sobre el suelo muy suaves. A priori, plasmar todo esto en una máquina con las limitaciones del C64 se antoja imposible, pero sacrificando algunos aspectos se puede conseguir algo decente. Eso creo, vamos.

Al abordar los sprites de los luchadores estudié cómo los habían gestionado otros juegos similares para C64. Para poder explicarlo mejor he utilizado C64 Debugger, una potente herramienta que permite depurar la ejecución de un programa, así como ver el contenido de la memoria, los sprites, los bitmaps, etc.

Street Fighter 2 (1992, US Gold)
La conversión oficial utiliza hasta 4 sprites multicolor para cada luchador, 128 por luchador en total, que ocupan 8KB de memoria.
Hoja de sprites de Ryu/Ken en Street Fighter 2 de US Gold.

Para que se vean por pantalla utiliza un doble buffer en el que se copian los sprites de la postura actual. El doble buffer permite evitar glitches, ya que puede suceder que se muestren sprites a medida que se actualizan. Con el doble buffer los punteros de los sprites apuntan siempre al buffer de sprites que ya ha sido copiado anteriormente, y se pueden copiar unos sprites mientras se muestran otros. Las diferentes alturas de cada luchador no se han respetado y por ejemplo Zangief es más alto que Chun Li.
Punteros a sprites en Street Fighter 2 de US Gold, se observa que en cada frame los punteros apuntan a direcciones diferentes de memoria (buffers).


Street Fighter versión EEUU (1988, Pacific Dataworks International)
La versión americana del videojuego de Capcom utiliza hasta 4 sprites por luchador pero en modo overlay, es decir, superpone sprites en alta resolución sobre sprites en baja resolución, lo que permite tener unos personajes coloridos y muy definidos, aunque de tamaño pequeño. El jugador 1, que siempre lleva a Ryu, tiene 136 sprites que ocupan 8,5KB de memoria. El jugador 2, por ejemplo Retsu, tiene 90 sprites que ocupan 5760 bytes.
Hoja de sprites de Ryu en Street Fighter versión EEUU.


En este caso también se usa el doble buffer explicado antes. Los luchadores tienen alturas similares, ya que son de un máximo de 2 sprites de alto.
Punteros a sprites en Street Fighter versión EEUU, en rojo los buffers de sprites.

Barbarian (1987, Palace Software)
Este caso es bastante peculiar: los personajes se dibujan directamente sobre el fondo bitmap y solamente se utilizan sprites para el chaleco del jugador 2, las manchas de sangre, la parte superior de los luchadores en algunos movimientos. Este sistema, aunque permite luchadores grandes (60 píxeles de altura en reposo, casi 3 sprites de alto), está implementado de forma que los movimientos son carácter a carácter, de 8 en 8 píxels, lo que provoca que los movimientos sean algo menos fluidos que en juegos que usan sprites y de la sensación de framerate bajo al no tener la misma fluidez. A pesar de esto, el juego es espectacular.
En los cuadros rojos están indicados los sprites de Barbarian. El resto de gráficos son bitmaps o caracteres.

IK + (1987, System 3)
El clásico de System 3 combina métodos vistos en los juegos anteriores: utiliza 12 sprites para 2 de los 3 luchadores, y el tercero lo dibuja en el bitmap como en el Barbarian. Para mostrar los sprites de los luchadores utiliza multiplexación, con la ventaja de que esos sprites siempre están alineados de 3 en 3, como se ve en la captura. Al no moverse los sprites verticalmente se evitan parpadeos. Todo esto proporciona una acción más fluida que en Barbarian y 3 personajes de gran tamaño en pantalla.
IK+, en rojo están marcados los sprites.


No he encontrado las hojas de sprites en memoria, así que imagino que estarán comprimidos. Al tener los 3 luchadores el mismo aspecto excepto por el color, con un bloque de sprites de un luchador se pueden dibujar los 3 personajes en pantalla, lo cual permite ahorrar mucha memoria.

En el caso de mi juego, inicialmente hice pruebas con sprites en alta resolución, pero lo descarté pronto por varios motivos:
  • Los luchadores aunque detallados, se veían muy pequeños, más o menos del tamaño de los del Street Figher USA.
  • Todos los personajes tendrían una altura similar, y así no podría respetar las proporciones entre luchadores, algo imprescindible.
  • Para implementar luchadores más altos tendría que utilizar más memoria por luchador y un multiplexador, y lo primero habría hecho más difícil programar la versión disco.
  • La implementación de los movimientos de miembros estirados de Dhalsim se complicaría considerablemente y se necesitaría usar multiplexación para un resultado óptimo.
Prueba de Ken en modo overlay.


Al final me decanté por una solución similar a la del Street Fighter 2 de US Gold: usar 4 sprites multicolor por luchador sin multiplexación pero respetando las dimensiones y proporciones de cada personaje. La "hoja de sprites" de un luchador contiene 128 sprites que ocupa 8KB de memoria. Así, los sprites de los 2 luchadores ocupan 16KB de memoria. En el VBANK (banco de memoria de vídeo) reservo un espacio de 512 bytes para copiar los 8 sprites de ambos luchadores. Con este uso de la memoria me queda espacio para el código, el bitmap del escenario, música y fx, y puedo hacer versiones en disco y cartucho.
Hoja de sprites de Ken (versión anterior).


Como curiosidad, inicialmente implementé un doble buffer como en otros títulos, pero al final he dejado de usarlo porque no lo necesito.

En el siguiente artículo os explicaré la conversión de los sprites originales y cómo el juego gestiona el pintado de los mismos. Si tenéis otro punto de vista sobre lo que he explicado aquí o si queréis comentar cualquier cosa sobre esto, me encantaría leeros en los comentarios.


Saludos, Paco.