[Anterior] Tabla de Contenidos [Siguiente]

Programando con SDL

Ocupando el Vídeo

Cuando se trabaja con video en SDL se debe pensar en superficies. Las superficies son basicamente un área de memoria, ya sea memoria del sistema (RAM) o memoria de video (de la tarjeta de video). En esta área de memoria se puede almacenar imágenes, dibujar sobre ellas, etc etc. Las superficies pueden ser creadas y destruidas varias veces a lo largo del juego, sin embargo, solo puede haber una superficie de pantalla. Esta es la superficie que aparecera en el monitor, por tanto, cualquier cosa que se desee hacer visible, debe ser dibujada sobre esta superficie.

La pantalla se inicializa con la instrucción SetVideoMode, la cual devuelve una superficie, que sin embargo no es distinta de ninguna otra. La instrucción completa será:

SDL_Surface *pScreen;
pScreen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE);
En este caso, se estaria configurando la pantalla para que funcione a una resolucion de 640x480 pixeles, con una profundidad de color de 16 bits. El cuarto argumento define que tipo de superficie será, si es posible tal superficie. Existen 2 tipos, las superficies de hardware y las superficies de software. La primera corresponde a las superficies retenidas en la memoria de video, que es la más rapida. La segunda corresponde a las superficies retenidas en la memoria de sistema, que corresponde a la RAM normal, la cual es marcada por SDL como "datos graficos retenidos". En el caso que el dispositivo no soporte superficies de hardware (como es el caso de X11), o que la memoria de harware este llena, entonces se creara una superficie, pero de software.
Ademas, existe un ultimo parametro que permite redimensionar la ventana (SDL_RESIZABLE), quitarle el marco (SDL_NOFRAME) o soportar renderizado OpenGL (SDL_OPENGL), entre otras.

Cada superficie creada, una vez que ha dejado de usarse, debe ser liberada. Esto se logra mediante la instrucción SDL_FreeSurface:
SDL_FreeSurface(pScreen);
Además de la pantalla, se necesitan otras superficies, dentro de las cuales se pueda dibujar otros gráficos. Hay dos formas principales de crear otras superficies. La primera es crear la superficie manualmente. Con esto se debe indicar cada pixel directamente sobre la superficie y por separado, lo cual es extremadamente poco práctico, en terminos generales. Una forma mucho más eficiente de hacerlo es importando archivos .bmp, y copiando la imagen en alguna superficie. Esto se logra con el siguiente comando:
SDL_Surface *SDL_LoadBMPU(const char *file);
De esta forma es facil hacer uso de varias superficies, cada una de las cuales retendrá un juego de graficos específico. La imagen del juego, por tanto, se construirá a partir de varias superficies a la superficie de la pantalla. Este proceso se conoce como blitting (BLock Image Transfer).
Existe solo una función para realizar el blitting:
int SDL_BlitSurface( SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);
De esta forma, se le indica al sistema que tome el cuadro srcrect, que se especifica con la estructura SDL_Rect, desde la superficie src, y que lo monte sobre la superficie dst, en el cuadro especificado por dstrect. La única condición para esto es que los cuadros sean del mismo tamaño, sin embargo, este tamaño puede ser mayor al tamaño de la superficie. De esta forma, el sistema recortará la figura automaticamente.
SDL_Rect corresponde a una estructura simple de cuatro enteros. los dos primeros indican la posición en la pantalla del cuadro que se desea transmitir, y los dos siguientes especifican el ancho y el alto del cuadro.
SDL_Rect srcrect = {600, 450, 64, 64};
El ultimo paso consiste en traspasar la superficie a la pantalla de forma efectiva, puesto que la superficie configurada de esta forma no corresponde a ella, puesto que es controlada por el dispositivo, no por SDL. El traspaso de la imagen se logra actualizando al dispositivo con el grafico que se ha creado. Para ello se ocupa la función siguiente:
void SDL_UpdateRect( SDL_Surface *screen, Sint32 x, Sint32 y, Sint32 w, Sint32 h);
De esta forma se actualiza solo una porción de la pantalla, que es mucho más rapido que actualizar la pantalla completa. Si de todos modos se desea actualizar la pantalla completa, se deben pasar solo ceros como argumentos.
Ejemplo:
void ShowBMP(char *file, SDL_Surface *screen, int x, int y)
{
    SDL_Surface *image;
    SDL_Rect dest;

    /* Cargamos el archivo BMP en la superficie */
    image = SDL_LoadBMP(file);
    if ( image == NULL ) {
        fprintf(stderr, "No pude cargar %s: %s\n",
	        file, SDL_GetError());
        return;
    }

    /* Volcamos en la superficie de pantalla. */
    dest.x = x;
    dest.y = y;
    dest.w = image->w;
    dest.h = image->h;
    SDL_BlitSurface(image, NULL, screen, &dest);

    /* Actualizamos la porcion de pantalla que ha cambiado */
    SDL_UpdateRects(screen, 1, &dest);

    SDL_FreeSurface(image);
}

[Anterior] Tabla De Contenido [Siguiente]