#include"SDL/SDL.h"
#include"SDL/SDL_ttf.h"
#include"SDL/SDL_image.h"
#include<sstream>
#include"SDL/SDL_mixer.h"
#include<string>
#include<vector>
#include<iostream>
//Dimensions
const int SCREEN_WIDTH = 1000;
const int SCREEN_HEIGHT = 450;
const int BPP = 32;
//Screen, event and font
SDL_Surface* screen = NULL;
SDL_Event event;
TTF_Font* font;
class projectile;
std::vector<projectile> allProjectiles;
//Background camera (allows me to change the position of the background)
SDL_Rect backgroundCam = {0, 50, 1000, 500};
//Music
Mix_Music* songs[1];
void handleMusic()
{
static int time = SDL_GetTicks();
static int playing = 0;
if( SDL_GetTicks() - time >= 100000 && (!playing) )
{
Mix_PlayMusic( songs[1], 0 );
time = SDL_GetTicks();
playing = 1;
}
if( (SDL_GetTicks() - time >= 18000) && (playing) )
{
Mix_PlayMusic( songs[0], 0 );
time = SDL_GetTicks();
playing = 0;
}
}
void blitSurface( int srcX, int srcY, SDL_Surface* source, SDL_Rect* clip = NULL )
{
SDL_Rect offsets;
offsets.x = srcX;
offsets.y = srcY;
SDL_BlitSurface( source, clip, screen, &offsets );
}
int init( std::string caption )
{
if( SDL_Init(SDL_INIT_EVERYTHING) == -1 )
{
return -1;
}
if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 )
{
return -1;
}
if( TTF_Init() == -1 )
{
return -1;
}
if( (screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, BPP, SDL_SWSURFACE )) == NULL )
{
return -1;
}
SDL_WM_SetCaption( caption.c_str(), NULL );
return 0;
}
void clearUp()
{
TTF_CloseFont( font );
Mix_FreeMusic( songs[0] );
Mix_FreeMusic( songs[1] );
SDL_Quit();
TTF_Quit();
Mix_CloseAudio();
}
void clearScreen()
{
SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 255, 255, 255 ) );
}
SDL_Surface* loadImage( std::string path )
{
SDL_Surface* loadedImage = NULL;
SDL_Surface* optimizedImage = NULL;
loadedImage = IMG_Load( path.c_str() );
if( loadedImage != NULL )
{
optimizedImage = SDL_DisplayFormat( loadedImage );
SDL_FreeSurface( loadedImage );
}
if( optimizedImage != NULL )
{
Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 255, 0, 255 );
SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, colorkey );
}
return optimizedImage;
}
int checkCollison( SDL_Rect* rect1, SDL_Rect* rect2 )
{
if(rect1->y >= rect2->y + rect2->h)
return 0;
if(rect1->x >= rect2->x + rect2->w)
return 0;
if(rect1->y + rect1->h <= rect2->y)
return 0;
if(rect1->x + rect1->w <= rect2->x)
return 0;
return 1;
}
void displayTTF( std::string text, int x, int y, int red = 0, int green = 0, int blue = 0 )
{
SDL_Color colour = { red, green, blue };
SDL_Surface* temp = TTF_RenderText_Solid( font, text.c_str(), colour );
blitSurface( x, y, temp );
SDL_FreeSurface( temp );
temp = NULL;
}
void displayTTF( int num, int x, int y, int red = 0, int green = 0, int blue = 0 )
{
SDL_Color colour = { red, green, blue };
std::stringstream stream;
stream << num;
SDL_Surface* temp = TTF_RenderText_Solid( font, stream.str().c_str(), colour );
blitSurface( x, y, temp );
SDL_FreeSurface( temp );
temp = NULL;
}
class projectile
{
public:
int x, y, w, h, velocity;
std::string filePath;
SDL_Surface* sprite;
projectile( int X, int Y, int VEL, int W, int H, std::string path ): x(X), y(Y), w(W), h(H), velocity(VEL), filePath(path) { sprite = loadImage( path.c_str() ); }
projectile( const projectile& proj )
{
this->x = proj.x;
this->y = proj.y;
this->w = proj.w;
this->h = proj.h;
this->velocity = proj.velocity;
this->filePath = proj.filePath;
this->sprite = loadImage( filePath.c_str() );
}
~projectile(){ SDL_FreeSurface(sprite); }
void show(){ blitSurface( x, y, sprite ); }
};
projectile spawnProjectile( int x, int y, int w, int h, int velocity, std::string path )
{
projectile proj( x, y, velocity, w, h, path );
return proj;
}
class player;
class enemy
{
protected:
SDL_Surface* spriteSheet;
SDL_Rect walk_left[3];
int x, y, w, h, xVel, hitDamage, frame;
virtual void setClips();
void handle_animation();
public:
enemy( std::string path, int X, int Y, int W, int H, int damage = 5, int VEL = -2 );
~enemy();
void move();
void show();
void shootBullet();
int getDamage() const { return hitDamage; }
SDL_Rect getStats();
};
void enemy::shootBullet()
{
static int counter = SDL_GetTicks();
if( SDL_GetTicks() - counter >= 1000 )
{
allProjectiles.push_back( spawnProjectile( x - 10, y, 10, 10, -3, "Lazer.png" ) );
counter = SDL_GetTicks();
}
}
SDL_Rect enemy::getStats()
{
SDL_Rect temp = {x, y, w, h};
return temp;
}
void enemy::show()
{
blitSurface( x, y, spriteSheet, &walk_left[frame] );
}
void enemy::setClips()
{
}
void enemy::move()
{
x += xVel;
if( x + w < 0 )
{
x = SCREEN_WIDTH;
y = rand() % SCREEN_HEIGHT;
}
handle_animation();
}
void enemy::handle_animation()
{
frame = (SDL_GetTicks() / 150) % 3;
if( frame > 3 )
{
frame = 0;
}
}
enemy::enemy( std::string path, int X, int Y, int W, int H, int damage, int VEL ):
x(X),
y(Y),
w(W),
h(H),
xVel(VEL),
hitDamage(damage),
frame(0)
{
setClips();
spriteSheet = loadImage( path.c_str() );
}
enemy::~enemy()
{
SDL_FreeSurface( spriteSheet );
}
class bunny : public enemy
{
private:
void setClips();
public:
bunny( std::string path, int X, int Y, int W, int H, int damage, int VEL ):
enemy::enemy( path, X, Y, W, H, damage, VEL )
{
setClips();
}
};
void bunny::setClips()
{
walk_left[0].x = 0;
walk_left[0].y = 0;
walk_left[0].w = 39;
walk_left[0].h = 44;
walk_left[1].x = 43;
walk_left[1].y = 2;
walk_left[1].w = 39;
walk_left[1].h = 44;
walk_left[2].x = 87;
walk_left[2].y = 5;
walk_left[2].w = 39;
walk_left[2].h = 44;
}
bunny createBunny( int x, int y )
{
bunny bunny( "Bunny.png", x, y, 39, 44, 5, -1 );
return bunny;
}
class player
{
private:
int x, y, w, h, yVel;
SDL_Surface* sprite;
public:
void move();
void show();
void handle_events();
player( int X, int Y, int W, int H, std::string path );
~player();
};
player::player( int X, int Y, int W, int H, std::string path ):
x(X),
y(W),
w(W),
h(H),
yVel(0)
{
sprite = loadImage( path.c_str() );
}
player::~player()
{
SDL_FreeSurface( sprite );
}
void player::handle_events()
{
if( event.type == SDL_KEYDOWN )
{
switch( event.key.keysym.sym )
{
case(SDLK_w): yVel-= 3; break;
case(SDLK_s): yVel+= 3; break;
}
}
if( event.type == SDL_KEYUP )
{
switch( event.key.keysym.sym )
{
case(SDLK_w): yVel+= 3; break;
case(SDLK_s): yVel-= 3; break;
}
}
}
void player::move()
{
y += yVel;
if( (y + h) > SCREEN_HEIGHT - 10 )
{
y -= yVel;
backgroundCam.y++;
}
if( backgroundCam.y + SCREEN_HEIGHT > backgroundCam.h )
{
backgroundCam.y--;
}
if( y < 10 )
{
y -= yVel;
backgroundCam.y-=2;
}
if( backgroundCam.y < 0 )
{
backgroundCam.y+=2;
}
}
void player::show()
{
SDL_Rect clip;
clip.x = 385;
clip.y = 11;
blitSurface( x, y, sprite, &clip );
}
//THIS DELETES THE REDUNDANT BULLETS
void handleProjectiles()
{
if( !allProjectiles.empty() )
{
std::vector<projectile>::iterator it = allProjectiles.begin();
for( ; it != allProjectiles.end(); it++ )
{
it->x += it->velocity;
it->show();
if( it->x + it->w < 0 )
{
allProjectiles.erase( allProjectiles.begin(), it );
}
}
}
}
int main( int argv, char* argc[] )
{
//Initialisation stage
init( "Space Game!" );
font = TTF_OpenFont( "arial.ttf", 15 );
songs[0] = Mix_LoadMUS( "music.ogg" );
songs[1] = Mix_LoadMUS( "music3.ogg" );
Mix_PlayMusic( songs[0], 0 );
Mix_VolumeMusic( 20 );
//Determines whether the game will run
bool quit = false;
player player( 50, 0, 153, 36, "Superman.png" );
SDL_Surface* background = loadImage( "Background.JPG" );
bunny bun = createBunny( 800, 20 );
while( !quit )
{
//Event handling
while( SDL_PollEvent(&event) )
{
if( event.type == SDL_QUIT )
{
quit = true;
}
player.handle_events();
}
player.move();
bun.move();
//Clears the previous frame
clearScreen();
//Rendering
//blitSurface( 0, 0, background, &backgroundCam );
player.show();
bun.show();
bun.shootBullet();
handleProjectiles();
SDL_Flip( screen );
SDL_Delay(20);
handleMusic();
}
SDL_FreeSurface( background );
clearUp();
return 0;
}