Hola a todos,
Tengo una duda acerca del rendimiento de la GP2X a la hora de pintar tiles en pantalla. Antes de empezar, daré las especificaciones técnicas de mi consola, por si es relevante: Firm: 2.1.1, Modelo: - F100. Mi proyecto básicamente es un port del Mario homebrew para correr en esta consola. Al ver que el framerate era irrisorio, he preparado una versión ultra-reducida del problema, que es el que os presento a continuación, y sólo contiene lo esencial. Funciona bajo SDL, tal como indica el título.
Mi problema, a grosso modo es el siguiente: Mi bucle de juego, en el que ahora mismo no hago más que un render de un mapa, ejecutado en la portátil, me corre a 19 fps. Teniendo en cuenta que quiero pintar un fondo, un par de personajes, ejecutar la lógica de juego y las colisiones, auguro que esto va a ser catastrófico en un futuro. Así pues, antes de continuar, quiero corregir cual sea el error que tenga para subir el rendimiento al máximo posible.
Mi bucle de pintado es el siguiente:
Código:
void render()
{
if(!sheet)
{
fprintf(stderr, "No MapSheet for map rendering.. Aborting Render\n");
return;
}
for(int i = 0; i < m_TilesW; i++)
{
for(int j = 0; j < m_TilesH; j++)
{
SDL_Rect rect_src, rect_dst;
int u = (info[i][j] * 16) % 256;
int v = ((info[i][j] / 16) * 16);
rect_src.x = u;
rect_src.y = v;
rect_src.w = 16;
rect_src.h = 16;
rect_dst.x = i * 16;
rect_dst.y = j * 16;
rect_dst.w = 16;
rect_dst.h = 16;
SDL_BlitSurface(sheet, &rect_src, screen, &rect_dst);
}
}
}
Obviamente, para el ejemplo simplificado, m_TilesW = 21 y m_TilesH = 16, de forma que cubre exactamente la pantalla de la gp2x y no pinto nada más de lo necesario. De aquí no se me ocurre qué tocar.
Para la inicialización de la consola:
Código:
SDL_Init(SDL_INIT_EVERYTHING);
screen = SDL_SetVideoMode(320, 240, 8, SDL_HWSURFACE);
if (screen == NULL) {
fprintf (stderr, "Couldn't set the video mode: %s\n", SDL_GetError ());
return false;
}
SDL_EnableUNICODE(1);
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
SDL_Joystick *joystick = SDL_JoystickOpen(0);
if(TTF_Init() == 0)
{
debug_font = TTF_OpenFont("arial.ttf", 10);
}
else
{
return false;
}
Lo que se me ocurre es intentar cambiar los parámetros de SetVideoMode, pero ninguno me ha dado un resultado mejor.
La función de render es la siguiente:
Código:
void renderDebugText(const char *msg, int x, int y)
{
SDL_Rect rect_src, rect_dst;
SDL_Color c; c.r = 255; c.g = 255; c.b = 255;
SDL_Surface *s = TTF_RenderText_Solid(debug_font, msg, c);
SDL_Surface *last_texture = picture;
rect_dst.x = x;
rect_dst.y = y;
rect_dst.h = s->h;
rect_dst.w = s->w;
rect_src = rect_dst;
rect_src.x = 0;
rect_src.y = 0;
SDL_BlitSurface(s, &rect_src, screen, &rect_dst);
SDL_FreeSurface(s);
return;
}
CMap map;
static int frames = 0;
static int last_frame_counter = 0;
CTimer timer;
void Render()
{
frames ++;
map.render();
char msg[32];
sprintf(msg, "FPS: %d\0", last_frame_counter);
renderDebugText(msg, 0, 0);
SDL_Flip(screen);
if(timer.GetElapsed() > 1000)
{
timer.Start();
last_frame_counter = frames;
frames = 0;
}
}
Nada raro aquí, que yo sepa. Lo único es el RenderDebugText que pide memoria y la libera en tiempo de ejecución para una surface. No supone ningún cambio significativo en el proyecto principal.
No se me ocurre nada más. Dejo el .c, los archivos auxiliares y el .gpe listo para correr en una GP2X. Cualquier sugerencia es bienvenida.
Atentamente, nokto.-
Marcadores