(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
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 & (screen_width - 1)) != 0 ) { std::clog << "warning: background image width is not a power of 2\n"; } if ( (screen_height & (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 ); }