#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 );
}
|