Tutorial 05 - Aplicación SDL.
Fecha Jueves, 30 agosto a las 21:20:22
Tema Simple DirectMedia Layer


Veamos otra la librería más, la librería SDL.

¿Qué tiene de especial esta otra librería?. Pues es otra librería multiplataforma, que al igual que GLUT permite su uso combinado con OpenGL y crea ventanas y gestiona los eventos de ratón, teclado, etc; pero es más completa ya que se trata de una librería multimedia que nos permite también añadir sonido a nuestra aplicación..



En este caso el modo de funcionar de la librería es a base de eventos. En la función ProcessMessage(), según el evento ocurrido, llamaremos al método de nuestra clase GraphicApplication encargado de gestionarlo.

Para poder desarrollar con dicha librería, debéis descargar la correspondiente al compilador que estéis usando: http://www.libsdl.org/download-1.2.php
Y configurar el entorno:

Para compilar en Linux, deberéis instalar la librería SDL para Linux, claro. En el directorio /prj/linux existe un fichero makefile. Os situáis en dicho directorio y tecleais make sdl, os generará en el directorio bin el ejecutable. Con make all generará el ejutable para GLUT y para SDL. Y con make clean borra los ficheros generados.

Con todo esto, el programa principal queda como sigue:



    ////////////////////////////////////////////////////////////////////////////    
    ///
    /// brief
    ///     Este código forma parte de los tutoriales sobre programación gráfica.
    ///
    ///
    ///     Vea el fichero licencia.txt para los detalles de uso.
    ///
    /// author 
    ///     Antonio Lucas Moreno
    ///     http://www.programaciongrafica.com/
    ///     contacto@programaciongrafica.com
    ///
    ////////////////////////////////////////////////////////////////////////////    

    #include 
    #include "common.h"
    #include "graphicapplication.h"

    // ----------------------------------------------------------------------------------------
    // En las opciones del proyecto de Visual C++, en la pestaña C/C++ seleccionar en el combo
    // "Code Generation" y en el combo "Use run-time library" seleccionar "Multithreaded DLL".
    #include 
    // ----------------------------------------------------------------------------------------

    #define WINDOW_WIDTH        640
    #define WINDOW_HEIGHT       480
    #define BPP                 32              // Bits por pixel.
    #define FULL_SCREEN         false

    static const SDL_VideoInfo  *   g_VideoInfo;
    static SDL_Surface          *   g_pSurface;
    static int                      g_VideoFlags;
    static bool                     g_IsActive;
    static PROGRAMACION_GRAFICA::WindowProps g_WindowProps;

    // -----------------------------------------------------------------------------
    // Creamos nuestro objeto aplicación de ámbito global para que sea accesible 
    // por la función gestora de mensajes de la ventana.
    PROGRAMACION_GRAFICA::GraphicApplication    g_GraphicApplication;
    // -----------------------------------------------------------------------------

    ///////////////////////////////////////////////////////////////////////////////
    ///     ProcessMessage: Gestiona los eventos SDL.
    ///
    ///     @param  SDL_Event *event: Evento/Mensaje recibido.
    ///
    ///     @return  int:
    ///                     -  0: Ok.
    ///                     - -1: Error.
    ///////////////////////////////////////////////////////////////////////////////
    int ProcessMessage(SDL_Event *event)
    {
        int isEnd= 0;

        SDL_MouseButtonEvent *mouseEvent        = (SDL_MouseButtonEvent *)event;
        SDL_MouseMotionEvent *mouseMotionEvent  = (SDL_MouseMotionEvent *)event;

        switch( event->type )
        {
            case SDL_ACTIVEEVENT:
                g_IsActive= (bool)(event->active.state & SDL_APPACTIVE);
                break;

            case SDL_VIDEORESIZE:
                g_pSurface= SDL_SetVideoMode( event->resize.w, event->resize.h,
                                              g_VideoInfo->vfmt->BitsPerPixel,
                                              g_VideoFlags );
                if ( g_pSurface )
                {
                    //  Reiniciamos OpenGL.
                    g_GraphicApplication.OnCreateWindow( g_WindowProps );

                    // Fijamos la perspectiva
                    g_GraphicApplication.OnResize( event->resize.w, event->resize.h );
                }
                else
                {
                    isEnd= 1; // Error
                }
                break;

            case SDL_KEYDOWN:
                switch ( event->key.keysym.sym )
                {
                    case SDLK_LEFT:
                        g_GraphicApplication.OnKeyDown( 0x25 );
                        break;
                    case SDLK_UP:
                        g_GraphicApplication.OnKeyDown( 0x26 );
                        break;
                    case SDLK_RIGHT:
                        g_GraphicApplication.OnKeyDown( 0x27 );
                        break;
                    case SDLK_DOWN:
                        g_GraphicApplication.OnKeyDown( 0x28 );
                        break;
                    default:
                        g_GraphicApplication.OnKeyDown( event->key.keysym.sym );
                        break;
                }
                break;

            case SDL_KEYUP:
                switch ( event->key.keysym.sym )
                {
                    case SDLK_LEFT:
                        g_GraphicApplication.OnKeyUp( 0x25 );
                        break;
                    case SDLK_UP:
                        g_GraphicApplication.OnKeyUp( 0x26 );
                        break;
                    case SDLK_RIGHT:
                        g_GraphicApplication.OnKeyUp( 0x27 );
                        break;
                    case SDLK_DOWN:
                        g_GraphicApplication.OnKeyUp( 0x28 );
                        break;
                    default:
                        g_GraphicApplication.OnKeyUp( event->key.keysym.sym );
                        break;
                }
                break;

            case SDL_MOUSEMOTION:
                g_GraphicApplication.OnMouseMove( mouseEvent->x, mouseEvent->y );
                break;

            case SDL_MOUSEBUTTONDOWN:

                switch( mouseEvent->button )
                {
                    case SDL_BUTTON_LEFT:
                        g_GraphicApplication.OnLButtonDown( mouseEvent->x, mouseEvent->y );
                        break;

                    case SDL_BUTTON_RIGHT:
                        g_GraphicApplication.OnRButtonDown( mouseEvent->x, mouseEvent->y );
                        break;

                    case SDL_BUTTON_MIDDLE:
                        break;
                }
                break;

            case SDL_MOUSEBUTTONUP:

                switch( mouseEvent->button )
                {
                    case SDL_BUTTON_LEFT:
                        g_GraphicApplication.OnLButtonUp( mouseEvent->x, mouseEvent->y );
                        break;

                    case SDL_BUTTON_RIGHT:
                        g_GraphicApplication.OnRButtonUp( mouseEvent->x, mouseEvent->y );
                        break;

                    case SDL_BUTTON_MIDDLE:
                        break;
                }
                break;

            case SDL_QUIT:
                isEnd= 1;
                break;
        }

        return isEnd;
    }

    ///////////////////////////////////////////////////////////////////////////////
    ///     main: Punto de entrada de la aplicación.
    ///
    ///     @param  int argc: Número de argumentos.
    ///     @param  char * argv[]: Parámetros de la línea de comando.
    ///
    ///     @return  int:
    ///                     -  0: Ok.
    ///                     - -1: Error.
    ///////////////////////////////////////////////////////////////////////////////
    int main(int argc, char * argv[])
    {
        int screenWidth, screenHeight;
        bool bEnd= false;
        int errorCode;
        SDL_Event event;

        try
        {
            g_WindowProps.position.x    = 0;
            g_WindowProps.position.y    = 0;
            g_WindowProps.width         = WINDOW_WIDTH;
            g_WindowProps.height        = WINDOW_HEIGHT;
            g_WindowProps.bpp           = BPP;
            g_WindowProps.bFullScreen   = FULL_SCREEN;
            strcpy( g_WindowProps.title, WINDOW_TITLE );

            // Inicializamos SDL
            if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
                throw -1;

            // Inicialización de nuestra aplicación.
            g_GraphicApplication.OnInit( g_WindowProps );

            // Obtenemos la información de vídeo
            g_VideoInfo= SDL_GetVideoInfo();
            if ( !g_VideoInfo )
                throw -1;

            // Obtenemos la resolución del escritorio
            screenWidth = g_VideoInfo->current_w;
            screenHeight= g_VideoInfo->current_h;

            // Inicializamos el modo de vídeo.
            g_VideoFlags  = SDL_OPENGL;          // Usaremos OpenGL con SDL.
            g_VideoFlags |= SDL_GL_DOUBLEBUFFER; // Habilitamos doble buffer.
            g_VideoFlags |= SDL_HWPALETTE;       // Almacenamos la paleta en hardware.

            if ( g_WindowProps.bFullScreen )
                g_VideoFlags |= SDL_FULLSCREEN;  // Habilitamos pantalla completa.
            else
                g_VideoFlags |= SDL_RESIZABLE;   // Habilitamos el redimensionado.

            // Renderizado por hardware, si lo admite
            if ( g_VideoInfo->hw_available )
                g_VideoFlags |= SDL_HWSURFACE;
            else
                g_VideoFlags |= SDL_SWSURFACE;

            // Si permite acleración por hardware lo fijamos
            if ( g_VideoInfo->blit_hw )
                g_VideoFlags |= SDL_HWACCEL;

            // Fijamos el uso de doble buffer en OpenGL
            SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

            // En SDL podemos especificar la posición inicial de la ventana con una variable de entorno
    #ifdef WIN32
            _putenv("SDL_VIDEO_WINDOW_POS");
            _putenv("SDL_VIDEO_CENTERED=1");
    //      _putenv("SDL_VIDEO_WINDOW_POS=100,100");    // Si queremos situar la ventana en una posición concreta
    #else
            putenv("SDL_VIDEO_WINDOW_POS");
            putenv("SDL_VIDEO_CENTERED=1");
    //      putenv("SDL_VIDEO_WINDOW_POS=100,100");
    #endif
            // Creamos la ventana principal
            g_pSurface= SDL_SetVideoMode( g_WindowProps.width, g_WindowProps.height, g_WindowProps.bpp, g_VideoFlags );
            if ( !g_pSurface )
                throw -1;

            if ( g_WindowProps.bFullScreen )
                SDL_WM_ToggleFullScreen( g_pSurface );

            // Guardamos la posición en la que se encuentra la ventana.
            g_GraphicApplication.SetScreenPosition( g_WindowProps.position.x, g_WindowProps.position.y );

            //  Inicialización de OpenGL.
            g_GraphicApplication.OnCreateWindow( g_WindowProps );

            // Fijamos la perspectiva
            g_GraphicApplication.OnResize( g_WindowProps.width, g_WindowProps.height );

            // Mientras no finalice
            while ( !bEnd )
            {
                // Tratamos los eventos
                while ( !bEnd && SDL_PollEvent( &event ) )
                {
                    bEnd= ProcessMessage( &event );
                }

                if (!bEnd)
                {
                    g_GraphicApplication.OnIdle   ();
                    g_GraphicApplication.OnRender ();
                    SDL_WM_SetCaption( g_GraphicApplication.GetMsgTitle(), NULL );
                    SDL_GL_SwapBuffers();   // Vuelca a la ventana actual la imagen renderizada.
                    bEnd= g_GraphicApplication.IsEnded();
                }
            } // fin while

            // Fin OK
            errorCode= 0;

        }
        catch (int errCode)
        {
            std::cout << std::endl;
            std::cout << "	+-----------------------------------------------------------+"  << std::endl;
            std::cout << "	" << SDL_GetError()                                             << std::endl;
            std::cout << "	+-----------------------------------------------------------+"  << std::endl;
            std::cout << std::endl;

            // Fin Error.           
            errorCode= errCode;
        }

        // Finalizamos SDL
        SDL_Quit();

        // Finalizamos la aplicación
        g_GraphicApplication.OnEnd();

        return errorCode;
    }

Podéis descargaros el ejemplo: tutorial-05.zip



Compartir en Facebook



Este artículo proviene de Programacion Grafica: Desarrollo 2D/3D con C++ y DirectX/OpenGL/GLUT/SDL - Windows/Linux
http://www.programaciongrafica.com

La dirección de esta noticia es:
http://www.programaciongrafica.com/modules.php?name=News&file=article&sid=6