507 lines
11 KiB
C++
Executable File
507 lines
11 KiB
C++
Executable File
#include "Game.h"
|
|
#include "SpriteStrip.h"
|
|
#include "Actor.h"
|
|
#include "Display2D.h"
|
|
#include <SDL_mixer.h>
|
|
#include <SDL.h>
|
|
#include <iostream>
|
|
|
|
Game::Game()
|
|
{
|
|
this->musicVolume = 128;
|
|
this->soundVolume = 128;
|
|
this->lastNumKeys = 0;
|
|
this->lastKeyState = NULL;
|
|
this->fpslock = 0;
|
|
this->realfps = 0;
|
|
return;
|
|
}
|
|
|
|
Game::~Game()
|
|
{
|
|
if ( this->canvas != NULL ) {
|
|
SDL_FreeSurface(this->canvas);
|
|
}
|
|
|
|
}
|
|
|
|
int Game::initSDL(int audio_rate, Uint16 audio_format, int audio_channels, int audio_buffers)
|
|
{
|
|
if ( SDL_Init(SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) != 0 ) {
|
|
//std::cerr << "Failed to initialize SDL. Error was: " << SDL_GetError() << "\n";
|
|
return 1;
|
|
}
|
|
|
|
if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers) != 0) {
|
|
//std::cerr << "Unable to initialize audio: " << Mix_GetError() << "\n";
|
|
exit(1);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Game::initVideo(int w, int h, int depth, int flags)
|
|
{
|
|
this->canvas = SDL_SetVideoMode(w, h, depth, flags);
|
|
if ( this->canvas == NULL ) {
|
|
//std::cerr << "Failed to create new SDL display. Error was: " << SDL_GetError() << "\n";
|
|
return 1;
|
|
}
|
|
////std::cerr << "Created new SDL display at " << this->canvas << "\n";
|
|
return 0;
|
|
}
|
|
|
|
void Game::update(int logicOnly)
|
|
{
|
|
DisplayList::iterator displayIter;
|
|
SDL_Surface *curFrame = NULL;
|
|
Display *display = NULL;
|
|
Uint8 *keyState = NULL;
|
|
int numKeys = 0;
|
|
int gfxframe = 1;
|
|
static unsigned int lastTime = 0;
|
|
static unsigned int lastfps = 0;
|
|
static unsigned int realFPStimer = 0;
|
|
SDL_Rect screen = {0, 0, this->canvas->w, this->canvas->h};
|
|
Vector displaypos;
|
|
|
|
SDL_PumpEvents();
|
|
|
|
if ( (this->fpslock != 0) && (SDL_GetTicks() - lastTime) >= (1000/this->fpslock) ) {
|
|
gfxframe = 1;
|
|
lastTime = SDL_GetTicks();
|
|
} else if (this->fpslock != 0) {
|
|
return;
|
|
}
|
|
|
|
if ( (SDL_GetTicks() - realFPStimer) > 1000 ) {
|
|
this->realfps = lastfps;
|
|
lastfps = 0;
|
|
realFPStimer = SDL_GetTicks();
|
|
} else {
|
|
lastfps++;
|
|
}
|
|
|
|
if ( logicOnly == 0 ) {
|
|
SDL_FillRect(this->canvas, &screen, 0);
|
|
}
|
|
for ( displayIter = this->windows.begin(); displayIter != this->windows.end() ; displayIter++ ) {
|
|
display = (*displayIter);
|
|
//std::cerr << "Updating display " << display << "\n";
|
|
display->update();
|
|
if ( logicOnly == 1 ) {
|
|
continue;
|
|
}
|
|
|
|
curFrame = display->nextFrame();
|
|
displaypos = display->getPosition();
|
|
//std::cerr << "Position of " << display << " " << displaypos.x << "x" << displaypos.y << "\n";
|
|
if ( curFrame && curFrame != this->canvas ) {
|
|
//std::cerr << "Blitting display " << display << " canvas " << curFrame << " to main canvas " << this->canvas << "(" << displaypos.x << "," << displaypos.y << ")...\n";
|
|
SDL_Rect destRect = {(Sint16) displaypos.x, (Sint16) displaypos.y, 0, 0};
|
|
SDL_BlitSurface(curFrame, NULL, this->canvas, &destRect);
|
|
//this->blitSprite(curFrame, 0, 0);
|
|
} else if ( curFrame == this->canvas ) {
|
|
//std::cerr << "Not blitting display window " << display << " to our canvas " << this->canvas << " because it is sharing our canvas at " << curFrame << "\n";
|
|
} else if ( curFrame == NULL ) {
|
|
//std::cerr << "display " << display << " has a NULL canvas\n";
|
|
}
|
|
}
|
|
|
|
if ( this->lastKeyState != NULL ) {
|
|
delete this->lastKeyState;
|
|
}
|
|
keyState = SDL_GetKeyState(&numKeys);
|
|
this->lastKeyState = new Uint8[numKeys];
|
|
if ( this->lastKeyState != NULL ) {
|
|
memcpy(this->lastKeyState, keyState, (sizeof(Uint8)*numKeys));
|
|
}
|
|
|
|
//this->handleEvents();
|
|
this->cleanSounds();
|
|
}
|
|
|
|
/*int Game::handleControlEvent(SDL_Event *event)
|
|
{
|
|
switch(event->type) {
|
|
case SDL_KEYUP:
|
|
if ( event->key.state == SDL_RELEASED ) {
|
|
if ( event->key.keysym.sym == SDLK_ESCAPE ) {
|
|
exit(0);
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Game::handleEvents()
|
|
{
|
|
SDL_Event nextEvent;
|
|
while ( SDL_PollEvent(&nextEvent) ) {
|
|
switch(nextEvent.type) {
|
|
case SDL_KEYUP:
|
|
this->handleControlEvent(&nextEvent);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
*/
|
|
int Game::playMusic(std::string filename)
|
|
{
|
|
Mix_HaltMusic();
|
|
if ( this->bgmusic )
|
|
Mix_FreeMusic(this->bgmusic);
|
|
this->bgmusic = Mix_LoadMUS(filename.c_str());
|
|
if ( this->bgmusic == NULL ) {
|
|
//std::cerr << "Unable to load " << filename.c_str() << " to play music.\n";
|
|
return 1;
|
|
}
|
|
if ( Mix_PlayMusic(this->bgmusic, -1) == -1 ) {
|
|
//std::cerr << "Unable to play background music. " << Mix_GetError() << " \n";
|
|
return 1;
|
|
}
|
|
Mix_VolumeMusic(this->musicVolume);
|
|
return 0;
|
|
}
|
|
|
|
void Game::haltMusic()
|
|
{
|
|
Mix_HaltMusic();
|
|
if ( this->bgmusic )
|
|
Mix_FreeMusic(this->bgmusic);
|
|
this->bgmusic = NULL;
|
|
}
|
|
|
|
int Game::playSound(std::string filename, int loops)
|
|
{
|
|
PlayingSound *sndstruct = NULL;
|
|
Mix_Chunk *sound = NULL;
|
|
int channel = 0;
|
|
|
|
sound = Mix_LoadWAV(filename.c_str());
|
|
if ( sound == NULL ) {
|
|
return 1;
|
|
}
|
|
|
|
channel = Mix_PlayChannel(-1, sound, loops);
|
|
if ( channel > -1 ) {
|
|
//std::cerr << "Pushing sound chunk " << sound << " on channel " << channel << "\n";
|
|
sndstruct = new PlayingSound();
|
|
sndstruct->sound = sound;
|
|
sndstruct->channel = channel;
|
|
this->playingSounds.push_back(sndstruct);
|
|
} else {
|
|
Mix_FreeChunk(sound);
|
|
return 1;
|
|
}
|
|
Mix_Volume(sndstruct->channel, this->soundVolume);
|
|
return 0;
|
|
}
|
|
|
|
void Game::cleanSounds(int force)
|
|
{
|
|
PlayingSoundList::iterator iter;
|
|
PlayingSoundList::iterator newIter;
|
|
PlayingSound *curSound = NULL;
|
|
iter = this->playingSounds.begin() ;
|
|
|
|
while ( iter != this->playingSounds.end()) {
|
|
curSound = *iter;
|
|
if ( curSound == NULL ) {
|
|
iter++;
|
|
continue;
|
|
}
|
|
|
|
if ( Mix_Playing(curSound->channel) != 0 && force == 1) {
|
|
Mix_HaltChannel(curSound->channel);
|
|
} else if ( Mix_Playing(curSound->channel) != 0 ) {
|
|
iter++;
|
|
continue;
|
|
}
|
|
|
|
newIter = iter;
|
|
iter++;
|
|
Mix_FreeChunk(curSound->sound);
|
|
//std::cerr << "Cleared sound at channel" << curSound->channel << "\n";
|
|
iter = this->playingSounds.erase(newIter);
|
|
delete curSound;
|
|
//iter++;
|
|
}
|
|
}
|
|
|
|
void Game::setMusicVolume(int volume)
|
|
{
|
|
this->musicVolume = volume;
|
|
Mix_VolumeMusic(this->musicVolume);
|
|
}
|
|
|
|
void Game::setSoundVolume(int volume)
|
|
{
|
|
this->soundVolume = volume;
|
|
Mix_Volume(-1, this->soundVolume);
|
|
}
|
|
|
|
int Game::keyHeldDown(int keysym)
|
|
{
|
|
Uint8 *keyState = NULL;
|
|
int numKeys = 0;
|
|
|
|
keyState = SDL_GetKeyState(&numKeys);
|
|
if ( this->lastKeyState == NULL ) {
|
|
return 0;
|
|
}
|
|
if ( keysym < this->lastNumKeys && keysym < numKeys ) {
|
|
return 0;
|
|
}
|
|
if ( this->lastKeyState[keysym] + keyState[keysym] == 2 ) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// ------------ class factory and memory management stuff
|
|
|
|
SpriteStrip *Game::newSpriteStrip(std::string key)
|
|
{
|
|
SpriteStrip *obj = new SpriteStrip();
|
|
if ( obj == NULL )
|
|
return NULL;
|
|
if ( key != "" ) {
|
|
if ( this->addSpriteStrip(obj, key) != 0 ) {
|
|
delete obj;
|
|
return NULL;
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
int Game::freeSpriteStrip(std::string key, SpriteStrip *obj)
|
|
{
|
|
if ( obj == NULL && this->spriteMap.count(key) == 0 ) {
|
|
return 1;
|
|
} else if ( obj == NULL ) {
|
|
obj = this->spriteMap[key];
|
|
}
|
|
this->spriteMap.erase(key);
|
|
delete obj;
|
|
}
|
|
|
|
Animation *Game::newAnimation(std::string key)
|
|
{
|
|
Animation *obj = new Animation();
|
|
if ( obj == NULL )
|
|
return NULL;
|
|
if ( key != "" ) {
|
|
if ( this->addAnimation(obj, key) != 0 ) {
|
|
delete obj;
|
|
return NULL;
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
int Game::freeAnimation(std::string key, Animation *obj)
|
|
{
|
|
if ( obj == NULL && this->animationMap.count(key) == 0 ) {
|
|
return 1;
|
|
} else if ( obj == NULL ) {
|
|
obj = this->animationMap[key];
|
|
}
|
|
this->animationMap.erase(key);
|
|
delete obj;
|
|
}
|
|
|
|
Actor *Game::newActor(std::string key)
|
|
{
|
|
Actor *obj = new Actor();
|
|
if ( obj == NULL )
|
|
return NULL;
|
|
if ( key != "" ) {
|
|
if ( this->addActor(obj, key) != 0 ) {
|
|
delete obj;
|
|
return NULL;
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
int Game::freeActor(std::string key, Actor *obj)
|
|
{
|
|
if ( obj == NULL && this->actorMap.count(key) == 0 ) {
|
|
return 1;
|
|
} else if ( obj == NULL ) {
|
|
obj = this->actorMap[key];
|
|
}
|
|
this->actorMap.erase(key);
|
|
delete obj;
|
|
}
|
|
|
|
|
|
Display2D *Game::newDisplay2D(std::string key)
|
|
{
|
|
Display2D *obj = new Display2D();
|
|
if ( obj == NULL )
|
|
return NULL;
|
|
if ( key != "" ) {
|
|
if ( this->addDisplay(obj, key) != 0 ) {
|
|
delete obj;
|
|
return NULL;
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
int Game::freeDisplay2D(std::string key, Display2D *obj)
|
|
{
|
|
if ( obj == NULL && this->displayMap.count(key) == 0 ) {
|
|
return 1;
|
|
} else if ( obj == NULL ) {
|
|
obj = (Display2D *)this->displayMap[key];
|
|
}
|
|
this->displayMap.erase(key);
|
|
delete obj;
|
|
}
|
|
|
|
MenuDisplay *Game::newMenuDisplay(std::string key)
|
|
{
|
|
MenuDisplay *obj = new MenuDisplay();
|
|
if ( obj == NULL )
|
|
return NULL;
|
|
if ( key != "" ) {
|
|
if ( this->addDisplay(obj, key) != 0 ) {
|
|
delete obj;
|
|
return NULL;
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
int Game::freeMenuDisplay(std::string key, MenuDisplay *obj)
|
|
{
|
|
if ( obj == NULL && this->displayMap.count(key) == 0 ) {
|
|
return 1;
|
|
} else if ( obj == NULL ) {
|
|
obj = (MenuDisplay *)this->displayMap[key];
|
|
}
|
|
this->displayMap.erase(key);
|
|
delete obj;
|
|
}
|
|
|
|
int Game::addSpriteStrip(SpriteStrip *strip, std::string key)
|
|
{
|
|
if ( strip == NULL || this->spriteMap.count(key) > 0 )
|
|
return 1;
|
|
this->spriteMap[key] = strip;
|
|
return 0;
|
|
}
|
|
|
|
SpriteStrip *Game::getSpriteStrip(std::string key)
|
|
{
|
|
if ( this->spriteMap.count(key) > 0 ) {
|
|
return this->spriteMap[key];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int Game::removeSpriteStrip(std::string stripName)
|
|
{
|
|
if ( this->spriteMap.count(stripName) > 0 ) {
|
|
this->spriteMap.erase(stripName);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int Game::addAnimation(Animation *ptr, std::string key)
|
|
{
|
|
if ( ptr != NULL || this->animationMap.count(key) == 0 ) {
|
|
this->animationMap[key] = ptr;
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
Animation *Game::getAnimation(std::string key)
|
|
{
|
|
if ( this->animationMap.count(key) > 0 ) {
|
|
return this->animationMap[key];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int Game::removeAnimation(std::string key)
|
|
{
|
|
if ( this->animationMap.count(key) > 0 ) {
|
|
this->animationMap.erase(key);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int Game::addActor(Actor *ptr, std::string key)
|
|
{
|
|
if ( ptr != NULL || this->actorMap.count(key) == 0 ) {
|
|
this->actorMap[key] = ptr;
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
Actor *Game::getActor(std::string key)
|
|
{
|
|
if ( this->actorMap.count(key) > 0 ) {
|
|
return this->actorMap[key];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int Game::removeActor(std::string key)
|
|
{
|
|
if ( this->actorMap.count(key) > 0 ) {
|
|
this->actorMap.erase(key);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int Game::addDisplay(Display *ptr, std::string key)
|
|
{
|
|
if ( ptr != NULL || this->displayMap.count(key) == 0 ) {
|
|
this->displayMap[key] = ptr;
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
Display *Game::getDisplay(std::string key)
|
|
{
|
|
if ( this->displayMap.count(key) > 0 ) {
|
|
return this->displayMap[key];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int Game::removeDisplay(std::string key)
|
|
{
|
|
if ( this->displayMap.count(key) > 0 ) {
|
|
this->displayMap.erase(key);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
void Game::lockFPS(int fps)
|
|
{
|
|
this->fpslock = fps;
|
|
}
|
|
|
|
void Game::finishFrame()
|
|
{
|
|
SDL_Flip(this->canvas);
|
|
}
|
|
|
|
SDL_Surface *Game::getCanvas()
|
|
{
|
|
return this->canvas;
|
|
}
|