#include "SDL.h"
#include "SDL_image.h"
#include <string>
//width, height, bpp and frame rate of program
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
const int FRAME_RATE = 30;
const int SQUARE_WIDTH = 20;
const int SQUARE_HEIGHT = 20;
SDL_Surface *screen = NULL;
SDL_Surface *square = NULL;
SDL_Surface *background = NULL;
//TODO: Declare surfaces
SDL_Event event;
SDL_Rect wall;
//classes
class Square //like dot, with SDL_Rect for x and y co-ords
{
private:
//velocity of the dot
int xVel, yVel;
public:
//x and y offsets
SDL_Rect box;
//init variables
Square();
//handle user input and apply it to the dot
void handle_input();
//move dot
void move();
//display dot
void show();
};
class Timer
{
private:
//time when timer started/paused
int startTicks;
int pausedTicks;
//timer status
bool paused;
bool started;
public:
//init variables
Timer();
//clock actions
void start();
void stop();
void pause();
void unpause();
//Gets timer's time
int get_ticks();
//check timer status
bool is_started();
bool is_paused();
};
//functions
SDL_Surface *load_image(std::string filename)
{
//The image that's loaded
SDL_Surface* loadedImage = NULL;
//The optimized surface that will be used
SDL_Surface* optimizedImage = NULL;
//Load the image
loadedImage = IMG_Load(filename.c_str());
//If the image loaded
if( loadedImage != NULL )
{
//Create an optimized surface
optimizedImage = SDL_DisplayFormat(loadedImage);
//Free the old surface
SDL_FreeSurface(loadedImage);
//If the surface was optimized
if(optimizedImage != NULL)
{
//Color key surface
SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB(optimizedImage->format, 0, 0xFF, 0xFF));
}
}
//Return the optimized surface
return optimizedImage;
}
void apply_surface(int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL)
{
//Holds offsets
SDL_Rect offset;
//Get offsets
offset.x = x;
offset.y = y;
//Blit
SDL_BlitSurface(source, clip, destination, &offset);
}
bool check_collision(SDL_Rect A, SDL_Rect B)
{
//boundaries for collision
int leftA, leftB;
int rightA, rightB;
int topA, topB;
int bottomA, bottomB;
//size of rectA
leftA = A.x;
rightA = A.x + A.w;
topA = A.y;
bottomA = A.y + A.h;
//size of rectB
leftB = B.x;
rightB = B.x + B.w;
topB = B.y;
bottomB = B.y + B.h ;
//if sides of A are outside B
if(bottomA <= topB)
{
return false;
}
else if(topA >= bottomB)
{
return false;
}
else if(rightA <= leftB)
{
return false;
}
else if(leftA >= rightB)
{
return false;
}
//if sides of A are within B
else
{
return true;
apply_surface(0, 0, background, screen, NULL);
}
}
bool init()
{
//Initialize all SDL subsystems
if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return false;
}
//Set up the screen
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);
//If there was an error in setting up the screen
if(screen == NULL)
{
return false;
}
//Initialize SDL_mixer
//Set the window caption
SDL_WM_SetCaption("Motion", NULL);
//If everything initialized fine
return true;
}
bool load_files()
{
//Load the background image
square = load_image("square.bmp");
background = load_image("background.png");
//If there was a problem in loading the background
if(square == NULL)
{
return false;
}
if(background == NULL)
{
return false;
}
//If there was an error in loading the font
//Load the music
//music = Mix_LoadMUS( "beat.wav" );
//If there was a problem loading the music
//Load the sound effects
//scratch = Mix_LoadWAV( "scratch.wav" );
//high = Mix_LoadWAV( "high.wav" );
//med = Mix_LoadWAV( "medium.wav" );
//low = Mix_LoadWAV( "low.wav" );
//If everything loaded fine
return true;
}
void clean_up()
{
//Free the surfaces
SDL_FreeSurface(square);
//Free the sound effects
//Mix_FreeChunk( scratch );
//Mix_FreeChunk( high );
//Mix_FreeChunk( med );
//Mix_FreeChunk( low );
//Free the music
//Mix_FreeMusic( music );
//Close the font
//TTF_CloseFont( font );
//Quit SDL_mixer
//Mix_CloseAudio();
//Quit SDL_ttf
//Quit SDL
SDL_Quit();
}
//Class functions
//Timer
Timer::Timer()
{
//init variables
startTicks = 0;
pausedTicks = 0;
paused = false;
started = false;
}
void Timer::start()
{
//start/unpause
started = true;
paused = false;
//get current time
startTicks = SDL_GetTicks();
}
void Timer::stop()
{
//stop/pause timer
started = false;
paused = false;
}
int Timer::get_ticks()
{
//if timer is running
if(started == true)
{
//if paused
if(paused == true)
{
//return #ticks when paused
return pausedTicks;
}
else
{
//return current time - start ticks
return SDL_GetTicks() - startTicks;
}
}
//if timer isnt running
return 0;
}
void Timer::pause()
{
//if timer is running and not paused
if((started == true) && (paused == false))
{
//pause timer
paused = true;
//calculate paused ticks
pausedTicks = SDL_GetTicks() - startTicks;
}
}
void Timer::unpause()
{
//if paused
if(paused == true)
{
//unpause
paused = false;
//reset start ticks
startTicks = SDL_GetTicks() - pausedTicks;
//reset paused ticks
pausedTicks = 0;
}
}
bool Timer::is_started()
{
return started;
}
bool Timer::is_paused()
{
return paused;
}
//Square
Square::Square()
{
//offsets
box.x = 0;
box.y = 0;
//dimensions
box.w = SQUARE_WIDTH;
box.h = SQUARE_HEIGHT;
//velocity
xVel = 0;
yVel = 0;
}
void Square::handle_input()
{
if(event.type == SDL_KEYDOWN)
{
switch(event.key.keysym.sym)
{
case SDLK_UP: yVel -= SQUARE_HEIGHT / 2; break;
case SDLK_DOWN: yVel += SQUARE_HEIGHT / 2; break;
case SDLK_LEFT: xVel -= SQUARE_WIDTH / 2; break;
case SDLK_RIGHT: xVel += SQUARE_WIDTH / 2; break;
}
}
else if(event.type == SDL_KEYUP)
{
switch(event.key.keysym.sym)
{
case SDLK_UP: yVel += SQUARE_HEIGHT / 2; break;
case SDLK_DOWN: yVel -= SQUARE_HEIGHT / 2; break;
case SDLK_LEFT: xVel += SQUARE_WIDTH / 2; break;
case SDLK_RIGHT: xVel -= SQUARE_WIDTH / 2; break;
}
}
}
void Square::move()
{
//move on x axis
box.x += xVel;
//if it goes too far left or right or collides
if((box.x < 0) || (box.x + SQUARE_WIDTH > SCREEN_WIDTH) || (check_collision(box, wall)))
{
//move back
box.x -= xVel;
}
//move on y axis
box.y += yVel;
//if it goes too far up ot down or collides
if((box.y < 0) || (box.y + SQUARE_HEIGHT > SCREEN_HEIGHT) || (check_collision(box, wall)))
{
box.y -= yVel;
}
}
void Square::show()
{
//show square
apply_surface(box.x, box.y, square, screen);
if(check_collision(box, wall) == true)
{
apply_surface(0, 0, background, screen, NULL);
}
}
int main(int argc, char* args[])
{
bool quit = false;
Square mySquare;
Timer fps;
if(init() == false)
{
return 1;
}
if(load_files() == false)
{
return 1;
}
wall.x = 300;
wall.y = 40;
wall.w = 40;
wall.h = 400;
while(quit == false)
{
fps.start();
while(SDL_PollEvent(&event))
{
mySquare.handle_input();
if(event.type == SDL_QUIT)
{
quit = true;
}
}
mySquare.move();
//show white screen, grey wall
if(check_collision(mySquare.box, wall) == false)
{
SDL_FillRect(screen, &screen->clip_rect, SDL_MapRGB(screen->format, 0xFF, 0xFF, 0xFF));
SDL_FillRect(screen, &wall, SDL_MapRGB(screen->format, 0x77, 0x77, 0x77));
}
else
{
apply_surface(0, 0, background, screen, NULL);
}
mySquare.show();
if(SDL_Flip(screen) == -1)
{
return 1;
}
if(fps.get_ticks() < 1000 / FRAME_RATE)
{
SDL_Delay((1000 / FRAME_RATE) - fps.get_ticks());
}
}
clean_up();
return 0;
}
I think that
apply_surface(0, 0, background, screen NULL)
Should be fine, but I don't know where to insert it.
Thanks.