sábado, 2 de enero de 2021

Desarrollo de Street Fighter 2 Champion Edition para C64. Parte 4: más sprites

Antes de nada, feliz año nuevo a todos. Deseo que este 2021 que justo acaba de empezar sea mejor que el anterior, cosa no muy difícil, por otra parte. Este artículo debería haber sido escrito hace meses pero la vida real manda y obliga a relegar las aficiones a un segundo plano. En el artículo anterior os expliqué cómo tomé la decisión de emplear 4 sprites para cada uno de los luchadores sin recurrir a la multiplexación para hacerlos más grandes. También os comenté brevemente cómo organizo la memoria para visualizarlos, y a continuación voy a detallar este punto un poco más. Agarraos que vienen curvas...

Como os comenté anteriormente, la hoja de sprites (sprite sheet) de cada personaje ocupa 8KB. Para los que no conozcáis cómo ve la memoria de vídeo el chip VIC-II os lo resumo rápidamente: el VIC-II solamente puede "ver" a la vez un bloque de 16KB de memoria RAM como memoria de vídeo o Video-BANK/VBANK (4 bancos de 16KB = 64KB), que se selecciona modificando unos bits en una dirección de memoria. En ese bloque de memoria RAM, en ese VBANK, se deben colocar todos los elementos gráficos que deseemos que se muestren excepto el mapa de colores o color ram, que siempre se almacena en las direcciones $d800-$dbe7: datos bitmap (bitmap ram), juego de caracteres (custom charset), mapa de caracteres en pantalla (screen ram) y sprites.

Los 4 VBANKs del VIC-II (imagen de Dustlayer, sitio muy recomendable).


Si un personaje necesita 8KB, dos necesitan 16KB, por lo que de copiarlos por completo en el VBANK lo ocuparían por completo y no dejarían espacio para la información del fondo bitmap, aparte de glitches varios que generaría esta situación. Por ello hay que recurrir al uso de buffers: los 16KB de los sprites se almacenan fuera del VBANK actual y únicamente se copian en el VBANK aquellos sprites que se deban mostrar en un momento determinado. Como cada sprite ocupa 64bytes y cada personaje necesita hasta 4 sprites para ser mostrado en pantalla, reservo un hueco de 512bytes en el VBANK (64 x 4 x 2 = 512) para copiar los sprites de los personajes a medida que los voy necesitando. La copia se hace durante ciclos posteriores a pintado de los sprites (para no producir glitches) y en frames alternos, es decir, en un frame copio los del jugador 1 y en el siguiente los del jugador 2, ya que el copiado requiere de muchos ciclos y me es imposible hacer ambas copias en un solo frame. De hecho es lo mismo que se hace en Street Fighter (EEUU) y Street Fighter 2, por poner dos ejemplos cercanos.

Mapa de memoria del C64 (imagen de The VMD Project).

 

¿Y cómo le digo al C64 dónde están los sprites de una posición de un luchador y en qué coordenadas hay que pintarlos? De forma muy resumida, para lo primero tengo, para cada personaje, un fichero que contiene varias líneas como esta, una por cada posición:

; Fichero de posiciones/movimientos.

!byte 00, $60, $00, $62, $00, $64, $00, $ff, $ff    ; SP_POS_PIE

El primer byte indica el tipo de disposición de los sprites (0 = 3 en columna, 20 = 4 sprites en cuadrado, etc), y los 4 siguientes pares son las posiciones de memoria en las que están los sprites de la posición quieto de pie. En cuanto a las disposiciones, el programa tiene una tabla con líneas como esta:

; Tabla de disposiciones.

!byte 3, 24, 0, 0, 0, 21, 0, 42, 255, 255    ;3 sprites en columna

El primer byte indica cuántos sprites tiene la disposición, el segundo contiene información para pintar la sombra, y los 4 siguientes pares son las coordenadas X e Y respecto de la "posición 0" del personaje en las que se deben dibujar los sprites de la posición actual. Cuando un personaje se mueve, en función del movimiento se lee la línea correspondiente en el fichero de posiciones para averiguar desde dónde hay que leer los sprites. A continuación se copian los sprites en el buffer del VBANK, y por último se posicionan en pantalla (X, Y) tras leer las coordenadas relativas desde la línea concreta en la tabla de disposiciones.

