Wiki

Tutoriales Programacion SDL

SDL (Simple DirectMedia Layer)

¿Qué es SDL?

Para aquellos que no lo sepáis, viene a ser el DirectX libre; provee de un sistema de administración de entrada/salida, sonido, fuentes truetype, servicio de red, gráficos 2D y por supuesto, interacción con OpenGL para 3D etc... . Lo bueno, es que además de ser OpenSource, es multiplataforma (Windows, GNU/Linux y OSX que yo sepa).

La mayoría de los que hemos intentado entrar en el mundillo scener a través de la parte de programación, nos hemos encontrado con el escollo que supone la creación de una ventana y su correspondiente unión a un contexto de render OpenGL; que aunque algunos IDEs traen el código en una plantilla lista para usar, siempre es un engorro. Con SDL disponemos de un método sencillo y consistente de hacer esto; además, tener a nuestra disposición (si queremos) reproducción de música y captura de eventos de teclado (las demos que se presentan a concurso suelen tener que poder pararse, pulsando la tecla ESC) siempre es una ventaja.

Inicializando SDL

Aunque se utilice OpenGL para el 3D, el resto (eventos de entrada/salida, audio, 2D...). Se sigue manejando de forma normal con SDL.

Sin más preámbulos, vamos al meollo de la cuestión; y no veo mejor forma de comenzar que un buen filete de código ;) .

#include <stdlib.h>
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include "SDLTest.h"

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define BPP 32

int sdl_load();
int opengl_init();
int show ( square* sqre);
void handle_input(SDL_Event event, square *sqre);
void move(square *sqre);

int main (int argc, char** argv){
    SDL_Event event;
    int quit;
    quit = 0;
    square sqre;
    sqre.x = 0;
    sqre.y = 0;
    sqre.xSpeed = 0;
    sqre.ySpeed = 0;
    
    if (sdl_load() == 0){
        printf("SDL Inicializado correctamente");
    }else{
        printf("Error Inicializando SDL");
        SDL_Quit();
        return 1;
    }
    
    
    /* Bucle principal y captura de eventos e/s */
    while(quit == 0){
        while ( SDL_PollEvent ( &event ) ){
            handle_input(event, &sqre);
            if ( event.type == SDL_QUIT )
                quit = 1;
        }    
        move(&sqre);
        glClear ( GL_COLOR_BUFFER_BIT );
        if( show (&sqre) != 0){
            printf("Error displaying quad");
        }
        SDL_GL_SwapBuffers ();
    }

    SDL_Quit();
    //getchar();
    return 0;
}

int sdl_load (){ 
    /*
     * Estas 3 funciones devuelven valores de error
     * que deberian ser comprobados. Aunque para este ejemplo
     * yo no lo haga por ahorrar código
     */
    if( SDL_Init ( SDL_INIT_EVERYTHING ) < 0){
        printf("Error Iniciando SDL %s\n",SDL_GetError());
        return 1;
    }
    if ( SDL_SetVideoMode ( SCREEN_WIDTH, SCREEN_HEIGHT, BPP, SDL_OPENGL ) == NULL ){
        printf("Error Iniciando el modo de video %s\n",SDL_GetError());
        return 1;
    }
    if ( opengl_init() > 0 ){
        printf("Error Iniciando OpenGL\n");
        return 1;
    }
    return 0;
}

int opengl_init (){
    glClearColor ( 0, 0, 0, 0 );
    glMatrixMode ( GL_PROJECTION );
    glLoadIdentity ();
    glOrtho ( 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1, 1 );
    /*Iniciamos la matriz de modelo*/
    glMatrixMode ( GL_MODELVIEW );
    glLoadIdentity ();
    if ( glGetError() != GL_NO_ERROR )
        return 1;
    return 0;    
}

int show ( square* sqre){
    /* Como siempre que dibujamos usando OpenGl
     * iniciamos un bloque glBegin / glEnd
     */
    glTranslated (sqre->x, sqre->y, 0);
    glBegin ( GL_QUADS );
        glColor4f ( 1.0, 1.0, 1.0, 1.0 );
        glVertex3f ( 0, 0, 0 );
        glVertex3f ( 20, 0, 0 );
        glVertex3f ( 20, 20, 0 );
        glVertex3f ( 0, 20, 0 );
    glEnd();

    glLoadIdentity ();
    return 0;
}

void move(square *sqre)
{
    //Move the square left or right
    sqre->x += sqre->xSpeed;
       
    //If the square went too far
    if( ( sqre->x < 0 ) || ( sqre->x + 20 > SCREEN_WIDTH ) )
    {
        //Move back
        sqre->x -= sqre->xSpeed;
    }
    
    //Move the square up or down
    sqre->y += sqre->ySpeed;
    
    //If the square went too far
    if( ( sqre->y < 0 ) || ( sqre->y + 20 > SCREEN_HEIGHT ) )
    {
        //Move back
        sqre->y -= sqre->ySpeed;
    }
}

void handle_input(SDL_Event event, square *sqre)
{
    //If a key was pressed
    if( event.type == SDL_KEYDOWN )
    {
        //Adjust the velocity
        switch( event.key.keysym.sym )
        {
            case SDLK_UP: sqre->ySpeed -= 20 / 2; break;
            case SDLK_DOWN: sqre->ySpeed += 20 / 2; break;
            case SDLK_LEFT: sqre->xSpeed -= 20 / 2; break;
            case SDLK_RIGHT: sqre->xSpeed += 20 / 2; break;    
        }
    }
    //If a key was released
    else if( event.type == SDL_KEYUP )
    {
        //Adjust the velocity
        switch( event.key.keysym.sym )
        {
            case SDLK_UP:  sqre->ySpeed -= 20 / 2; break;
            case SDLK_DOWN:  sqre->ySpeed -= 20 / 2; break;
            case SDLK_LEFT: sqre->xSpeed -= 20 / 2; break;
            case SDLK_RIGHT: sqre->xSpeed -= 20 / 2; break;    
        }        
    }
}

Aviso: Este tutorial no está terminado.

Esta página es el resultado del esfuerzo de los siguientes autores. El número entre paréntesis corresponde a la cantidad de versiones con las que cada usuario ha contribuido:

cybrid (5)