Tutorial SDL 2 en Español - Capítulo 4

Capítulo 4: Programación controlada por Eventos en SDL 2.

En este tema vamos a aprender como manejar eventos en SDL 2. En los juegos mostrar gráficos es muy importante, pero también lo es manejar las entradas del usuario. No creo que a alguien le interese un juego en el que no se pueda controlar al personaje.
En el código, específicamente en la función main, después que se ha inicializado SDL y cargado los medios, declaramos una bandera o indicador quitar de tipo booleano que se usará para registrar el momento en el que el usuario desea abandonar la aplicación.
//Bandera del bucle principal
bool quitar = false;

//Controlador de Eventos
SDL_Event e;
La bandera o indicador quitar lo inicializamos en false, luego declaramos un controlador de eventos SDL_Event e; que se usará para saber qué eventos realizó el usuario, como presionar una tecla del teclado, un botón del mando de juegos o se hizo clic con el mouse. En este programa simplemente vamos a esperar por que el usuario presione una tecla del teclado. Luego de esto, iniciamos un bucle como sigue:
//Bucle principal
while(!quitar){

    //Maneja la cola de eventos
    while(SDL_PollEvent(&e) != 0){

        //Si el usuario solicita salir
        if(e.type == SDL_KEYDOWN){
            quitar = true;
        }
    }

    //Aplicamos la imagen en la superficie de la ventana
    SDL_BlitSurface(bmpImagen, NULL, Superficie, NULL);

    //Actualizamos la superficie de la ventana
    SDL_UpdateWindowSurface(Ventana);

}
El bucle principal se ejecutará una y otra vez hasta que quitar sea true, en tutoriales anteriores, esperabamos algunos segundos mientras se mostraba una imagen, esta vez esperaremos hasta que el usuario decida quitar el programa.
Luego de esto, existe otro bucle dentro del bucle principal, este bucle de eventos procesa la cola de eventos hasta que esté vacía. Cuando nosotros presionamos una tecla del teclado o un botón, estos eventos se van colocando en orden secuencial en la cola de eventos. La función SDL_PollEvent lo que hace es colocar los eventos de la cola de eventos al parámetro que le hemos pasado, es decir en "e" para que podamos procesarlo, cuando la cola de eventos está vacía SDL_PollEvent retorna 0.
Luego tenemos un if que verifica el tipo de evento, si el evento es de tipo SDL_KEYDOWN, es decir, que se ha presionado alguna tecla del teclado, entonces el indicador o bandera cambia a true, si no, no se modifica.
Luego de esto, nos queda el procesamiento del resto del código, en este caso las funciones SDL_BlitSurface y SDL_UpdateWindowSurface.
NOTA:
Observe que esta parte del código es ineficiente, ya que se procesará código de forma repetida que sólo es necesario procesar una vez, pero aquí lo hacemos así de modo de mostrar cómo funciona el bucle principal, que es el alma de un programa de juegos.
El código fuente debe quedar de la siguiente forma:
//Encabezados de inclusión utilizado en nuestros programas
#include <SDL.h>
#include <stdio.h>

//Declaración de la funciones
bool Inicializar();     // Inicialización de SDL y creación de Ventanas
bool cargarMedios();    // Carga los medios
void cerrar();          // Libera los medios y cierra SDL

//Inicialización de la ventana, la superficie y la imagen
SDL_Window* Ventana      = NULL; //La ventana donde se renderizará la imagen
SDL_Surface* Superficie  = NULL; //La superficie que contendrá la ventana
SDL_Surface* bmpImagen   = NULL; //La imagen que se mostrará en la superficie

bool Inicializar(){

    //Bandera de inicialización es correcta
    bool correcto = true;

    //Inicializa el subsistema de Video
    if(SDL_Init(SDL_INIT_VIDEO) < 0){
        printf("ERROR: No se pudo inicializar SDL, Error SDL: %s\n", SDL_GetError());
        correcto = false;
    }
    else{
        //Se crea la ventana principal
        Ventana = SDL_CreateWindow("Tutorial SDL 2", 50, 50, 640, 480, SDL_WINDOW_SHOWN);
        if(Ventana == NULL){
            printf("ERROR: No se pudo crear la ventana, SDL_Error: %s\n", SDL_GetError());
            correcto = false;
        }
        else{
            //Se crea la superficie para la ventana principal
            Superficie = SDL_GetWindowSurface(Ventana);
        }
    }

    //Salimos de la función
    return correcto;
}

bool cargarMedios(){
    //Bandera de carga correcta
    bool correcto = true;

    //Carga la imagen que se mostrará
    bmpImagen = SDL_LoadBMP("mapaBits.bmp");
    if( bmpImagen == NULL){
        printf("No se pudo cargar la imagen %s SDL Error: %s\n", "mapaBits.bmp", SDL_GetError());
        correcto = false;
    }
    //Salimos de la función
    return correcto;
}

void cerrar(){
    //Liberamos la superficie utilizada
    SDL_FreeSurface(bmpImagen);
    bmpImagen = NULL;

    //Destruimos la Ventana para liberar recursos.
    SDL_DestroyWindow(Ventana);

    //Quitamos el subsistema de SDL.
    SDL_Quit();
}

int main(int argc, char* args[]){
    //Inicializa SDL y crea las ventanas
    if(!Inicializar()){
        printf("No se pudo inicializar\n");
    }
    else{
        //Carga los medios
        if(!cargarMedios()){
            printf("No se pudo cargar los medios\n");
        }
        else{
            //Bandera del bucle principal
            bool quitar = false;

            //Controlador de Eventos
            SDL_Event e;

            //Bucle principal
            while(!quitar){

                //Maneja la cola de eventos
                while(SDL_PollEvent(&e) != 0){

                    //Si el usuario solicita salir
                    if(e.type == SDL_KEYDOWN){
                        quitar = true;
                    }
                }

                //Aplicamos la imagen en la superficie de la ventana
                SDL_BlitSurface(bmpImagen, NULL, Superficie, NULL);

                //Actualizamos la superficie de la ventana
                SDL_UpdateWindowSurface(Ventana);
            }
        }
    }

    //Liberamos los recursos y cerramos SDL
    cerrar();

    //Salimos de main
    return 0;
}
Hasta aquí hemos visto como manejar eventos con SDL 2  y también vimos como se procesa la cola de eventos. Puedes descargar el código fuente completo aquí.

No hay comentarios:

Publicar un comentario