Aventuras en Megadrive: Deconstruyendo Escenarios
Este es el fondo original del primer nivel de Hijos de Camelot. Nada más comenzar, el escenario cambia de color, anochece.
4 imágenes, resolución: 320x240px, profundidad de color: 32bits
Vamos a adaptar este escenario a la Megadrive. Recordemos las cosas a tener en cuenta:
- La resolución debe ser 320x224px.
- La profundidad de color debe ser 4bpp / 16 colores por plano (hasta 32 colores usando planos A y B para representar un fondo).
- Debemos dibujarlo con el menor número posible de tiles.
- Hay un cambio de colores día-noche que debemos reflejar.
Resolución
Voy a recortar por abajo, dónde se encontraban los controles en pantalla. No tiene mayor misterio. Paso de 320x240px a 320x224px.
Profundidad de Color
El fondo es poco colorido, por lo que en principio parece sencillo. Tenemos que reducir la profundidad de color. Lo más sencillo es usar nuestro programa de dibujo favorito para que reduzca los colores, pero puede que el programa escoja colores no adecuados, en dicho caso habremos de editar previamente la imagen y cambiar los colores nosotros mismos.
En mi caso, utilizo GraphicsGale, un programa sencillo de usar, portable y gratuito.
GraphicsGale > Image count colors
Paint Shop Pro 7 > Colores > Contar colores
La primera imagen (de las 4 de arriba) tiene 354 colores. Vamos a reducir la profundidad de color.
GraphicsGale > All Frames > Color Depth > 4bpp / 16 colors (dither desactivado)
En el caso de la primera imagen, usando cualquiera de los dos programas en general queda bastante bien, pero en la paleta quedan muchos tonos de marrón. Lo ideal sería hacerlo a mano para tener más tonos de otros colores, no obstante lo voy a dejar así porque no queda del todo mal.
Nota: Si usamos Paint Shop Pro 7, entonces Disminuir Colores > 16 colores (Color más cercano)
Recordar que podemos usar 32 colores. MD soporta 16 colores por capa.
Así que teóricamente podemos dividir la imagen de fondo en 2, limitar a 16 colores cada imagen y tener 32 en total.
Esto lo veremos más adelante pues no es sencillo de resolver a man.
Contando Tiles
¿Cuántas tiles ocupa una imagen usada de fondo?
Una forma rápida de saberlo es usar ImaGenesis. Este programa entre otras cosas permite contar tiles: analiza una imagen y calcula cuantos tiles se necesitan para mostrarla. Aproximadamente es lo que hará el SGDK, nos vale para hacernos una idea.
2 pasos:
ImaGenesis > Mode > 15 colors, 4bpp….. Optimized +
ImaGenesis > Actions > Quantize Now
Para la primera imagen cuenta 530 tiles distintas. Recordemos que, para cada plano, podemos tener hasta 4096 tiles, por tanto no vamos mal.
De forma visual podemos hacer un programa nuevo y sólo cargar dicha imagen. Podemos ver cuantas tiles ha ocupado la imagen usando GensKmod (CPU / Debug / Genesis / VDP). Ahora haz click en la última tile y en Offset te aparecerán cuantos tiles ha ocupado la imagen. Recuerda que si has utilizado TILE_USERINDEX para reservar los primeros 16 tiles, entonces resta 16 al total de tiles para saber cuántos ocupa la imagen.
Finalmente y por supuesto también se puede contar con una variable desde dentro del programa y sacar su valor. Esta es la forma más exacta.
KLog_S1("num de tiles del fondo:", mi_imagen.tileset->numTile);
En este caso el valor es 528 tiles. Si recuerdas, ImaGenesis daba 530 tiles.
Explico el uso de KLog_S1 en la entrada dedicada a debug.
Por supuesto, lo ideal sería rehacer la imagen desde 0 para ocupar el mínimo de memoria posible, no obstante en mi caso no lo voy a hace ya que no tengo mucho tiempo libre y me sobra VRAM. Como se puede ver, estoy desperdiciando mucha memoria, si fuese un proyecto serio esto no sería aceptable.
Anochece
En vez de retocar el resto de imágenes, y ocupar memoria tontamente, voy a cambiar la paleta de la fondo para simular el anochecer.
- El cielo el azul pasará a un naranja y de ahí poco a poco a negro.
- El verde de los matorrales, los voy a cambiar a marrones.
- En la muralla, cambiaré los rojos a tonos más oscuros.
Voy a usar la función VDP_setPaletteColor()
VDP_setPaletteColor(color_a_cambiar, RGB)
El primer parámetro es el índice del color de todas las paletas de MD (0-63). Recordar que la primera paleta va del 0 al 15, la segunda del 16 al 31, etc.
El segundo parámetro es el color en formato RGB. Recuerda usar RGB24_TO_VDPCOLOR()
Para escoger color, esto nos puede ayudar:
https://www.w3schools.com/colors/colors_picker.asp
El color azul es el color 4 (ver la captura anterior, se comienza en 0).
Veamos un ejemplo, donde a cada segundo que pasa, cambiamos el color azul por otro para simular el anochecer:
#include <genesis.h> #include "gfx.h" //carga la imagen de background int main() { u16 ind, contador; SYS_disableInts(); VDP_setScreenWidth320(); VDP_setPalette(PAL0,bga_image.palette->data); ind = TILE_USERINDEX; VDP_drawImageEx(PLAN_A, &bga_image, TILE_ATTR_FULL(PAL0, FALSE, FALSE, FALSE, ind), 0, 0, FALSE, TRUE); ind += bga_image.tileset->numTile; SYS_enableInts(); contador = 0; while(TRUE) { contador++; //60fps, cada segundo vale 60 más //Cambio de cielo (azul->naranja->rojo->negro) if(contador>60*1) VDP_setPaletteColor(4, RGB24_TO_VDPCOLOR(0xFF6600)); if(contador>60*2) VDP_setPaletteColor(4, RGB24_TO_VDPCOLOR(0xCC5200)); if(contador>60*3) VDP_setPaletteColor(4, RGB24_TO_VDPCOLOR(0x993D00)); if(contador>60*4) VDP_setPaletteColor(4, RGB24_TO_VDPCOLOR(0x662900)); if(contador>60*5) VDP_setPaletteColor(4, RGB24_TO_VDPCOLOR(0x000000)); VDP_waitVSync(); } return 0; }
Ampliamos a todo el fondo.
El color verde de las plantas lo tenemos en el color 1 y 8 de la paleta. Cambiará a marrón.
El color del tejado del castillo (rojos) son los colores 2 y 12 de la paleta. Los oscureceré.
... //Cambio de cielo (azul->naranja->rojo->negro) if(contador>60*1) VDP_setPaletteColor(4, RGB24_TO_VDPCOLOR(0xFF6600)); if(contador>60*2) VDP_setPaletteColor(4, RGB24_TO_VDPCOLOR(0xCC5200)); if(contador>60*3) VDP_setPaletteColor(4, RGB24_TO_VDPCOLOR(0x993D00)); if(contador>60*4) VDP_setPaletteColor(4, RGB24_TO_VDPCOLOR(0x662900)); if(contador>60*5) VDP_setPaletteColor(4, RGB24_TO_VDPCOLOR(0x000000)); //cambio de castillo (rojo->rojo oscuro) if(contador>60*3) VDP_setPaletteColor(2, RGB24_TO_VDPCOLOR(0x802000)); if(contador>60*4) VDP_setPaletteColor(12, RGB24_TO_VDPCOLOR(0x661A00)); //cambio del cesped (verde->marrón) if(contador>60*1) VDP_setPaletteColor(8, RGB24_TO_VDPCOLOR(0x999900)); if(contador>60*2) VDP_setPaletteColor(1, RGB24_TO_VDPCOLOR(0x997300)); ...
En esta captura se aprecia como va cambiando la paleta y el fondo. He señalado alguno de los cambios (pero no todos).
(nota: en cuanto pueda lo cambio por un gift animado), no lo digo… ¡lo hago!
Observar como va cambiando los colores en la paleta, en los tiles de la memoria del VDP y en el propio juego.
GITHUB
El código de esta lección, y de todas las demás, lo podrás encontrar en mi github: