SDL é uma API para interagir com dispositivos do Sistema como por exemplo o CD-rom e Joysticks.
Ela foi desenvolvida pela Loki Games para facilitar o desenvolvimento de jogos livre de plataforma (Windows e Linux), sendo o líder de projeto original Sam Latinga
Características
- Portável (livre de plataforma)
- código-fonte aberto
- Usada por diversos softwares
Exemplos
Criando um janela com SDL + OpenGL: http://www.pontov.com.br/site/index.php?option=com_content&view=article&id=142:criando-uma-janela-opengl&catid=56:opengl&Itemid=57
Uso de Joystick
xxx
APIs auxiliares
A API SDL possui diversas bibliotecas auxiliares que implementam diversas funcionalidades uteis. Uma delas e a SDL_Image que possibilita que imagens JPEG, PNG, e TIFF sejam carregadas.
O link para a biblioteca SDL_Image e http://www.libsdl.org/projects/SDL_image
SDL Image
A API SDL Image permite o carregamento de diversos formatos de imagem. Estes formatos incluem o próprio .bmp, o png, o jpeg e o gif.
Para se utilizar a biblioteca basta configurá-la da mesma forma que qualquer outra biblioteca C, ou seja, dizer ao compilador e ao linker os diretórios em que os .h e .lib estão. Depois no código basta chamar a função IMG_Load no lugar da função SDL_LoadBMP.
SDL ttf
A API SDL ttf serve para carregar fontes truetype e possibilitar seu uso em aplicações SDL
SDL Mixer
A API SDL Mixer permite a execução de arquivos de som em aplicações SDL
Ligações para outras linguagens
SDL2
A SDL2 é a versão mais nova da SDL. Dentre as novidades estão o suporte a Opengl 3+ e Android.
Caracteristicas
- Suporte a texturas
- Suporte a APIs graficas 3D (OGL, DX)
- Suporte a haptico (vibracao nos controladores)
- Suporte a Android
Instalação
Linux
A forma mais simples é instalar usando o gerenciador de pacotes da tua distribuição. No Ubuntu a linha de comando é a seguinte:
sudo apt install libsdl2-dev
Exemplo de codigo
Exemplo simples SDL2 + OpenGL 3.2
#include <iostream> #include <GL/gl.h> #include <SDL2/SDL.h> using namespace std; const char* PROGRAM_NAME = "OPENGL PROGRAM"; /* A simple function that prints a message, the error code returned by SDL, * and quits the application */ void sdldie(const char *msg) { printf("%s: %s\n", msg, SDL_GetError()); SDL_Quit(); exit(1); } void checkSDLError(int line = -1) { #ifndef NDEBUG const char *error = SDL_GetError(); if (*error != '\0') { printf("SDL Error: %s\n", error); if (line != -1) printf(" + line: %i\n", line); SDL_ClearError(); } #endif } int main(int argc, char *argv[]) { SDL_Window *mainwindow; /* Our window handle */ SDL_GLContext maincontext; /* Our opengl context handle */ if (SDL_Init(SDL_INIT_VIDEO) < 0) /* Initialize SDL's Video subsystem */ sdldie("Unable to initialize SDL"); /* Or die on error */ /* Request opengl 3.2 context. * SDL doesn't have the ability to choose which profile at this time of writing, * but it should default to the core profile */ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); /* Turn on double buffering with a 24bit Z buffer. * You may need to change this to 16 or 32 for your system */ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); /* Create our window centered at 512x512 resolution */ mainwindow = SDL_CreateWindow(PROGRAM_NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 512, 512, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); if (!mainwindow) /* Die if creation failed */ sdldie("Unable to create window"); checkSDLError(__LINE__); /* Create our opengl context and attach it to our window */ maincontext = SDL_GL_CreateContext(mainwindow); checkSDLError(__LINE__); /* This makes our buffer swap syncronized with the monitor's vertical refresh */ SDL_GL_SetSwapInterval(1); /* Clear our buffer with a red background */ glClearColor ( 1.0, 0.0, 0.0, 1.0 ); glClear ( GL_COLOR_BUFFER_BIT ); /* Swap our back buffer to the front */ SDL_GL_SwapWindow(mainwindow); /* Wait 2 seconds */ SDL_Delay(2000); /* Same as above, but green */ glClearColor ( 0.0, 1.0, 0.0, 1.0 ); glClear ( GL_COLOR_BUFFER_BIT ); SDL_GL_SwapWindow(mainwindow); SDL_Delay(2000); /* Same as above, but blue */ glClearColor ( 0.0, 0.0, 1.0, 1.0 ); glClear ( GL_COLOR_BUFFER_BIT ); SDL_GL_SwapWindow(mainwindow); SDL_Delay(2000); /* Delete our opengl context, destroy our window, and shutdown SDL */ SDL_GL_DeleteContext(maincontext); SDL_DestroyWindow(mainwindow); SDL_Quit(); return 0; }
SDL2 + OpenGL 3.1
// Using SDL and standard IO #include <GL/glew.h> #include <SDL2/SDL.h> #include <SDL2/SDL_opengl.h> #include <GL/glu.h> #include <GL/gl.h> #include <stdio.h> #include <string> // Starts up SDL and creates window bool init(); // Initializes matrices and clear color bool initGL(); // Renders quad to the screen void render(); // Frees media and shuts down SDL void close(); // Shader loading utility programs void printProgramLog( GLuint program ); void printShaderLog( GLuint shader ); // The window we'll be rendering to SDL_Window* gWindow = NULL; // OpenGL context SDL_GLContext gContext; // Render flag bool gRenderQuad = true; // Graphics program GLuint gProgramID = 0; GLint gVertexPos2DLocation = -1; GLuint gVBO = 0; GLuint gIBO = 0; bool init() { // Initialization flag bool success = true; // Initialize SDL if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_AUDIO) < 0 ) { printf("SDL COuld not be initialized: %s\n", SDL_GetError()); success = false; } else { // Use OpenGL 2.1 SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE ); // Create window gWindow = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN ); if( gWindow == NULL ) { printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() ); success = false; } else { // Create context gContext = SDL_GL_CreateContext( gWindow ); if( gContext == NULL ) { printf( "OpenGL context could not be created! SDL Error: %s\n", SDL_GetError() ); } else { // Initialize GLEW glewExperimental = GL_TRUE; GLenum glewError = glewInit(); if( glewError != GLEW_OK ) { printf( "Error initializing GLEW! %s\n", glewGetErrorString( glewError ) ); } // Use Vsync if( SDL_GL_SetSwapInterval( 1 ) < 0 ) { printf( "Warning: Unable to set VSync! SDL Error: %s\n", SDL_GetError() ); } // Initialize OpenGL if( !initGL() ) { printf( "Unable to initialize OpenGL!\n" ); success = false; } } } } return success; } bool initGL() { // Success flag bool success = true; // Generate Program gProgramID = glCreateProgram(); // Create vertex shader GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER ); // Get vertex source const GLchar* vertexShaderSource[] = { "#version 140\nin vec2 LVertexPos2D; void main() { gl_Position = vec4( LVertexPos2D.x, LVertexPos2D.y, 0, 1 ); }" }; // Set vertex source glShaderSource( vertexShader, 1, vertexShaderSource, NULL ); // Compile vertex source glCompileShader( vertexShader ); // Check vertex shader for errors GLint vShaderCompiled = GL_FALSE; glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &vShaderCompiled ); if( vShaderCompiled != GL_TRUE ) { printf( "Unable to compile vertex shader: %d!\n", vertexShader ); printShaderLog( vertexShader ); success = false; } else { // Attach vertex shader to program glAttachShader( gProgramID, vertexShader ); // Create fragment shader GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER ); // Get fragment source const GLchar* fragmentShaderSource[] = { "#version 140\nout vec4 LFragment; void main() { LFragment = vec4( 1.0, 1.0, 1.0, 1.0 ); }" }; // Set fragment source glShaderSource( fragmentShader, 1, fragmentShaderSource, NULL ); // Compile fragment source glCompileShader( fragmentShader ); // Check fragment shader for errors GLint fShaderCompiled = GL_FALSE; glGetShaderiv( fragmentShader, GL_COMPILE_STATUS, &fShaderCompiled ); if( fShaderCompiled != GL_TRUE ) { printf( "Unable to compile fragment shader: %d!\n", fragmentShader ); printShaderLog( fragmentShader ); success = false; } else { // Attach fragment shader to program glAttachShader( gProgramID, fragmentShader ); // Link program glLinkProgram( gProgramID ); // Check for errors GLint programSuccess = GL_TRUE; glGetProgramiv( gProgramID, GL_LINK_STATUS, &programSuccess ); if( programSuccess != GL_TRUE ) { printf( "Error linking program %d!\n", gProgramID ); printProgramLog( gProgramID ); success = false; } else { // Get vertex attribute location gVertexPos2DLocation = glGetAttribLocation( gProgramID, "LVertexPos2D" ); if( gVertexPos2DLocation == -1 ) { printf( "LVertexPos2D is not a valid glsl program variable!\n" ); success = false; } else { // Initialize clear color glClearColor( 0.f, 0.f, 0.f, 1.f ); // VBO data GLfloat vertexData[] = { -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f }; // IBO data GLuint indexData[] = { 0, 1, 2, 3 }; // Create VBO glGenBuffers( 1, &gVBO ); glBindBuffer( GL_ARRAY_BUFFER, gVBO ); glBufferData( GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), vertexData, GL_STATIC_DRAW ); // Create IBO glGenBuffers( 1, &gIBO ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, gIBO ); glBufferData( GL_ELEMENT_ARRAY_BUFFER, 4 * sizeof(GLuint), indexData, GL_STATIC_DRAW ); } } } } return success; } void render() { // Clear color buffer glClear( GL_COLOR_BUFFER_BIT ); // Render quad if( gRenderQuad ) { // Bind program glUseProgram( gProgramID ); // Enable vertex position glEnableVertexAttribArray( gVertexPos2DLocation ); // Set vertex data glBindBuffer( GL_ARRAY_BUFFER, gVBO ); glVertexAttribPointer( gVertexPos2DLocation, 2, GL_FLOAT, GL_FALSE, 2 * sizeof( GLfloat ), NULL ); // Set index data and render glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, gIBO ); glDrawElements( GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, NULL ); // Disable vertex position glDisableVertexAttribArray( gVertexPos2DLocation ); // Unbind program glUseProgram( NULL ); } } void close() { // Deallocate program glDeleteProgram( gProgramID ); SDL_DestroyWindow(gWindow); gWindow = NULL; // Quit SDL subsystems SDL_Quit(); } void printProgramLog(GLuint program) { // Make sure name is program if( glIsProgram( program ) ) { // Program log length int infoLogLength = 0; int maxLength = infoLogLength; // Get info string length glGetProgramiv( program, GL_INFO_LOG_LENGTH, &maxLength ); // Allocate string char* infoLog = new char[ maxLength ]; // Get info log glGetProgramInfoLog( program, maxLength, &infoLogLength, infoLog ); if( infoLogLength > 0 ) { // Print log printf( "%s\n", infoLog ); } // Deallocate string delete[] infoLog; } else { printf( "Name %d is not a program\n", program ); } } void printShaderLog(GLuint shader) { // Make sure name is shader if( glIsShader( shader ) ) { // Shader log length int infoLogLength = 0; int maxLength = infoLogLength; // Get info string length glGetProgramiv( shader, GL_INFO_LOG_LENGTH, &maxLength ); // Allocate string char* infoLog = new char[ maxLength ]; // Get info log glGetShaderInfoLog( shader, maxLength, &infoLogLength, infoLog ); if( infoLogLength > 0 ) { // Print log printf( "%s\n", infoLog ); } // Deallocate string delete[] infoLog; } else { printf( "Name %d is not a program\n", shader ); } } int main( int argc, char *args[] ) { // Start up SDL and create window if( !init()) { printf("Failed to initialize"); } else { bool quit = false; // Event handler SDL_Event e; // Enable text input SDL_StartTextInput(); // While application is running while( !quit ) { // Handle events on queue while( SDL_PollEvent( &e ) != 0 ) { // User requests quit if( e.type == SDL_QUIT ) { quit = true; } else if( e.type == SDL_KEYDOWN ) { if( e.key.keysym.sym == SDLK_ESCAPE ){ quit = true; } } } // Render quad render(); // Update Screen SDL_GL_SwapWindow( gWindow ); } // Disable text input SDL_StopTextInput(); } // Free resources and close SDL close( ); return 0; }
Links
http://www.libsdl.org/ Página oficial da SDL
http://sdljava.sourceforge.net/ SDLJava
http://www.pygame.org/news.html PyGame
Tutoriais
http://lazyfoo.net/tutorials/SDL/index.php SIte muito bom com uma seção dedicada de artigos referente a tutoriais SDL2
https://wiki.libsdl.org/Tutorials Listagem de páginas com tutoriais sobre SDL