En esta publicación, profundizaremos en cómo funcionan las animaciones de la superficie del agua en nuestro juego de NES de 8 bits Böbl.
Seguramente este tiene que ser el detalle técnico más interesante de Böbl, ya que es algo que nunca antes se había visto en NES.
ROM versus RAM para gráficos
En NES, tienes la opción de equipar tu cartucho con un chip ROM o RAM para gráficos. Estos se denominan CHR ROM y CHR RAM respectivamente.
ROM CHR
Ventajas:
- No es necesario almacenar los gráficos en la ROM del programa, lo que deja más espacio para el código y otros datos, es decir, más contenido del juego.
- Con un asignador de memoria como MMC3, puedes actualizar muchos mosaicos a la vez sin costo de CPU intercambiando bancos de CHR ROM
Contras:
- Por lo general, estás limitado a solo un par de fotogramas de animación predefinidos.
Mega Man 5 utiliza la conmutación de bancos CHR ROM para animar una gran cantidad de mosaicos.
CHR RAM
Ventajas
- Puede modificar mosaicos gráficos individuales durante el tiempo de ejecución, es decir, dibujar sobre ellos o reemplazarlos.
- Animaciones muy fluidas y fáciles de lograr.
- Permite efectos gráficos novedosos.
Contras
- Los gráficos deben almacenarse en la ROM del programa antes de cargarse en la RAM CHR, por lo que es posible que tengas que sacrificar el contenido del juego.
- Las actualizaciones de mosaicos requieren la participación de la CPU, por lo que existe un límite severo en la cantidad de animación que puedes tener al mismo tiempo.
El juego de NES Battletoads utiliza CHR RAM para crear efectos gráficos interesantes, como los bordes de la pantalla que se desplazan verticalmente a una velocidad más rápida.
Aquí hay un primer plano del contenido de CHR RAM:
Battletoads updates CHR RAM to achieve fluid parallax scrolling.
Pasemos a otro ejemplo:
Contra... también conocido como Probotector si eres de Europa, como nosotros
Si solo necesita actualizar unos pocos mosaicos, gana CHR RAM porque la conmutación de bancos de CHR ROM solo funciona en fragmentos de 1 KB, por lo que desperdiciaría mucho espacio duplicando gráficos.
Más importante aún, aquí puedes ver por qué las animaciones de fondo son útiles:
Si bien sería mucho más fácil usar sprites para una barrera eléctrica animada como esta, si intentas alinear más de 8 sprites horizontalmente en la NES, los que sobran desaparecen, lo que los juegos intentan eludir usando el infame parpadeo de sprites.
Sin embargo, para los mosaicos de fondo, ¡no existe tal límite! Todo parece estar bien.
Animando la superficie del agua.
Como se indicó anteriormente, la cantidad de actualizaciones de gráficos que la NES puede realizar por cuadro es muy limitada.
Una pantalla en Böbl puede tener un máximo de 32 mosaicos de superficies de agua animadas. Esas son las dos filas inferiores de mosaicos en el lado derecho (CHR RAM) de esta imagen:
¡Y también hay animaciones de cascada independientes ejecutándose en todo momento!
Para alcanzar este número de actualizaciones de mosaicos, utilizamos dos trucos:
La mitad de los colores.
El formato gráfico de 4 colores (2 bits) de la NES utiliza 16 bytes por mosaico de 8x8 píxeles. Los mosaicos de superficie de agua de Böbl usan solo 2 colores (1 bit), lo que significa que podemos actualizar solo 8 bytes por mosaico.
La mitad de la velocidad de fotogramas
Las actualizaciones se alternan: 16 mosaicos en cuadros pares y los otros 16 en cuadros impares. Esto significa que la animación de la superficie del agua se ejecuta a 30 fps mientras que el resto del juego se ejecuta a 60 fps. Afortunadamente, todo todavía parece fluido (nunca mejor dicho).
A continuación, veamos cómo funciona la simulación de la superficie del agua:
Piense en una superficie de agua como una secuencia de puntos. Cada uno describe el nivel del agua en una posición x determinada.
Cuando un objeto golpea la superficie del agua, la velocidad vertical de uno de esos puntos cambia y efectivamente oscilará hacia adelante y hacia atrás alrededor del nivel de la superficie. Con el tiempo, el nivel del agua se propagará a puntos adyacentes, perdiendo impulso en el proceso. Con el tiempo, todos los puntos volverán a formar una superficie quieta.
Lograr esto de manera convincente requeriría bastante memoria y matemáticas, posiblemente incluyendo divisiones, que son extremadamente lentas en la pobre CPU de 8 bits alojada dentro de la NES.
Afortunadamente, la CPU funciona bien en sumas y restas. Entonces nuestra solución fue generar previamente la deformación del agua. Es decir, almacenamos los cambios causados en el nivel del agua como una especie de animación: una secuencia de números que le indican al juego cuánto debe subir o bajar el nivel del agua en un punto determinado, en un momento determinado.
Luego generamos los mosaicos gráficos a partir de los niveles calculados de todos los puntos de la superficie del agua con algún código ensamblador optimizado (haga clic si se atreve).
Incluso con todas estas optimizaciones, el juego utiliza entre el 40 y el 60 % de la CPU sólo para el efecto de deformación del agua.