(C++) SDL example 5: moving an image over a background image in a 2D OpenGL environment

February 24, 2017 · View on GitHub

 

 

 

 

 

(C++) SDL example 5: moving an image over a background image in a 2D OpenGL environment

 

This SDL example shows an image moving over a background image, like this screenshot (png).

 

Operating system: Ubuntu

IDE: Qt Creator 2.0.0

Project type: Qt4 Console Application

Selected required modules: QtCore

Compiler: G++ 4.4.1

Additional libraries: SDL, OpenGL, Boost

 

 

 

 

 

Qt project file

 


#------------------------------------------------- # # Project created by QtCreator 2010-07-17T14:57:33 # #------------------------------------------------- QT += core QT -= gui TARGET = CppSdlExample5 CONFIG += console CONFIG -= app_bundle TEMPLATE = app LIBS += -L/usr/local/lib -lSDL LIBS += -L/usr/local/lib -lGL SOURCES += main.cpp

 

 

 

 

 

Source code

 


#include <cassert> #include <cstdlib> #include <iostream> #include <vector> #include <boost/timer.hpp> #include <SDL/SDL.h> #include <SDL/SDL_opengl.h> int main() {   const bool full_screen = false;   //Initialization   if( SDL_Init( SDL_INIT_VIDEO) < 0 )   {     assert(!"Assume SDL initialization does not fail");   }   //Perform SDL_Quit at program exit   std::atexit(SDL_Quit);   //Load the background   SDL_Surface * const background = SDL_LoadBMP("Background512x256.bmp");   assert(background && "Assume background image is found in same folder as binary");   int screen_width = background->w;   int screen_height = background->h;   // Check that the image's dimensions are a power of 2   if ( (screen_width &amp; (screen_width - 1)) != 0 )   {     std::clog << "warning: background image width is not a power of 2\n";   }   if ( (screen_height &amp; (screen_height - 1)) != 0 )   {     std::clog << "warning: background image width is not a power of 2\n";   }   //Create screen of same size as background   const int bits_per_pixel = 32;   SDL_Surface * const screen = SDL_SetVideoMode( screen_width, screen_height, bits_per_pixel, SDL_OPENGL | (full_screen ? SDL_FULLSCREEN : 0));   assert(screen && "Assume SDL video mode setting does not fail");   if (full_screen)   {     screen_width = screen->w;     screen_height = screen->h;   }   //Load the sprite   SDL_Surface * const sprite = SDL_LoadBMP("Butterfly128x128_Alpha.bmp");   assert(background && "Assume sprite image is found in same folder as binary");   //Initialize OpenGL   glClearColor( 0, 0, 0, 0 );   glMatrixMode( GL_PROJECTION );   glLoadIdentity();   glOrtho( 0, screen_width, screen_height, 0, -1, 1 );   glMatrixMode( GL_MODELVIEW );   glLoadIdentity();   if( glGetError() != GL_NO_ERROR )   {     assert(!"Assume OpenGL initialization does not fail");   }   GLenum texture_format;   const GLint bytes_per_pixel = background->format->BytesPerPixel;   switch (bytes_per_pixel)   {     case 3: texture_format = (SDL_BYTEORDER != SDL_BIG_ENDIAN ? GL_BGR : GL_RGB ); break;     case 4: texture_format = (SDL_BYTEORDER != SDL_BIG_ENDIAN ? GL_BGRA : GL_RGBA); break;     default: assert(!"Should not get here");   }   //Generate a texture object handle for the background   GLuint texture_background;   glGenTextures( 1, &texture_background);   // Bind the texture object   glBindTexture( GL_TEXTURE_2D, texture_background);   // Set the texture's stretching properties   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );   // Edit the texture object's image data using the information SDL_Surface gives us   glTexImage2D( GL_TEXTURE_2D, 0, bytes_per_pixel, background->w, background->h, 0,                 texture_format, GL_UNSIGNED_BYTE, background->pixels );   //Generate a texture object handle for the sprite   GLuint texture_sprite;   glGenTextures( 1, &texture_sprite);   // Bind the texture object   glBindTexture( GL_TEXTURE_2D, texture_sprite);   // Set the texture's stretching properties   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );   // Edit the texture object's image data using the information SDL_Surface gives us   glTexImage2D( GL_TEXTURE_2D, 0, bytes_per_pixel, sprite->w, sprite->h, 0,                 GL_BGRA, GL_UNSIGNED_BYTE, sprite->pixels );   //Set up sprite   const int sprite_width = sprite->w;   const int sprite_height = sprite->h;   int sprite_x = (screen_width / 2) - (sprite_width / 2);   int sprite_y = (screen_height / 2) - (sprite_height / 2);   int sprite_dx = 1;   int sprite_dy = 1;   const int frames_per_second = 60;   const int ticks_per_second = 1000 / frames_per_second;   while (1)   {     //Use timer to keep frame rate constant     boost::timer timer;     //Enable user to terminate program     SDL_Event event;     SDL_PollEvent( &event );     if( event.type == SDL_KEYDOWN       || event.type == SDL_MOUSEBUTTONDOWN       || event.type == SDL_QUIT) break;     //Move the square     sprite_x+=sprite_dx;     sprite_y+=sprite_dy;     //Make the square bounce     if (sprite_x < 0 || sprite_x + sprite_width > screen_width ) sprite_dx = -sprite_dx;     if (sprite_y < 0 || sprite_y + sprite_height > screen_height ) sprite_dy = -sprite_dy;     //Clear the screen     glClear( GL_COLOR_BUFFER_BIT );     //Draw background     glBindTexture( GL_TEXTURE_2D, texture_background );     //glBlendFunc(GL_ZERO, GL_ZERO);     //glDisable(GL_BLEND);     glEnable(GL_TEXTURE_2D);     glBegin( GL_QUADS );     glTexCoord2i( 0, 0 ); glVertex2i( 0 , 0 );     glTexCoord2i( 1, 0 ); glVertex2i( screen_width, 0 );     glTexCoord2i( 1, 1 ); glVertex2i( screen_width, screen_height);     glTexCoord2i( 0, 1 ); glVertex2i( 0 , screen_height);     glEnd();     //Draw the sprite     glBindTexture( GL_TEXTURE_2D, texture_sprite );     glBegin( GL_QUADS );     glTexCoord2i( 0, 0 ); glVertex2i( sprite_x , sprite_y );     glTexCoord2i( 1, 0 ); glVertex2i( sprite_x + sprite_width, sprite_y );     glTexCoord2i( 1, 1 ); glVertex2i( sprite_x + sprite_width, sprite_y + sprite_height);     glTexCoord2i( 0, 1 ); glVertex2i( sprite_x , sprite_y + sprite_height);     glEnd();     glDisable(GL_TEXTURE_2D);     //Reset     glLoadIdentity();     //Update screen     SDL_GL_SwapBuffers();     //Keep frame rate constant     const int ticks_elapsed = static_cast<int>(timer.elapsed() * 1000.0);     if (ticks_elapsed < ticks_per_second)     {       SDL_Delay( ticks_per_second - ticks_elapsed );     }   }   SDL_FreeSurface( screen );   glDeleteTextures( 1, &texture_background ); }