Hoja de sprites o sprite sheet de Ken en Super Street Fighter 2 para SNES.

 

Bien, aclarado esto, paso a explicar cómo he convertido los sprites del juego original al formato de sprite del C64. De entrada he de decir que en realidad he convertido los sprites de la versión para SNES del Super Street Fighter 2 Champion Edition, ya que son muy similares a los de la versión arcade del SF2 y las sprite sheets están bastante completas. Como en el juego original los personajes tienen una cantidad de movimientos enorme, muy difícil de trasladar al C64 por restricciones de memoria, tuve que elegir una serie de movimientos básicos comunes a todos para convertirlos, y desechar el resto, de forma que el máximo de sprites por personaje son 128:

  • Quieto de pie (2 frames para la respiración).
  • Agachado.
  • Caminar (3 frames por ahora).
  • Salto vertical (2 frames).
  • Salto hacia adelante/atrás (2 o más frames).
  • Defensa de pie.
  • Defensa agachado.
  • Golpeado de pie.
  • Golpeado agachado.
  • Golpeado de pie con caída al suelo.
  • Golpeado en el aire.
  • Groggy (2 frames).
  • KO.
  • Puñetazo fuerte de pie, agachado y saltando.
  • Puñetazo flojo de pie, agachado y saltando.
  • Patada fuerte de pie, agachado y saltando.
  • Algunos movimientos especiales

Para convertir los sprites he usado el editor de imágenes Gimp y el editor de sprites SpritePad. El proceso de conversión de sprites de SNES a C64 fue el siguiente:

  1. Creo una imagen Gimp de 192x336 píxeles con guías verticales cada 24 píxeles y horizontales cada 21 píxeles. De esta manera delimito cada uno de los 128 sprites formato C64 (16 filas de 8 sprites). Esta imagen me sirve de plantilla para los demás personajes, y con ese tamaño puedo importarla posteriormente en SpritePad.
  2. Abro con Gimp la hoja de sprites original y selecciono un movimiento del personaje (por ejemplo, quieto de pie).
  3. Pego la selección en la imagen plantilla y borro la sombra.
  4. Como la selección pegada ocupa más de 4 sprites de C64, la escalo (reduzco su tamaño) hasta que ocupe un número de sprites razonable en función del tamaño original del personaje. Por ejemplo, Ken, Ryu, Chun Li o Sagat ocupan 3 sprites de alto en reposo, mientras que Honda ocupa 2 de alto por 2 de ancho. Tomo el tamaño de la cabeza en la posición quieto de pie como referencia para escalar el resto de movimientos.
  5. Si no puedo colocar la selección del movimiento de forma que sus sprites estén contiguos, recorto uno o más sprites y los coloco en otros huecos.
  6. Vuelvo al punto 2 hasta que completo toda la hoja de sprites y los pongo todos en una misma capa.
  7. Ahora toca convertir los coloridos sprites de SNES a los 3 colores del C64 (2 comunes + 1 propio). Para ello utilizo la herramienta de selección de color para pintar todos los píxels de la piel de color rosa, los de los bordes o pliegues de blanco, y los elementos del color propio (kimono, traje, calzón, etc) de azul.
  8. Convierto la imagen a formato bitmap.
  9. Abro SpritePad e importo la imagen bmp.
  10. Selecciono todos los sprites y cambio el color blanco por el negro y el color azul por el propio del personaje.
  11. Procedo a retocar y repintar cada uno de los sprites hasta obtener un buen resultado.

 

Como podéis ver, es un proceso algo complejo en el que los personajes pierden muchos detalles y hay que elegir cuidadosamente qué se deja fuera sin que el personaje pierda personalidad y sea reconocible dentro de las limitaciones del C64. En la próxima entrega os explicaré más cosillas sobre el desarrollo...


Saludos.


No hay comentarios:

Publicar un comentario