| SDL: Segundos pasos: Programación de Vídeo Juegos | ||
|---|---|---|
| Anterior | Capítulo 2. Algunas funciones de interés | |
En el artículo anterior vimos funciones básicas para el manejo de superficies, ahora vamos a ver algunas nuevas para ayudarnos entre otras cosas a que nuestro juego vaya más rápido.
Para crear una nueva superficie utizamos la siguiente función:
SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
Con esta función podremos crear una nueva superficie cuadrada donde podemos agregar nuevos elementos. Estos son los parámetros:
flags: son diferentes banderas que se le pueden pasar. Estas son SDL_SWSURFACE, SDL_HWSURFACE, SDL_SRCCOLORKEY y SDL_SRCALPHA.
width: anchura de la nueva superficie.
height: altura de la nueva superficie.
depth: la profundidad.
Rmask: color rojo.
Gmask: color verde.
Bmask: color azul.
Amask: transparencia.
A continuación vemos un ejemplo de como aplicarlo para que quede más claro.
/* Creamos las variables necesarias */
SDL_Surface *surface;
Uint32 rmask, gmask, bmask, amask;
/* damos valores a las variables */
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 200, 200, 32, rmask, gmask, bmask, amask);
if(surface == NULL) {
fprintf(stderr, "CreateRGBSurface ha fallado: %s\n", SDL_GetError());
exit(1);
}
En el ejemplo anterior hemos creado una superficie de 200x200 pixeles.
Durante el desarrollo de un juego tenemos que ir eliminando todo aquello que gasta tiempo y que es prescindible. En esta sección vamos a ver varias funciones que nos ayudan a este trabajo y así mejorar la velocidad del programa.
Una parte importante para todo esto es el "clipping" que viene a ser recortar una parte de pantalla para que sea actualizada, mientras que la parte que quede fuera no se actualice en ese refresco. Con un ejemplo lo vemos mas claro. Imaginarse un juego de naves donde tenemos una parte de la pantalla donde se desarrolla el juego y otra donde colocamos las puntuaciones, vidas y más. Esta parte sólo se actualizará en el momento que subamos las puntuacion, perdamos o ganemos un vida o algo parecido, por lo que se esté actualizando en cada refresco es una pérdida de tiempo. Para ello utilizamos esta función:
void SDL_SetClipRect(SDL_Surface *surface, SDL_Rect *rect);
Esta función debe aparecer antes del SDL_Flip y se le pasa como primer parámetro la pantalla y como segundo el SDL_Rect con el recorte correspondiente.
Otra parte importante es el formato de las imágenes que estemos utilizando. Supongamos que tenemos una pantalla con 24 bit, etc... Esta pantalla tendrá un formato determinado. Imaginemos ahora que queremos pegar (hacer blit) diferentes imágenes en la pantalla que posiblemente tengan otro formato diferente. A la hora de pegar cada una de las imágenes en cada frame, SDL tendrá que hacer la transformación al formato correspondiente. La función que vamos a ver ahora lo que hace es cambiar el formato de la imagen al principio, por lo que se ahorra el cambio de formato al pegar la imagen. La función es la siguiente:
SDL_Surface *SDL_ConvertSurface(SDL_Surface *src, SDL_PixelFormat *fmt, Uint32 flags);
El primer parámetro es la superficie que queremos convertir, el segundo el formato y el tercero las banderas. La función nos devuelve un puntero a una superficie con el formato correspondiente.
Por último y ya que estamos hablando del rendimiento sobre SDL, no voy a comentar ninguna función, solo comentar un problema que me he encontrado al ir desarrollando. En Windows deberíamos de utilizar la misma profundidad de color en el juego que la que estemos utilizando en la pantalla. Es decir, si utilizamos 16 bpp en la función SDL_SetVideoMode al crear nuestro screen para la pantalla, en las propiedades del sistema operativo deberíamos de tenerlo también, ya que en ordenadores más antiguos puede retardar demasiado el refresco de la pantalla. Seguramente tendrá varias formas de poder solucionarse este problema, como forzar al juego a utilizar los mismo bpp que tiene el sistema operativo, pero actualmente yo no se como es y esta seña es simplemente para que la tengáis en cuenta.
SDL_SaveBMP es una función que nos da la posibilidad de crear a partir de una superficie un archivo BMP. Esto nos puede servir para crear ScreenShot del juego en tiempo de ejecución o para utilizarlo en alguna parte del juego. La función tiene la siguiente forma:
int SDL_SaveBMP(SDL_Surface *surface, const char *file);
Como primer parámetro se le pasa un puntero a la superficie y como segundo la ruta donde queremos guardar el archivo. Devuelve 0 en el caso que se cree la imagen y -1 si ha exisitido algún problema.
SDL_SetAlpha es una función que nos da la posibilidad de dar transparencia a una superficie. La función tiene la siguiente estructura:
int SDL_SetAlpha(SDL_Surface *surface, Uint32 flag, Uint8 alpha);
El primer parámetro es la superficie, el segundo los flags, y por último el grado de transparencia un número entre 0 a 255, siendo 255 el valor transparente. Con superficie cargadas desde PNG con zonas transparentes esta función tiene problemas para crear las transparencias.
SDL_SetColorKey esuna función que define un color transparente en la imagen. Al crear los tiles para un juego se define un color que será el que se colocará como transparente. Por ejemplo una nave se le coloca el fondo verde y con esta función se elimina ese color. La estructura de la función es la siguiente:
int SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key);
El primer parámetro es la superficie a la cual queremos aplicar el color transparente, el segundo son los flags, y el tercer es el color. Para ello utilizaremos la función SDL_MapRGB que nos devuelve un valor Uint32 con el valor de un color RGB. A continuación vemos un ejemplo:
Uint32 color; // Escificamos el verde como color para transparente color = SDL_MapRGB(imagen->format, 0,255,0); SDL_SetColorKey(imagen, SDL_SRCCOLORKEY | SDL_RLEACCEL, color);