Rotando sprites con IA


Para este juego quería diseñar una mecánica de rotación de gravedad similar a lo que se ve en Mario galaxy, o en juegos indie como el VVVVVV, y pues para poder hacer esto necesitaba poder rotar un sprite, dado las limitaciones de hardware de la Gameboy no es posible rotar un sprite 90 grados, solo se puede espejar Flip en X o en Y usando S_FLIPX y S_FLIPY respectivamente, tambien se puede convinar ambos logrando una rotación de 180 grados, pero no de 90

Así que me propuse rotar el sprite por software, pero había un problema los gráficos de Gameboy se codificación y se decodifican en 1bpp en un solo color  o 2bpp para los cuatro colores, es decir se comprimen para ahorrar espacio la mitad de los bytes, por ejemplo el siguiente arreglo es para un sprite de 8x8

unsigned char sprite[] = { 0x18, 0x18, 0x2C, 0x34, 0x4E, 0x72, 0x8F, 0xF1,0xEF, 0xF7, 0x2C, 0x34, 0x2C, 0x34, 0x3C, 0x3C  };

Esto programas como el GBTD (Gameboy tile designer) así como los conversores de imágenes que se usa tanto en GBDK como GBstudio lo convierten automáticamente. 

En ésta conversión los pixeles de la primera fila de 8 se distribuyen entre los 2 primeros bytes y así consecutivamente mas información aquí https://www.huderlem.com/demos/gameboy2bpp.html

como pueden notar rotar un sprite no sería algo tan sencillo como intercambiar filas por columnas o sus equivalentes (usando / y % para obtenerlos del arreglo unidireccional) , ya que dado la codificación si uno hace esto es decir intercambiar bytes del arreglo, el sprite resultante se distorsióna. 

entonces decidí usar la IA antes que seguir confundiendome pensando, le pasé la explicación de la página anterior a chatgpt y le pedí que haga una función que codifique y decodifique los sprites tras varios intentos pues la ia estaba más confundida que yo logré optener una función que decodifica los sprites y después le dije que hiciera la función inversa.  después simplemente junte las funciones y cambie los indexes de filas y columnas para rotarlo 



#include <stdio.h>
unsigned char temp_index_i=0;
unsigned char temp_index_j=0;
unsigned char temp_index_row=0;
unsigned char temp_index_col=0;
unsigned char spriteIndex = 0;
unsigned char temp_lowByte = 0;
unsigned char temp_highByte = 0;
unsigned char temp_pixelColor = 0;
unsigned char temp_matriz[64];
void rotate_sprite(unsigned char sprite_tile[]){
    spriteIndex=0;
    for (temp_index_row = 0; temp_index_row < 8; temp_index_row++) {
        for (temp_index_col = 0; temp_index_col < 8; temp_index_col++) {
            temp_lowByte =  sprite_tile[spriteIndex];
            temp_highByte = sprite_tile[spriteIndex + 1];
            temp_pixelColor = 0;
            temp_pixelColor |=  (temp_highByte >> (7 - temp_index_col)) & 0x01 ;
            temp_pixelColor <<= 1;
            temp_pixelColor |=  (temp_lowByte >> (7 - temp_index_col)) & 0x01 ;
            temp_matriz[temp_index_row + (7- temp_index_col)*8 ] = temp_pixelColor;
        }
        spriteIndex += 2;
    }
  //  set_bkg_tiles(2,2,8,8,&temp_matriz[0]);
    spriteIndex = 0;
    for (temp_index_row = 0; temp_index_row < 8; temp_index_row++) {
        for (temp_index_col = 0; temp_index_col < 8; temp_index_col += 8) {
            temp_lowByte = 0;
            temp_highByte = 0;
            for (temp_index_i = 0; temp_index_i < 8; temp_index_i++) {
                temp_lowByte |= ((temp_matriz[temp_index_row*8 + temp_index_col + temp_index_i] & 0x01) << (7 - temp_index_i));
                temp_highByte |= (((temp_matriz[temp_index_row*8 + temp_index_col + temp_index_i] >> 1) & 0x01) << (7 - temp_index_i));
            }
            sprite_tile[spriteIndex] = temp_lowByte;
            sprite_tile[spriteIndex+1] = temp_highByte;
            spriteIndex += 2;
        }
    }
}
    
//end of sprite_rotate.c

ahora este código es algo lento pero funciona ,así que solo lo uso la primera vez que carga el juego y le toma alrededor de 2 segundos, llegando a preguntar en foros encontré el siguiente código pero es para la codificación 1bpp 


//90 degrees clockwise:
#include <gbdk/platform.h>
#include <gbdk/stdint.h>
const uint8_t  tile[] = {0x00, 0xD8, 0xEC, 0xCC, 0xFC, 0xC6, 0xE6, 0xDC};
uint8_t buffer_1bpp_tile[8];
void main()
{
    set_bkg_1bpp_data(0, 1, tile);
    for (uint8_t j = 0, mask = 0x80; j != 8; j++, mask >>= 1) {
        uint8_t row = 0;
        for (uint8_t i = 0; i != 8; i++) {
            row |= ((tile[i] & mask) ? 1 : 0) << i;
        }
        buffer_1bpp_tile[j] = row;
    }
    set_bkg_1bpp_data(1, 1, buffer_1bpp_tile);
}
//

pero no lo uso porque es 1bpp y porque ya tengo el primero

Get keychan

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.