Aplicación SDL.
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:
Y configurar el entorno:
- Dev-C++: http://jnrdev.72dpiarmy.com/en/howtosdldevcpp/
o descargar el paquete en el área de descargas: sdl-1.2.12.DevPak - Visual C++: http://www.javielinux.com/articulos/sdln1/sdl-n1/x94.html
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 allgenerará 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;
}
Comentarios