[Add] New memory management.

[Clean] Source code was messy, so I have given it a good clean.
This commit is contained in:
Rtch90 2012-06-02 21:54:35 +01:00
parent d16472c28e
commit 896b966530
45 changed files with 2291 additions and 2011 deletions

View File

@ -12,7 +12,6 @@ HEADERS += ../src/Libs/wglext.h \
../src/libUnuk/Engine/WorldManager.h \ ../src/libUnuk/Engine/WorldManager.h \
../src/libUnuk/Engine/ParticleEmitter.h \ ../src/libUnuk/Engine/ParticleEmitter.h \
../src/libUnuk/Engine/NPC.h \ ../src/libUnuk/Engine/NPC.h \
../src/libUnuk/Engine/MemManager.h \
../src/libUnuk/Engine/MemClass.h \ ../src/libUnuk/Engine/MemClass.h \
../src/libUnuk/Engine/Collision.h \ ../src/libUnuk/Engine/Collision.h \
../src/libUnuk/Engine/Character.h \ ../src/libUnuk/Engine/Character.h \
@ -49,11 +48,11 @@ HEADERS += ../src/Libs/wglext.h \
../src/libUnuk/System/MathBox.h \ ../src/libUnuk/System/MathBox.h \
../src/libUnuk/Engine/Pathfinding.h \ ../src/libUnuk/Engine/Pathfinding.h \
../src/libUnuk/UI/SavegameMenu.h \ ../src/libUnuk/UI/SavegameMenu.h \
../src/libUnuk/Engine/Spells.h ../src/libUnuk/Engine/Spells.h \
../src/libUnuk/Engine/MemManager.h
SOURCES += ../src/libUnuk/Engine/WorldManager.cpp \ SOURCES += ../src/libUnuk/Engine/WorldManager.cpp \
../src/libUnuk/Engine/ParticleEmitter.cpp \ ../src/libUnuk/Engine/ParticleEmitter.cpp \
../src/libUnuk/Engine/NPC.cpp \ ../src/libUnuk/Engine/NPC.cpp \
../src/libUnuk/Engine/MemManager.cpp \
../src/libUnuk/Engine/Collision.cpp \ ../src/libUnuk/Engine/Collision.cpp \
../src/libUnuk/Engine/Character.cpp \ ../src/libUnuk/Engine/Character.cpp \
../src/libUnuk/Sprite/TextureManager.cpp \ ../src/libUnuk/Sprite/TextureManager.cpp \
@ -86,4 +85,5 @@ SOURCES += ../src/libUnuk/Engine/WorldManager.cpp \
../src/libUnuk/UI/Bar.cpp \ ../src/libUnuk/UI/Bar.cpp \
../src/libUnuk/System/Vec2.cpp \ ../src/libUnuk/System/Vec2.cpp \
../src/libUnuk/UI/SavegameMenu.cpp \ ../src/libUnuk/UI/SavegameMenu.cpp \
../src/libUnuk/Engine/Spells.cpp ../src/libUnuk/Engine/Spells.cpp \
../src/libUnuk/Engine/MemManager.cpp

View File

@ -5,470 +5,472 @@
#include "../libUnuk/UI/EventHistory.h" #include "../libUnuk/UI/EventHistory.h"
Game::Game(void) { Game::Game(void) {
Debug::logger->message("Creating characters.."); Debug::logger->message("Creating characters..");
_player = new Player(&_map); _player = new Player(&_map);
_map.SetPlayer(_player); _map.SetPlayer(_player);
_runGameReturnValue = gameMainMenu; _runGameReturnValue = gameMainMenu;
} }
Game::~Game(void) { Game::~Game(void) {
Debug::logger->message("\n----- Cleaning Up ------"); Debug::logger->message("\n----- Cleaning Up ------");
// cleaning _player up caused a nice seg fault. I'll look later. // cleaning _player up caused a nice seg fault. I'll look later.
//delete _player; //delete _player;
} }
void Game::New(const string& savegameIDArg) { void Game::New(const string& savegameIDArg) {
_saveGameID = savegameIDArg; _saveGameID = savegameIDArg;
NewSavegame(savegameIDArg); NewSavegame(savegameIDArg);
int spawnX; int spawnX;
int spawnY; int spawnY;
_map.FindSpawnPoint(spawnX, spawnY, 40, 45); _map.FindSpawnPoint(spawnX, spawnY, 40, 45);
_player->SetXY((float)spawnX, (float)spawnY); _player->SetXY((float)spawnX, (float)spawnY);
} }
void Game::Load(const string& savegameIDArg) { void Game::Load(const string& savegameIDArg) {
_saveGameID = savegameIDArg; _saveGameID = savegameIDArg;
LoadSavegame(savegameIDArg); LoadSavegame(savegameIDArg);
int spawnX; int spawnX;
int spawnY; int spawnY;
_map.FindSpawnPoint(spawnX, spawnY, 40, 45); _map.FindSpawnPoint(spawnX, spawnY, 40, 45);
_player->SetXY((float)spawnX, (float)spawnY); _player->SetXY((float)spawnX, (float)spawnY);
} }
gameNavVal_t Game::Run(void) { gameNavVal_t Game::Run(void) {
_player->LoadSprites("../Data/Media/Images/Characters/Reniesta.png", 40, 45); _player->LoadSprites("../Data/Media/Images/Characters/Reniesta.png", 40, 45);
int fps = 0; int fps = 0;
int frame = 0; int frame = 0;
int nextGameTick = SDL_GetTicks(); int nextGameTick = SDL_GetTicks();
Timer frameTimer; Timer frameTimer;
frameTimer.Start(); frameTimer.Start();
Timer fpsCalc; Timer fpsCalc;
fpsCalc.Start(); fpsCalc.Start();
Timer renderTimer; Timer renderTimer;
Timer updateTimer; Timer updateTimer;
stringstream playerHealth; stringstream playerHealth;
_playerHealth.SetXY(15, 27); _playerHealth.SetXY(15, 27);
_playerHealth.SetTextBlended("Player Health - XX", vsmall, COLOUR_WHITE); _playerHealth.SetTextBlended("Player Health - XX", vsmall, COLOUR_WHITE);
stringstream playerExp; stringstream playerExp;
_playerExp.SetXY(15, 57); _playerExp.SetXY(15, 57);
_playerExp.SetTextBlended("Player Level XX (XX/XX)", vsmall, COLOUR_WHITE); _playerExp.SetTextBlended("Player Level XX (XX/XX)", vsmall, COLOUR_WHITE);
_gameRenderTime.SetXY(10, 90); _gameRenderTime.SetXY(10, 90);
_gameRenderTime.SetTextBlended("Render - XX", vsmall, COLOUR_BLACK); _gameRenderTime.SetTextBlended("Render - XX", vsmall, COLOUR_BLACK);
_gameUpdateTime.SetXY(10, 110); _gameUpdateTime.SetXY(10, 110);
_gameUpdateTime.SetTextBlended("Update - XX", vsmall, COLOUR_BLACK); _gameUpdateTime.SetTextBlended("Update - XX", vsmall, COLOUR_BLACK);
stringstream playerXYString; stringstream playerXYString;
_playerXY.SetXY(10, 130); _playerXY.SetXY(10, 130);
_playerXY.SetTextBlended("Player coords - XX XX", vsmall, COLOUR_BLACK); _playerXY.SetTextBlended("Player coords - XX XX", vsmall, COLOUR_BLACK);
_playerHealthBar.SetBackgroundRGB(0, 0, 0); _playerHealthBar.SetBackgroundRGB(0, 0, 0);
_playerHealthBar.SetForegroundRGB(255, 0, 0); _playerHealthBar.SetForegroundRGB(255, 0, 0);
_playerHealthBar.SetXY(10, 20); _playerHealthBar.SetXY(10, 20);
_playerHealthBar.SetWidthHeight(200, 25); _playerHealthBar.SetWidthHeight(200, 25);
_playerExpBar.SetBackgroundRGB(0, 0, 0); _playerExpBar.SetBackgroundRGB(0, 0, 0);
_playerExpBar.SetForegroundRGB(0, 0, 255); _playerExpBar.SetForegroundRGB(0, 0, 255);
_playerExpBar.SetXY(10, 50); _playerExpBar.SetXY(10, 50);
_playerExpBar.SetWidthHeight(200, 25); _playerExpBar.SetWidthHeight(200, 25);
_playerExpBar.SetProgress(0.0f); _playerExpBar.SetProgress(0.0f);
eventHistory = new EventHistory(); eventHistory = new EventHistory();
_gameRunning = true; _gameRunning = true;
while(_gameRunning) { while(_gameRunning) {
bool stillRunning = true; bool stillRunning = true;
updateTimer.Start(); updateTimer.Start();
while((int)SDL_GetTicks() > nextGameTick) { while((int)SDL_GetTicks() > nextGameTick) {
HandleInput(); HandleInput();
if (!_gameRunning) { if (!_gameRunning) {
stillRunning = false; stillRunning = false;
break; break;
} }
UpdateGame(); UpdateGame();
nextGameTick += SKIP_TICKS; nextGameTick += SKIP_TICKS;
} }
updateTimer.Pause(); updateTimer.Pause();
if (!stillRunning) { if (!stillRunning) {
break; break;
} }
renderTimer.Start(); renderTimer.Start();
Render(); Render();
renderTimer.Pause(); renderTimer.Pause();
// Calculate and display our FPS. // Calculate and display our FPS.
if(fpsCalc.GetTicks() >= 1000) { if(fpsCalc.GetTicks() >= 1000) {
fps = frame / (fpsCalc.GetTicks() / 1000); fps = frame / (fpsCalc.GetTicks() / 1000);
stringstream caption; stringstream caption;
caption << "Unuk - FPS: " << fps; caption << "Unuk - FPS: " << fps;
SDL_WM_SetCaption(caption.str().c_str(), NULL); SDL_WM_SetCaption(caption.str().c_str(), NULL);
fpsCalc.Start(); fpsCalc.Start();
frame = 0; frame = 0;
playerHealth.str(""); playerHealth.str("");
playerHealth << "Player Health - " << _player->GetHealth(); playerHealth << "Player Health - " << _player->GetHealth();
_playerHealth.SetTextBlended(playerHealth.str(), vsmall, COLOUR_WHITE); _playerHealth.SetTextBlended(playerHealth.str(), vsmall, COLOUR_WHITE);
_playerHealthBar.SetProgress((float)_player->GetHealth() / 100.0f); _playerHealthBar.SetProgress((float)_player->GetHealth() / 100.0f);
playerExp.str(""); playerExp.str("");
playerExp << "Player Level " << _player->GetLevel() << " (" << _player->GetExp() << "/" << Player::EXP_TABLE[_player->GetLevel() - 1] << ")"; playerExp << "Player Level " << _player->GetLevel() << " (" << _player->GetExp() << "/" << Player::EXP_TABLE[_player->GetLevel() - 1] << ")";
_playerExp.SetTextBlended(playerExp.str(), vsmall, COLOUR_WHITE); _playerExp.SetTextBlended(playerExp.str(), vsmall, COLOUR_WHITE);
_playerExpBar.SetProgress((float)_player->GetExp() / (float)Player::EXP_TABLE[_player->GetLevel() - 1]); _playerExpBar.SetProgress((float)_player->GetExp() / (float)Player::EXP_TABLE[_player->GetLevel() - 1]);
// Check to see if we are allowed to display debug info. // Check to see if we are allowed to display debug info.
if(debugEnabled) { if(debugEnabled) {
_gameUpdateTime.SetTextBlended("Update - " + updateTimer.GetTicksStr(), vsmall, COLOUR_BLACK); _gameUpdateTime.SetTextBlended("Update - " + updateTimer.GetTicksStr(), vsmall, COLOUR_BLACK);
_gameRenderTime.SetTextBlended("Render - " + renderTimer.GetTicksStr(), vsmall, COLOUR_BLACK); _gameRenderTime.SetTextBlended("Render - " + renderTimer.GetTicksStr(), vsmall, COLOUR_BLACK);
playerXYString.str(""); playerXYString.str("");
playerXYString << "Player coords: x" << _player->GetX() << ", y" << _player->GetY(); playerXYString << "Player coords: x" << _player->GetX() << ", y" << _player->GetY();
_playerXY.SetTextBlended(playerXYString.str(), vsmall, COLOUR_BLACK); _playerXY.SetTextBlended(playerXYString.str(), vsmall, COLOUR_BLACK);
} }
} }
// Restrict the fps. // Restrict the fps.
if(1000 / MAX_FPS > frameTimer.GetTicks()) { if(1000 / MAX_FPS > frameTimer.GetTicks()) {
// SDL_Delay does not accept a float so for higher framerate // SDL_Delay does not accept a float so for higher framerate
// limits there's an innacuracy. This is as much as 3fps // limits there's an innacuracy. This is as much as 3fps
// at a limit of 60fps. // at a limit of 60fps.
SDL_Delay((1000 / MAX_FPS) - frameTimer.GetTicks()); SDL_Delay((1000 / MAX_FPS) - frameTimer.GetTicks());
} }
frameTimer.Start(); frameTimer.Start();
frame++; frame++;
} }
delete eventHistory; delete eventHistory;
return _runGameReturnValue; return _runGameReturnValue;
} }
void Game::HandleInput(void) { void Game::HandleInput(void) {
if(_ingameMenu.GetStatus() == false) { if(_ingameMenu.GetStatus() == false) {
while(SDL_PollEvent(&event)) { while(SDL_PollEvent(&event)) {
_player->HandleInput(); _player->HandleInput();
if(event.key.type == SDL_KEYDOWN) { if(event.key.type == SDL_KEYDOWN) {
if(event.key.keysym.sym == SDLK_ESCAPE) if(event.key.keysym.sym == SDLK_ESCAPE)
_ingameMenu.SetStatus(true); _ingameMenu.SetStatus(true);
if(event.key.keysym.sym == SDLK_p) if(event.key.keysym.sym == SDLK_p)
debugEnabled = !debugEnabled; debugEnabled = !debugEnabled;
if(event.key.keysym.sym == SDLK_0) if(event.key.keysym.sym == SDLK_0)
eventHistory->LogEvent("Item gained."); eventHistory->LogEvent("Item gained.");
} }
else if(event.type == SDL_QUIT) { else if(event.type == SDL_QUIT) {
_gameRunning = false; _gameRunning = false;
_runGameReturnValue = gameQuitGame; _runGameReturnValue = gameQuitGame;
break; break;
} }
} }
} else { } else {
switch(_ingameMenu.HandleInput()) { switch(_ingameMenu.HandleInput()) {
case ingameMenuNothing: case ingameMenuNothing:
break; break;
case ingameMenuResume: case ingameMenuResume:
_ingameMenu.SetStatus(false); _ingameMenu.SetStatus(false);
break; break;
case ingameMenuSaveGame: case ingameMenuSaveGame:
SaveSavegame(); SaveSavegame();
_ingameMenu.SetStatus(false); _ingameMenu.SetStatus(false);
Debug::logger->message("Game Saved!"); Debug::logger->message("Game Saved!");
break; break;
case ingameMenuLoadGame: case ingameMenuLoadGame:
LoadSavegame(_saveGameID); LoadSavegame(_saveGameID);
_ingameMenu.SetStatus(false); _ingameMenu.SetStatus(false);
Debug::logger->message("Game Loaded!"); Debug::logger->message("Game Loaded!");
break; break;
case ingameMenuOptions: case ingameMenuOptions:
break; break;
case ingameMenuMainMenu: case ingameMenuMainMenu:
SDL_FillRect(screen, NULL, 0); SDL_FillRect(screen, NULL, 0);
_gameRunning = false; _gameRunning = false;
break; break;
} }
if(event.type == SDL_QUIT) { if(event.type == SDL_QUIT) {
_gameRunning = false; _gameRunning = false;
_ingameMenu.SetStatus(false); _ingameMenu.SetStatus(false);
_runGameReturnValue = gameQuitGame; _runGameReturnValue = gameQuitGame;
} }
} }
} }
void Game::UpdateGame(void) { void Game::UpdateGame(void) {
if(_ingameMenu.GetStatus() == false) { UpdateInput();
_map.Update(); if(_ingameMenu.GetStatus() == false) {
_player->Update(); _map.Update();
_player->Update();
if(gameOver) { if(gameOver) {
gameOver = false; gameOver = false;
_map.New(); _map.New();
_player->SetHealth(100); _player->SetHealth(100);
_player->SetLevelLiteral(1); _player->SetLevelLiteral(1);
_player->SetExpLiteral(0); _player->SetExpLiteral(0);
New(_saveGameID); New(_saveGameID);
} }
} else { } else {
// :D // :D
} }
} }
void Game::Render(void) { void Game::Render(void) {
//SDL_FillRect(screen, NULL, 0); // You might want to clear the buffer! --konom | I don't want a blacked out ingame menu, save it for MainMenu. --Allanis //SDL_FillRect(screen, NULL, 0);
if(_ingameMenu.GetStatus() == false) { if(_ingameMenu.GetStatus() == false) {
_map.Render(); _map.Render();
_player->Render(); _player->Render();
_playerHealthBar.DrawLiteral(); _playerHealthBar.DrawLiteral();
_playerHealth.RenderLiteral(); _playerHealth.RenderLiteral();
_playerExpBar.DrawLiteral(); _playerExpBar.DrawLiteral();
_playerExp.RenderLiteral(); _playerExp.RenderLiteral();
if(debugEnabled) { if(debugEnabled) {
_gameRenderTime.RenderLiteral(); _gameRenderTime.RenderLiteral();
_gameUpdateTime.RenderLiteral(); _gameUpdateTime.RenderLiteral();
_playerXY.RenderLiteral(); _playerXY.RenderLiteral();
_npcHealth.RenderLiteral(); _npcHealth.RenderLiteral();
} }
eventHistory->Render(); eventHistory->Render();
} else { } else {
_ingameMenu.Render(); _ingameMenu.Render();
} }
SDL_Flip(screen); SDL_Flip(screen);
} }
void Game::NewSavegame(const string savegameIDArg) { void Game::NewSavegame(const string savegameIDArg) {
string saveFilename = "../Save/" + savegameIDArg; string saveFilename = "../Save/" + savegameIDArg;
_map.New(); _map.New();
_map.Save(_saveGameID); _map.Save(_saveGameID);
TiXmlDocument doc; TiXmlDocument doc;
TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "", ""); TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "", "");
TiXmlElement* saveElement = new TiXmlElement("save"); TiXmlElement* saveElement = new TiXmlElement("save");
TiXmlElement* nameElement = new TiXmlElement("name"); TiXmlElement* nameElement = new TiXmlElement("name");
TiXmlText* nameText = new TiXmlText("Allanis"); //TODO: replace with _player->GetName() when it works. --konom TiXmlText* nameText = new TiXmlText("Allanis"); //TODO: replace with _player->GetName() when it works.
nameElement->LinkEndChild(nameText); nameElement->LinkEndChild(nameText);
int spawnX; int spawnX;
int spawnY; int spawnY;
_map.FindSpawnPoint(spawnX, spawnY, 40, 45); _map.FindSpawnPoint(spawnX, spawnY, 40, 45);
_player->SetXY(spawnX, spawnY); _player->SetXY(spawnX, spawnY);
std::stringstream xString; std::stringstream xString;
xString << spawnX; xString << spawnX;
TiXmlElement* xElement = new TiXmlElement("x"); TiXmlElement* xElement = new TiXmlElement("x");
TiXmlText* xText = new TiXmlText(xString.str().c_str()); TiXmlText* xText = new TiXmlText(xString.str().c_str());
xElement->LinkEndChild(xText); xElement->LinkEndChild(xText);
std::stringstream yString; std::stringstream yString;
yString << spawnY; yString << spawnY;
TiXmlElement* yElement = new TiXmlElement("y"); TiXmlElement* yElement = new TiXmlElement("y");
TiXmlText* yText = new TiXmlText(yString.str().c_str()); TiXmlText* yText = new TiXmlText(yString.str().c_str());
yElement->LinkEndChild(yText); yElement->LinkEndChild(yText);
_player->SetLevelLiteral(1); _player->SetLevelLiteral(1);
TiXmlElement* levelElement = new TiXmlElement("level"); TiXmlElement* levelElement = new TiXmlElement("level");
TiXmlText* levelText = new TiXmlText("1"); TiXmlText* levelText = new TiXmlText("1");
levelElement->LinkEndChild(levelText); levelElement->LinkEndChild(levelText);
_player->SetExpLiteral(0); _player->SetExpLiteral(0);
TiXmlElement* expElement = new TiXmlElement("exp"); TiXmlElement* expElement = new TiXmlElement("exp");
TiXmlText* expText = new TiXmlText("0"); TiXmlText* expText = new TiXmlText("0");
expElement->LinkEndChild(expText); expElement->LinkEndChild(expText);
TiXmlElement* healthElement = new TiXmlElement("health"); TiXmlElement* healthElement = new TiXmlElement("health");
TiXmlText* healthText = new TiXmlText("100"); TiXmlText* healthText = new TiXmlText("100");
healthElement->LinkEndChild(healthText); healthElement->LinkEndChild(healthText);
TiXmlElement* mapElement = new TiXmlElement("map"); TiXmlElement* mapElement = new TiXmlElement("map");
TiXmlText* mapText = new TiXmlText("map"); //TODO: replace with actual map name. TiXmlText* mapText = new TiXmlText("map"); //TODO: replace with actual map name.
mapElement->LinkEndChild(mapText); mapElement->LinkEndChild(mapText);
saveElement->LinkEndChild(nameElement); saveElement->LinkEndChild(nameElement);
saveElement->LinkEndChild(xElement); saveElement->LinkEndChild(xElement);
saveElement->LinkEndChild(yElement); saveElement->LinkEndChild(yElement);
saveElement->LinkEndChild(levelElement); saveElement->LinkEndChild(levelElement);
saveElement->LinkEndChild(expElement); saveElement->LinkEndChild(expElement);
saveElement->LinkEndChild(healthElement); saveElement->LinkEndChild(healthElement);
saveElement->LinkEndChild(mapElement); saveElement->LinkEndChild(mapElement);
doc.LinkEndChild(decl); doc.LinkEndChild(decl);
doc.LinkEndChild(saveElement); doc.LinkEndChild(saveElement);
doc.SaveFile(saveFilename.c_str()); doc.SaveFile(saveFilename.c_str());
} }
void Game::LoadSavegame(const string savegameIDArg) { void Game::LoadSavegame(const string savegameIDArg) {
_saveGameID = savegameIDArg; _saveGameID = savegameIDArg;
string saveFilename = "../Save/" + _saveGameID; string saveFilename = "../Save/" + _saveGameID;
// Converting to XML ftw! // Converting to XML ftw!
TiXmlDocument mapFile(saveFilename.c_str()); TiXmlDocument mapFile(saveFilename.c_str());
// Create new save if can't load file. // Create new save if can't load file.
if(!mapFile.LoadFile()) { if(!mapFile.LoadFile()) {
New(savegameIDArg); New(savegameIDArg);
return; return;
} }
TiXmlElement* rootElem = NULL; TiXmlElement* rootElem = NULL;
TiXmlElement* dataElem = NULL; TiXmlElement* dataElem = NULL;
// <save> - Grab a save file. // <save> - Grab a save file.
rootElem = mapFile.FirstChildElement("save"); rootElem = mapFile.FirstChildElement("save");
assert(rootElem != NULL); assert(rootElem != NULL);
if(rootElem) { if(rootElem) {
// <name> - Parse the player name. // <name> - Parse the player name.
dataElem = rootElem->FirstChildElement("name"); dataElem = rootElem->FirstChildElement("name");
assert(dataElem != NULL); assert(dataElem != NULL);
// Overloaded new/delete operator takes this out of scope.. // Overloaded new/delete operator takes this out of scope..
// TODO: Fix. // TODO: Fix.
//_player->SetName(dataElem->GetText()); //_player->SetName(dataElem->GetText());
// </name> // </name>
/* /*
// <x> - Parse the player x coord. // <x> - Parse the player x coord.
dataElem = dataElem->NextSiblingElement("x"); dataElem = dataElem->NextSiblingElement("x");
assert(dataElem != NULL); assert(dataElem != NULL);
int playerX = atoi(dataElem->GetText()); int playerX = atoi(dataElem->GetText());
// </x> // </x>
// <y> - Parse the player y coord. // <y> - Parse the player y coord.
dataElem = dataElem->NextSiblingElement("y"); dataElem = dataElem->NextSiblingElement("y");
assert(dataElem != NULL); assert(dataElem != NULL);
int playerY = atoi(dataElem->GetText()); int playerY = atoi(dataElem->GetText());
// </y> // </y>
_player->SetXY((float)playerX, (float)playerY); _player->SetXY((float)playerX, (float)playerY);
*/ */
// <level> - Parse the player level. // <level> - Parse the player level.
dataElem = dataElem->NextSiblingElement("level"); dataElem = dataElem->NextSiblingElement("level");
assert(dataElem != NULL); assert(dataElem != NULL);
int playerLevel = atoi(dataElem->GetText()); int playerLevel = atoi(dataElem->GetText());
// </level> // </level>
_player->SetLevelLiteral(playerLevel); _player->SetLevelLiteral(playerLevel);
// <exp> - Parse the player exp. // <exp> - Parse the player exp.
dataElem = dataElem->NextSiblingElement("exp"); dataElem = dataElem->NextSiblingElement("exp");
assert(dataElem != NULL); assert(dataElem != NULL);
int playerExp = atoi(dataElem->GetText()); int playerExp = atoi(dataElem->GetText());
// </exp> // </exp>
_player->SetExpLiteral(playerExp); _player->SetExpLiteral(playerExp);
// <health> - Parse the player health. // <health> - Parse the player health.
dataElem = dataElem->NextSiblingElement("health"); dataElem = dataElem->NextSiblingElement("health");
assert(dataElem != NULL); assert(dataElem != NULL);
int playerHealth = atoi(dataElem->GetText()); int playerHealth = atoi(dataElem->GetText());
// </health> // </health>
_player->SetHealthLiteral(playerHealth); _player->SetHealthLiteral(playerHealth);
} }
// <save> // <save>
// </save> // </save>
_map.Load(_saveGameID); _map.Load(_saveGameID);
} }
void Game::SaveSavegame(void) { void Game::SaveSavegame(void) {
string saveFilename = "../Save/" + _saveGameID; string saveFilename = "../Save/" + _saveGameID;
TiXmlDocument doc; TiXmlDocument doc;
TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "", ""); TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "", "");
TiXmlElement* saveElement = new TiXmlElement("save"); TiXmlElement* saveElement = new TiXmlElement("save");
TiXmlElement* nameElement = new TiXmlElement("name"); TiXmlElement* nameElement = new TiXmlElement("name");
TiXmlText* nameText = new TiXmlText("Allanis"); //TODO: replace with _player->GetName() when it works. --konom TiXmlText* nameText = new TiXmlText("Allanis"); //TODO: replace with _player->GetName() when it works. --konom
nameElement->LinkEndChild(nameText); nameElement->LinkEndChild(nameText);
/* /*
std::stringstream xString; std::stringstream xString;
xString << _player->GetX(); xString << _player->GetX();
TiXmlElement* xElement = new TiXmlElement("x"); TiXmlElement* xElement = new TiXmlElement("x");
TiXmlText* xText = new TiXmlText(xString.str().c_str()); TiXmlText* xText = new TiXmlText(xString.str().c_str());
xElement->LinkEndChild(xText); xElement->LinkEndChild(xText);
std::stringstream yString; std::stringstream yString;
yString << _player->GetY(); yString << _player->GetY();
TiXmlElement* yElement = new TiXmlElement("y"); TiXmlElement* yElement = new TiXmlElement("y");
TiXmlText* yText = new TiXmlText(yString.str().c_str()); TiXmlText* yText = new TiXmlText(yString.str().c_str());
yElement->LinkEndChild(yText); yElement->LinkEndChild(yText);
*/ */
std::stringstream levelString; std::stringstream levelString;
levelString << _player->GetLevel(); levelString << _player->GetLevel();
TiXmlElement* levelElement = new TiXmlElement("level"); TiXmlElement* levelElement = new TiXmlElement("level");
TiXmlText* levelText = new TiXmlText(levelString.str().c_str()); TiXmlText* levelText = new TiXmlText(levelString.str().c_str());
levelElement->LinkEndChild(levelText); levelElement->LinkEndChild(levelText);
std::stringstream expString; std::stringstream expString;
expString << _player->GetExp(); expString << _player->GetExp();
TiXmlElement* expElement = new TiXmlElement("exp"); TiXmlElement* expElement = new TiXmlElement("exp");
TiXmlText* expText = new TiXmlText(expString.str().c_str()); TiXmlText* expText = new TiXmlText(expString.str().c_str());
expElement->LinkEndChild(expText); expElement->LinkEndChild(expText);
std::stringstream healthString; std::stringstream healthString;
healthString << _player->GetHealth(); healthString << _player->GetHealth();
TiXmlElement* healthElement = new TiXmlElement("health"); TiXmlElement* healthElement = new TiXmlElement("health");
TiXmlText* healthText = new TiXmlText(healthString.str().c_str()); TiXmlText* healthText = new TiXmlText(healthString.str().c_str());
healthElement->LinkEndChild(healthText); healthElement->LinkEndChild(healthText);
saveElement->LinkEndChild(nameElement); saveElement->LinkEndChild(nameElement);
//saveElement->LinkEndChild(xElement); //saveElement->LinkEndChild(xElement);
//saveElement->LinkEndChild(yElement); //saveElement->LinkEndChild(yElement);
saveElement->LinkEndChild(levelElement); saveElement->LinkEndChild(levelElement);
saveElement->LinkEndChild(expElement); saveElement->LinkEndChild(expElement);
saveElement->LinkEndChild(healthElement); saveElement->LinkEndChild(healthElement);
doc.LinkEndChild(decl); doc.LinkEndChild(decl);
doc.LinkEndChild(saveElement); doc.LinkEndChild(saveElement);
doc.SaveFile(saveFilename.c_str()); doc.SaveFile(saveFilename.c_str());
_map.Save(_saveGameID); _map.Save(_saveGameID);
} }

View File

@ -23,46 +23,46 @@ enum gameNavVal_t { gameMainMenu, gameQuitGame };
class Game { class Game {
public: public:
Game(void); Game(void);
~Game(void); ~Game(void);
void New(const string& savegameIDArg); void New(const string& savegameIDArg);
void Load(const string& savegameIDArg); void Load(const string& savegameIDArg);
gameNavVal_t Run(void); gameNavVal_t Run(void);
private: private:
void HandleInput(void); void HandleInput(void);
void UpdateGame(void); void UpdateGame(void);
void Render(void); void Render(void);
void NewSavegame(const string savegameIDArg); void NewSavegame(const string savegameIDArg);
void LoadSavegame(const string savegameIDArg); void LoadSavegame(const string savegameIDArg);
void SaveSavegame(void); void SaveSavegame(void);
static const int MAX_FPS = 200; static const int MAX_FPS = 200;
static const int GAME_UPDATES_PER_SECOND = 60; static const int GAME_UPDATES_PER_SECOND = 60;
static const int SKIP_TICKS = 1000 / GAME_UPDATES_PER_SECOND; static const int SKIP_TICKS = 1000 / GAME_UPDATES_PER_SECOND;
bool _gameRunning; bool _gameRunning;
gameNavVal_t _runGameReturnValue; gameNavVal_t _runGameReturnValue;
string _saveGameID; string _saveGameID;
string _mapID; string _mapID;
Text _gameUpdateTime; Text _gameUpdateTime;
Text _gameRenderTime; Text _gameRenderTime;
Text _playerXY; Text _playerXY;
Text _npcHealth; Text _npcHealth;
IngameMenu _ingameMenu; IngameMenu _ingameMenu;
LevelGen _map; LevelGen _map;
Player* _player; Player* _player;
Text _playerHealth; Text _playerHealth;
Text _playerExp; Text _playerExp;
Bar _playerHealthBar; Bar _playerHealthBar;
Bar _playerExpBar; Bar _playerExpBar;
}; };

View File

@ -1,39 +1,40 @@
#include "Player.h" #include "Player.h"
#include "Globals.h" #include "Globals.h"
#include "../libUnuk/UI/EventHistory.h" #include "../libUnuk/UI/EventHistory.h"
#include "../libUnuk/System/Input.h"
// Pixels * 60 / sec. // Pixels * 60 / sec.
const float Player::PLAYER_SPEED = Character::CHARACTER_SPEED + 0.5f; const float Player::PLAYER_SPEED = Character::CHARACTER_SPEED + 1.0f;
// Amount of Exp needed every level // Amount of Exp needed every level
const int Player::EXP_TABLE[MAX_LEVEL] = { const int Player::EXP_TABLE[MAX_LEVEL] = {
10, 10,
30, 30,
90, 90,
150, 150,
300, 300,
512, 512,
1000, 1000,
2000, 2000,
3500, 3500,
5000, 5000,
6500, 6500,
8500, 8500,
10250, 10250,
12000, 12000,
15000, 15000,
25000, 25000,
50000, 50000,
65000, 65000,
80000, 80000,
100000 100000
}; };
Player::Player(LevelGen *mapArg) : Character(mapArg) { Player::Player(LevelGen *mapArg) : Character(mapArg) {
_level = 1; _level = 1;
_exp = 0; _exp = 0;
_lastTileX = 0; _lastTileX = 0;
_lastTileY = 0; _lastTileY = 0;
} }
Player::~Player(void) { Player::~Player(void) {
@ -41,108 +42,108 @@ Player::~Player(void) {
} }
void Player::HandleInput(void) { void Player::HandleInput(void) {
if(event.key.type == SDL_KEYDOWN) { if(event.key.type == SDL_KEYDOWN) {
switch(event.key.keysym.sym) { switch(event.key.keysym.sym) {
case SDLK_w: case SDLK_w:
case SDLK_UP: case SDLK_UP:
yVel -= PLAYER_SPEED; yVel -= PLAYER_SPEED;
xVel = 0; xVel = 0;
directionFacing = FACING_UP; directionFacing = FACING_UP;
break; break;
case SDLK_s: case SDLK_s:
case SDLK_DOWN: case SDLK_DOWN:
yVel += PLAYER_SPEED; yVel += PLAYER_SPEED;
xVel = 0; xVel = 0;
directionFacing = FACING_DOWN; directionFacing = FACING_DOWN;
break; break;
case SDLK_a: case SDLK_a:
case SDLK_LEFT: case SDLK_LEFT:
xVel -= PLAYER_SPEED; xVel -= PLAYER_SPEED;
yVel = 0; yVel = 0;
directionFacing = FACING_LEFT; directionFacing = FACING_LEFT;
break; break;
case SDLK_d: case SDLK_d:
case SDLK_RIGHT: case SDLK_RIGHT:
xVel += PLAYER_SPEED; xVel += PLAYER_SPEED;
yVel = 0; yVel = 0;
directionFacing = FACING_RIGHT; directionFacing = FACING_RIGHT;
break; break;
case SDLK_SPACE: case SDLK_SPACE:
attacking = true; attacking = true;
attackTimer.Start(); attackTimer.Start();
map->GetWorld().OnPlayerAttack(this); map->GetWorld().OnPlayerAttack(this);
break; break;
default: default:
break; break;
} }
} }
else if(event.key.type == SDL_KEYUP) { else if(event.key.type == SDL_KEYUP) {
switch(event.key.keysym.sym) { switch(event.key.keysym.sym) {
case SDLK_w: case SDLK_UP: yVel = 0; break; case SDLK_w: case SDLK_UP: yVel = 0; break;
case SDLK_s: case SDLK_DOWN: yVel = 0; break; case SDLK_s: case SDLK_DOWN: yVel = 0; break;
case SDLK_a: case SDLK_LEFT: xVel = 0; break; case SDLK_a: case SDLK_LEFT: xVel = 0; break;
case SDLK_d: case SDLK_RIGHT: xVel = 0; break; case SDLK_d: case SDLK_RIGHT: xVel = 0; break;
default: break; default: break;
} }
} }
else if(event.type == SDL_MOUSEBUTTONDOWN) { else if(event.type == SDL_MOUSEBUTTONDOWN) {
if(event.button.button == SDL_BUTTON_LEFT) { if(event.button.button == SDL_BUTTON_LEFT) {
attacking = true; attacking = true;
attackTimer.Start(); attackTimer.Start();
map->GetWorld().OnPlayerAttack(this); map->GetWorld().OnPlayerAttack(this);
} }
} }
} }
void Player::Update(void) { void Player::Update(void) {
Move(); Move();
//AddSpeachBubble("Woot, My name is Allanis, welcome to my home. Just testing some more text to see if this works.."); //AddSpeachBubble("Woot, My name is Allanis, welcome to my home. Just testing some more text to see if this works..");
// For now The camera will be static.
//SetCamera();
// For now The camera will be static.
//SetCamera();
tileX = x / AStarTile::FAKE_SIZE; tileX = x / AStarTile::FAKE_SIZE;
tileY = y / AStarTile::FAKE_SIZE; tileY = y / AStarTile::FAKE_SIZE;
if(tileX != _lastTileX || tileY != _lastTileY) { if(tileX != _lastTileX || tileY != _lastTileY) {
_lastTileX = tileX; _lastTileX = tileX;
_lastTileY = tileY; _lastTileY = tileY;
map->GetWorld().OnPlayerMove(this); map->GetWorld().OnPlayerMove(this);
} }
_healthBar.SetProgress((float)GetHealth() / 100.0f); _healthBar.SetProgress((float)GetHealth() / 100.0f);
} }
void Player::SetName(string nameArg) { void Player::SetName(string nameArg) {
_name = nameArg; _name = nameArg;
} }
void Player::Move() { void Player::Move() {
map->MoveIfPossible(this, xVel, yVel, true); map->MoveIfPossible(this, xVel, yVel, true);
Character::HealthBarScroll(); Character::HealthBarScroll();
} }
void Player::SetLevel(int level) { void Player::SetLevel(int level) {
_level = level; _level = level;
_exp = _exp - EXP_TABLE[level - 1]; _exp = _exp - EXP_TABLE[level - 1];
if(_exp < 0) { if(_exp < 0) {
_exp = 0; _exp = 0;
} }
if(_level == MAX_LEVEL) { if(_level == MAX_LEVEL) {
eventHistory->LogEvent("YOU BEAT IT! I'M SO PROUD!"); eventHistory->LogEvent("YOU BEAT IT! I'M SO PROUD!");
eventHistory->LogEvent("*Sheds Tear*"); eventHistory->LogEvent("*Sheds Tear*");
} }
} }
void Player::SetExp(int exp) { void Player::SetExp(int exp) {
std::stringstream evtMsg; std::stringstream evtMsg;
evtMsg << "Gained " << (exp - _exp) << " Experience Points."; evtMsg << "Gained " << (exp - _exp) << " Experience Points.";
eventHistory->LogEvent(evtMsg.str()); eventHistory->LogEvent(evtMsg.str());
_exp = exp; _exp = exp;
if(_level != MAX_LEVEL && _exp >= EXP_TABLE[_level - 1]) { if(_level != MAX_LEVEL && _exp >= EXP_TABLE[_level - 1]) {
eventHistory->LogEvent("Player leveled up!"); eventHistory->LogEvent("Player leveled up!");
SetLevel(_level + 1); SetLevel(_level + 1);
} }
} }

View File

@ -8,41 +8,41 @@
class Player : public Character { class Player : public Character {
public: public:
Player(LevelGen* mapArg); Player(LevelGen* mapArg);
~Player(void); ~Player(void);
void HandleInput(void); void HandleInput(void);
void Update(void); void Update(void);
void SetName(string nameArg); void SetName(string nameArg);
string GetName(void) { return _name; } string GetName(void) { return _name; }
void SetLevel(int level); void SetLevel(int level);
int GetLevel(void) { return _level; } int GetLevel(void) { return _level; }
void SetExp(int exp); void SetExp(int exp);
int GetExp(void) { return _exp; } int GetExp(void) { return _exp; }
void SetLevelLiteral(int level) { _level = level; } void SetLevelLiteral(int level) { _level = level; }
void SetExpLiteral(int exp) { _exp = exp; } void SetExpLiteral(int exp) { _exp = exp; }
void SetHealthLiteral(int health) { _health = health; } void SetHealthLiteral(int health) { _health = health; }
void SetXY(float xArg, float yArg) { x = xArg, y = yArg; _lastTileX = xArg / TILE_WIDTH; _lastTileY = yArg / TILE_HEIGHT; } void SetXY(float xArg, float yArg) { x = xArg, y = yArg; _lastTileX = xArg / TILE_WIDTH; _lastTileY = yArg / TILE_HEIGHT; }
static const int MAX_LEVEL = 20; static const int MAX_LEVEL = 20;
static const int EXP_TABLE[MAX_LEVEL]; static const int EXP_TABLE[MAX_LEVEL];
protected: protected:
void Move(void); void Move(void);
void CheckTileCollisions(void); void CheckTileCollisions(void);
private: private:
static const float PLAYER_SPEED; static const float PLAYER_SPEED;
string _name; string _name;
int _level; int _level;
int _exp; int _exp;
int _lastTileX; int _lastTileX;
int _lastTileY; int _lastTileY;
}; };

View File

@ -9,7 +9,9 @@
#include "../libUnuk/UI/SavegameMenu.h" #include "../libUnuk/UI/SavegameMenu.h"
#include "../libUnuk/Engine/NPC.h" #include "../libUnuk/Engine/NPC.h"
#include "../libUnuk/System/Debug.h" #include "../libUnuk/System/Debug.h"
#include "../libUnuk/System/Input.h"
#include "../libUnuk/Engine/MemClass.h" #include "../libUnuk/Engine/MemClass.h"
#include "Constants.h" #include "Constants.h"
#include "Globals.h" #include "Globals.h"
#include "Game.h" #include "Game.h"
@ -34,24 +36,24 @@ static gameNavVal_t RunGame(bool load) {
} else if(savegameMenuRet == savegameMenuCancel) { } else if(savegameMenuRet == savegameMenuCancel) {
return gameMainMenu; return gameMainMenu;
} }
std::stringstream saveFilename; std::stringstream saveFilename;
saveFilename << "save_" << savegameMenu.GetSelection(); saveFilename << "save_" << savegameMenu.GetSelection();
Debug::logger->message("Entering game state..");
Game* game = new Game;
if(load) { Debug::logger->message("Entering game state..");
game->Load(saveFilename.str()); Game* game = new Game;
} else {
game->New(saveFilename.str());
}
gameNavVal_t ret = game->Run(); if(load) {
game->Load(saveFilename.str());
} else {
game->New(saveFilename.str());
}
delete game; gameNavVal_t ret = game->Run();
return ret; delete game;
return ret;
} }
#if !defined(_WIN32) || defined(_DEBUG) #if !defined(_WIN32) || defined(_DEBUG)
@ -60,93 +62,100 @@ int main() {
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) { int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) {
#endif #endif
Debug::openLog(true); Debug::openLog(true);
Debug::logger->message("\n----- Engine Loading -----"); Debug::logger->message("\n----- Engine Loading -----");
if(SDL_Init(SDL_INIT_VIDEO == -1)) { if(SDL_Init(SDL_INIT_VIDEO == -1)) {
system("zenity --error --text=\"Could not load SDL\""); system("zenity --error --text=\"Could not load SDL\"");
Debug::logger->message("Error: Could not load SDL"); Debug::logger->message("Error: Could not load SDL");
return 1; return 1;
} else } else
Debug::logger->message("SDL loaded.."); Debug::logger->message("SDL loaded..");
if(TTF_Init() == -1) { if(TTF_Init() == -1) {
system("zenity --error --text=\"Could not load SDL_TTF\""); system("zenity --error --text=\"Could not load SDL_TTF\"");
Debug::logger->message("Error: Could not load SDL_TTF"); Debug::logger->message("Error: Could not load SDL_TTF");
return 1; return 1;
} else } else
Debug::logger->message("SDL_TTF loaded.."); Debug::logger->message("SDL_TTF loaded..");
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_HWSURFACE); screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_HWSURFACE);
Debug::logger->message("Video mode set.."); Debug::logger->message("Video mode set..");
SDL_WM_SetCaption("fps - 00", NULL); SDL_WM_SetCaption("fps - 00", NULL);
srand((unsigned int)time(NULL)); srand((unsigned int)time(NULL));
camera.x = 0; camera.x = 0;
camera.y = 0; camera.y = 0;
camera.w = SCREEN_WIDTH; camera.w = SCREEN_WIDTH;
camera.h = SCREEN_HEIGHT; camera.h = SCREEN_HEIGHT;
errorTexture = LoadImage("../Data/Media/error.png"); errorTexture = LoadImage("../Data/Media/error.png");
Text::LoadFonts(); Text::LoadFonts();
Debug::logger->message("Creating mainmenu.."); Debug::logger->message("Creating mainmenu..");
MainMenu* menu = new MainMenu; MainMenu* menu = new MainMenu;
Debug::logger->message("\n----- Engine Initialization Complete -----"); // Initiate input.
Debug::logger->message("\n----- Logic -----"); Debug::logger->message("Setting up I/O..");
CreateInput();
bool menuRunning = true; Debug::logger->message("\n----- Engine Initialization Complete -----");
while(menuRunning) { Debug::logger->message("\n----- Logic -----");
switch(menu->Run()) {
case mainMenuNewGame:
delete menu;
switch(RunGame(false)) {
case gameMainMenu:
menu = new MainMenu;
break;
case gameQuitGame:
menuRunning = false;
break;
}
break;
case mainMenuLoadGame:
delete menu;
switch(RunGame(true)) {
case gameMainMenu:
menu = new MainMenu;
break;
case gameQuitGame:
menuRunning = false;
break;
}
break;
case mainMenuOptions:
break;
case mainMenuExitGame:
menuRunning = false;
delete menu;
break;
}
}
//stringstream caption;
//caption << "Unuk - FPS: " << fps;
//SDL_WM_SetCaption(caption.str().c_str(), NULL); bool menuRunning = true;
while(menuRunning) {
switch(menu->Run()) {
case mainMenuNewGame:
delete menu;
switch(RunGame(false)) {
case gameMainMenu:
menu = new MainMenu;
break;
case gameQuitGame:
menuRunning = false;
break;
}
break;
case mainMenuLoadGame:
delete menu;
switch(RunGame(true)) {
case gameMainMenu:
menu = new MainMenu;
break;
case gameQuitGame:
menuRunning = false;
break;
}
break;
case mainMenuOptions:
break;
case mainMenuExitGame:
menuRunning = false;
delete menu;
break;
}
}
// Clean up after ourselves. //stringstream caption;
Text::FreeFonts(); //caption << "Unuk - FPS: " << fps;
SDL_FreeSurface(screen); //SDL_WM_SetCaption(caption.str().c_str(), NULL);
SDL_FreeSurface(errorTexture);
SDL_Quit(); // Clean up after ourselves.
TTF_Quit(); Text::FreeFonts();
return 0; SDL_FreeSurface(screen);
SDL_FreeSurface(errorTexture);
DestroyInput();
SDL_Quit();
TTF_Quit();
return 0;
} }

View File

@ -4,104 +4,104 @@
const float Character::CHARACTER_SPEED = 2.0f; const float Character::CHARACTER_SPEED = 2.0f;
Character::Character(LevelGen* mapArg) { Character::Character(LevelGen* mapArg) {
map = mapArg; map = mapArg;
attacking = false; attacking = false;
directionFacing = FACING_DOWN; directionFacing = FACING_DOWN;
_animationStage = ANIM_NO_FOOT; _animationStage = ANIM_NO_FOOT;
_animationTimer.Start(); _animationTimer.Start();
_leftFoot = false; _leftFoot = false;
_health = 100; _health = 100;
x = 0; x = 0;
y = 0; y = 0;
w = 40; w = 40;
h = 45; h = 45;
xVel = 0.0f; xVel = 0.0f;
yVel = 0.0f; yVel = 0.0f;
_texture = NULL;
_healthBar.SetBackgroundRGB(0, 0, 0); _texture = NULL;
_healthBar.SetForegroundRGB(255, 0, 0);
_showHealthBar = false; _healthBar.SetBackgroundRGB(0, 0, 0);
_healthBar.SetForegroundRGB(255, 0, 0);
_showHealthBar = false;
} }
Character::~Character(void) { Character::~Character(void) {
SDL_FreeSurface(_texture); SDL_FreeSurface(_texture);
} }
void Character::LoadSprites(string filename, int wArg, int hArg) { void Character::LoadSprites(string filename, int wArg, int hArg) {
if(_texture != NULL) if(_texture != NULL)
SDL_FreeSurface(_texture); SDL_FreeSurface(_texture);
_texture = LoadImageAlpha(filename.c_str()); _texture = LoadImageAlpha(filename.c_str());
w = (float)wArg; w = (float)wArg;
h = (float)hArg; h = (float)hArg;
for(int m_direction = 0; m_direction < 4; m_direction++) { for(int m_direction = 0; m_direction < 4; m_direction++) {
for(int m_action = 0; m_action < 4; m_action++) { for(int m_action = 0; m_action < 4; m_action++) {
_sprites[m_direction][m_action].x = (Sint16)(w * m_action); _sprites[m_direction][m_action].x = (Sint16)(w * m_action);
_sprites[m_direction][m_action].y = (Sint16)(h * m_direction); _sprites[m_direction][m_action].y = (Sint16)(h * m_direction);
_sprites[m_direction][m_action].w = (Sint16)w; _sprites[m_direction][m_action].w = (Sint16)w;
_sprites[m_direction][m_action].h = (Sint16)h; _sprites[m_direction][m_action].h = (Sint16)h;
} }
} }
_healthBar.SetWidthHeight((int)w, 10); _healthBar.SetWidthHeight((int)w, 10);
} }
void Character::Render(void) { void Character::Render(void) {
if(attacking && attackTimer.GetTicks() < ATTACKING_DISPLAY_LEN) { if(attacking && attackTimer.GetTicks() < ATTACKING_DISPLAY_LEN) {
ApplySurface((int)x, (int)y, _texture, screen, &_sprites[directionFacing][ANIM_ATTACK]); ApplySurface((int)x, (int)y, _texture, screen, &_sprites[directionFacing][ANIM_ATTACK]);
return; return;
} }
else if(attacking) else if(attacking)
attacking = false; attacking = false;
if(xVel == 0.0f && yVel == 0.0f) if(xVel == 0.0f && yVel == 0.0f)
ApplySurface((int)x, (int)y, _texture, screen, &_sprites[directionFacing][ANIM_NO_FOOT]); ApplySurface((int)x, (int)y, _texture, screen, &_sprites[directionFacing][ANIM_NO_FOOT]);
else { else {
if(_animationTimer.GetTicks() > ANIMATION_SPEED) { if(_animationTimer.GetTicks() > ANIMATION_SPEED) {
if(_animationStage == ANIM_NO_FOOT) { if(_animationStage == ANIM_NO_FOOT) {
if(_leftFoot == true) if(_leftFoot == true)
_animationStage = ANIM_RIGHT_FOOT; _animationStage = ANIM_RIGHT_FOOT;
else else
_animationStage = ANIM_LEFT_FOOT; _animationStage = ANIM_LEFT_FOOT;
} }
else if(_animationStage == ANIM_LEFT_FOOT) { else if(_animationStage == ANIM_LEFT_FOOT) {
_animationStage = ANIM_NO_FOOT; _animationStage = ANIM_NO_FOOT;
_leftFoot = true; _leftFoot = true;
} }
else if(_animationStage == ANIM_RIGHT_FOOT) { else if(_animationStage == ANIM_RIGHT_FOOT) {
_animationStage = ANIM_NO_FOOT; _animationStage = ANIM_NO_FOOT;
_leftFoot = false; _leftFoot = false;
} }
_animationTimer.Start(); _animationTimer.Start();
} }
ApplySurface((int)x, (int)y, _texture, screen, &_sprites[directionFacing][_animationStage]); ApplySurface((int)x, (int)y, _texture, screen, &_sprites[directionFacing][_animationStage]);
} }
if(_showHealthBar && (_healthBarDuration.GetTicks() >= 5000)) { if(_showHealthBar && (_healthBarDuration.GetTicks() >= 5000)) {
_healthBarDuration.Stop(); _healthBarDuration.Stop();
_showHealthBar = false; _showHealthBar = false;
} }
if(_showHealthBar) { if(_showHealthBar) {
_healthBar.Draw(); _healthBar.Draw();
} }
} }
void Character::Update(void) { void Character::Update(void) {
_healthBar.SetProgress((float)_health / 100.0f); _healthBar.SetProgress((float)_health / 100.0f);
} }
void Character::OnAttack(void) { void Character::OnAttack(void) {
_healthBarDuration.Start(); _healthBarDuration.Start();
_showHealthBar = true; _showHealthBar = true;
} }
void Character::HealthBarScroll(void) { void Character::HealthBarScroll(void) {
_healthBar.SetXY((int)x, (int)(y - _healthBar.GetHeight() - 5)); _healthBar.SetXY((int)x, (int)(y - _healthBar.GetHeight() - 5));
} }

View File

@ -20,99 +20,99 @@ class LevelGen;
class Character { class Character {
public: public:
Character(LevelGen* mapArg); Character(LevelGen* mapArg);
~Character(void); ~Character(void);
void LoadSprites(string filename, int wArg, int hArg); void LoadSprites(string filename, int wArg, int hArg);
float GetX(void) { return x; } float GetX(void) { return x; }
float GetY(void) { return y; } float GetY(void) { return y; }
float GetWidth(void) { return w; } float GetWidth(void) { return w; }
float GetHeight(void) { return h; } float GetHeight(void) { return h; }
void SetXY(float xArg, float yArg) { x = xArg, y = yArg; } void SetXY(float xArg, float yArg) { x = xArg, y = yArg; }
void SetXVelocity(float arg) { xVel = arg; } void SetXVelocity(float arg) { xVel = arg; }
void SetYVelocity(float arg) { yVel = arg; } void SetYVelocity(float arg) { yVel = arg; }
void SetHealth(int health) { _health = health; } void SetHealth(int health) { _health = health; }
int GetHealth(void) { return _health; } int GetHealth(void) { return _health; }
int GetDirectionFacing(void) { return directionFacing; } int GetDirectionFacing(void) { return directionFacing; }
void SetDirectionFacing(int dir) { directionFacing = dir; } void SetDirectionFacing(int dir) { directionFacing = dir; }
void Render(void); void Render(void);
void Update(void); void Update(void);
void OnAttack(void); void OnAttack(void);
// Overload new and delete operators to utilize MemManager. // Overload new and delete operators to utilize MemManager.
inline void* operator new(size_t size) { // inline void* operator new(size_t size) {
return gMemManager.Allocate(size); // return gMemManager.Allocate(size);
} // }
inline void operator delete(void* object) { // inline void operator delete(void* object) {
gMemManager.Free(object); // gMemManager.Free(object);
} // }
inline void* operator new [](size_t size) { // inline void* operator new [](size_t size) {
return gMemManager.Allocate(size); // return gMemManager.Allocate(size);
} // }
inline void operator delete [](void* object) { // inline void operator delete [](void* object) {
gMemManager.Free(object); // gMemManager.Free(object);
} // }
enum { enum {
FACING_UP, FACING_UP,
FACING_RIGHT, FACING_RIGHT,
FACING_DOWN, FACING_DOWN,
FACING_LEFT FACING_LEFT
}; };
protected: protected:
void HealthBarScroll(void); void HealthBarScroll(void);
float x; float x;
float y; float y;
float w; float w;
float h; float h;
float xVel; float xVel;
float yVel; float yVel;
int tileX; int tileX;
int tileY; int tileY;
Timer attackTimer; Timer attackTimer;
bool attacking; bool attacking;
int _health; int _health;
LevelGen* map; LevelGen* map;
static const float CHARACTER_SPEED; static const float CHARACTER_SPEED;
int directionFacing; int directionFacing;
static const int ANIM_LEFT_FOOT = 0; static const int ANIM_LEFT_FOOT = 0;
static const int ANIM_NO_FOOT = 1; static const int ANIM_NO_FOOT = 1;
static const int ANIM_RIGHT_FOOT = 2; static const int ANIM_RIGHT_FOOT = 2;
static const int ANIM_ATTACK = 3; static const int ANIM_ATTACK = 3;
Bar _healthBar; Bar _healthBar;
Timer _healthBarDuration; Timer _healthBarDuration;
bool _showHealthBar; bool _showHealthBar;
private: private:
static const int ANIMATION_SPEED = 200; static const int ANIMATION_SPEED = 200;
static const int ATTACKING_DISPLAY_LEN = 150; static const int ATTACKING_DISPLAY_LEN = 150;
SDL_Surface* _texture; SDL_Surface* _texture;
// [direction][action] // [direction][action]
SDL_Rect _sprites[4][4]; SDL_Rect _sprites[4][4];
Timer _animationTimer; Timer _animationTimer;
int _animationStage; int _animationStage;
bool _leftFoot; bool _leftFoot;
}; };

View File

@ -1,32 +0,0 @@
#pragma once
#include "MemManager.h"
extern MemManager gMemManager;
class MemClass {
public:
MemClass(void) : r(0), c(0) {}
MemClass(double a, double b): r(a), c(b) {}
inline void* operator new(size_t size) {
return gMemManager.Allocate(size);
}
inline void operator delete(void* object) {
gMemManager.Free(object);
}
inline void* operator new [](size_t size) {
return gMemManager.Allocate(size);
}
inline void operator delete [](void* object) {
gMemManager.Free(object);
}
private:
// Real part.
double r;
// Complex part.
double c;
};

View File

@ -1,206 +1,535 @@
#include "MemClass.h" #include <new>
#include <cassert>
#include <cstdio>
#ifdef _WIN32
#include <windows.h>
#endif
#include <malloc.h>
#include <string.h>
#include "MemManager.h" #include "MemManager.h"
MemManager gMemManager;
void BitMapEntry::SetBit(int position, bool flag) { // This is rather C'ish, it can't really be helped since using new/delete inside allocation
blocksAvailable += flag ? 1 : -1; // routines would be, well, no fun. This also excludes SDL containers.
int elementNo = position / INT_SIZE;
int bitNo = position % INT_SIZE; // Don't use this here..
if(flag) #ifdef new
bitMap[elementNo] = bitMap[elementNo] | (1 << bitNo); #undef new
else #endif
bitMap[elementNo] = bitMap[elementNo] & ~(1 << bitNo);
// We will dump the report here..
const char logFileName[] = "../Bin/MemLeaks.log";
// Longs are guaranteed to be 2 bits.
typedef unsigned long uint32;
// Identifiers which are placed to allocated buffer (4-byte alignment)
const uint32 memPrefix = 0xBAADF00D;
const uint32 memPostfix = 0xBABE2BED;
const uint32 memNotUsed = 0xDEADC0DE;
// Identifiers for array / non array allocations / deleted allocations.
const uint32 nonArrayAllocation = 0x2BADF00D;
const uint32 arrayAllocation = 0xBAD4ACE2;
const uint32 invalidAllocation = 0x76543210;
// Amount. Be careful, this could be a memory overkill.
const int numberPrefix = 32; // 128 bytes.
const int numberPostfix = 32; // 128 bytes.
void RemoveMessages(void) {
#ifdef _WIN32
MSG msg = { 0 };
while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
if(msg.message == WM_PAINT)
return;
}
#endif
} }
void BitMapEntry::SetMultipleBits(int position, bool flag, int count) { struct AllocationUnit {
blocksAvailable += flag ? count : -count; // Just for convenience.
int elementNo = position / INT_SIZE; uint32* prefixPointer;
int bitNo = position % INT_SIZE; uint32* postfixPointer;
uint32* dataPointer;
int bitSize = (count <= INT_SIZE - bitNo) ? count : INT_SIZE - bitNo; // Size with and withough manager extras.
SetRangeOfInt(&bitMap[elementNo], bitNo + bitSize - 1, bitNo, flag); size_t requestedSize;
count -= bitSize; size_t overallSize;
if(!count) return;
int i = ++elementNo; // Catches mixing new[]/delete and new/delete[] changed from bool to int
while(count >= 0) { // to catch problems with memory blocks allocated without using memory manager.
if(count <= INT_SIZE) { int arrayAllocated;
SetRangeOfInt(&bitMap[i], count - 1, 0, flag);
return; // Allocation info which may or may not be present.
} else char* allocatedFrom;
bitMap[i] = flag ? unsigned (-1) : 0;
count -= 32; // Allocation was marked during last snapshot, therfore, it will not be shown
i++; // at leak snapshot dump.
} bool markedSnapshot;
};
AllocationUnit* CreateAllocationUnit(void) {
AllocationUnit* unit = static_cast<AllocationUnit*> (malloc(sizeof(AllocationUnit)));
unit->prefixPointer = 0;
unit->postfixPointer = 0;
unit->dataPointer = 0;
unit->requestedSize = 0;
unit->overallSize = 0;
unit->arrayAllocated = nonArrayAllocation;
unit->allocatedFrom = 0;
unit->markedSnapshot = false;
return unit;
} }
void BitMapEntry::SetRangeOfInt(int* element, int msb, int lsb, bool flag) { void deleteAllocationUnit(AllocationUnit* unit) {
if(flag) { if(unit->allocatedFrom)
int mask = (unsigned(-1) << lsb) & (unsigned(-1) >> (INT_SIZE - msb - 1)); free(unit->allocatedFrom);
*element |= mask; if(unit->prefixPointer)
} else { free(unit->prefixPointer);
int mask = (unsigned(-1) << lsb) & (unsigned(-1) >> (INT_SIZE - msb - 1)); unit->arrayAllocated = invalidAllocation;
*element &= ~mask; free(unit);
}
} }
MemClass* BitMapEntry::FirstFreeBlock(size_t/* size*/) { // Allocation information.
for(int i = 0; i < BIT_MAP_ELEMENTS; i++) {
if(bitMap[i] == 0)
// There aint any bits free.
continue;
// Yield the first bit position. This is a 1 struct AllocationLink {
// in an int from the right. AllocationUnit* allocationUnit;
int result = bitMap[i] & -(bitMap[i]); AllocationLink* next;
//void* address = 0; };
int basePos = (INT_SIZE * i);
switch(result) { struct AllocationRoot {
// Make the corresponfing bit 0 so block is no longer free. AllocationLink* first;
case 0x00000001: return ComplexObjectAddress(basePos + 0); };
case 0x00000002: return ComplexObjectAddress(basePos + 1);
case 0x00000004: return ComplexObjectAddress(basePos + 2); // Hash data.
case 0x00000008: return ComplexObjectAddress(basePos + 3); static const int hashSize = 3677; // Prime number. Big enough?
case 0x00000010: return ComplexObjectAddress(basePos + 4); static AllocationRoot hashMap[hashSize] = { 0 };
case 0x00000020: return ComplexObjectAddress(basePos + 5);
case 0x00000040: return ComplexObjectAddress(basePos + 6); static int allocationCount = 0; // Amount of allocations.
case 0x00000080: return ComplexObjectAddress(basePos + 7); static int allocationMemory = 0; // Memory allocated.
case 0x00000100: return ComplexObjectAddress(basePos + 8);
case 0x00000200: return ComplexObjectAddress(basePos + 9); static int PeakMemoryUsage = 0;
case 0x00000400: return ComplexObjectAddress(basePos + 10); static int peakPointers = 0;
case 0x00000800: return ComplexObjectAddress(basePos + 11);
case 0x00001000: return ComplexObjectAddress(basePos + 12); int CalculateHashIndex(const void* buffer) {
case 0x00002000: return ComplexObjectAddress(basePos + 13); int value = reinterpret_cast<int> (buffer);
case 0x00004000: return ComplexObjectAddress(basePos + 14); // Shift lower bits (alignment would kill coverage).
case 0x00008000: return ComplexObjectAddress(basePos + 15); value >>= 4;
case 0x00010000: return ComplexObjectAddress(basePos + 16);
case 0x00020000: return ComplexObjectAddress(basePos + 17); // Create index.
case 0x00040000: return ComplexObjectAddress(basePos + 18); value %= hashSize;
case 0x00080000: return ComplexObjectAddress(basePos + 19); return value;
case 0x00100000: return ComplexObjectAddress(basePos + 20);
case 0x00200000: return ComplexObjectAddress(basePos + 21);
case 0x00400000: return ComplexObjectAddress(basePos + 22);
case 0x00800000: return ComplexObjectAddress(basePos + 23);
case 0x01000000: return ComplexObjectAddress(basePos + 24);
case 0x02000000: return ComplexObjectAddress(basePos + 25);
case 0x04000000: return ComplexObjectAddress(basePos + 26);
case 0x08000000: return ComplexObjectAddress(basePos + 27);
case 0x10000000: return ComplexObjectAddress(basePos + 28);
case 0x20000000: return ComplexObjectAddress(basePos + 29);
case 0x40000000: return ComplexObjectAddress(basePos + 30);
case 0x80000000: return ComplexObjectAddress(basePos + 31);
default: break;
}
}
return 0;
} }
MemClass* BitMapEntry::ComplexObjectAddress(int pos) { void AddAllocation(AllocationUnit* allocation) {
SetBit(pos, false); assert(allocation);
return &((static_cast<MemClass*>(Head()) + (pos / INT_SIZE)) [INT_SIZE - (pos % INT_SIZE + 1)]);
++allocationCount;
allocationMemory += allocation->requestedSize;
AllocationLink* link = static_cast<AllocationLink*> (malloc(sizeof(AllocationLink)));
link->allocationUnit = allocation;
link->next = 0;
int hashIndex = CalculateHashIndex(allocation->dataPointer);
if(hashMap[hashIndex].first == 0)
hashMap[hashIndex].first = link;
else {
// Push front.
link->next = hashMap[hashIndex].first;
hashMap[hashIndex].first = link;
}
if(allocationMemory > PeakMemoryUsage)
PeakMemoryUsage = allocationMemory;
if(allocationCount > peakPointers)
peakPointers = allocationCount;
} }
void* BitMapEntry::Head(void) { AllocationUnit* FindAllocation(void* pointer) {
return gMemManager.GetMemoryPoolList()[index]; int hashIndex = CalculateHashIndex(pointer);
AllocationLink* current = hashMap[hashIndex].first;
while(current) {
if(current->allocationUnit->dataPointer == pointer)
return current->allocationUnit;
current = current->next;
}
RemoveMessages();
assert(!"Allocation not found. Uninitialized pointer?");
return 0;
} }
void* MemManager::Allocate(size_t size) { void RemoveAllocation(AllocationUnit* allocation) {
// None array. if(allocationCount <= 0) {
if(size == sizeof(MemClass)) { RemoveMessages();
set<BitMapEntry*>::iterator freeMapI = _freeMapEntries.begin(); assert(allocationCount > 0);
if(freeMapI != _freeMapEntries.end()) { }
BitMapEntry* mapEntry = *freeMapI;
return mapEntry->FirstFreeBlock(size);
} else {
AllocateChunkAndInitBitMap();
_freeMapEntries.insert(&(_bitMapEntryList[_bitMapEntryList.size() - 1]));
return _bitMapEntryList[_bitMapEntryList.size() - 1].FirstFreeBlock(size);
}
} else {
// Array.
if(_arrayMemoryList.empty()) {
return AllocateArrayMemory(size);
} else {
map<void*, ArrayMemoryInfo>::iterator infoI = _arrayMemoryList.begin();
map<void*, ArrayMemoryInfo>::iterator infoEndI = _arrayMemoryList.end();
while(infoI != infoEndI) { int hashIndex = CalculateHashIndex(allocation->dataPointer);
ArrayMemoryInfo info = (*infoI).second;
if(info.StartPosition != 0)
// Only search the memory blocks where allocation
// is done from first byte.
continue;
else {
BitMapEntry* entry = &_bitMapEntryList[info.memPoolListIndex];
if(entry->blocksAvailable < (size / sizeof(MemClass)))
return AllocateArrayMemory(size);
else {
info.StartPosition = BIT_MAP_SIZE - entry->blocksAvailable;
info.Size = size / sizeof(MemClass);
MemClass* baseAddress = static_cast<MemClass*>(_memoryPoolList[info.memPoolListIndex]) + info.StartPosition;
_arrayMemoryList[baseAddress] = info; AllocationLink* current = hashMap[hashIndex].first;
SetMultipleBlockBits(&info, false); AllocationLink* previous = 0;
return baseAddress; while(current) {
} if(current->allocationUnit == allocation) {
} // Remove.
} if(previous)
} previous->next = current->next;
} else
return 0; hashMap[hashIndex].first = current->next;
--allocationCount;
allocationMemory -= current->allocationUnit->requestedSize;
// Free memory.
deleteAllocationUnit(current->allocationUnit);
free(current);
return;
}
previous = current;
current = current->next;
}
RemoveMessages();
assert(!"Allocation not found. Uninitialized pointer?");
} }
void* MemManager::AllocateArrayMemory(size_t size) { void DumpLeakReport(void) {
void* chunkAddress = AllocateChunkAndInitBitMap(); if(allocationCount > 0) {
ArrayMemoryInfo info; DumpLeakSnapshot(true);
info.memPoolListIndex = _memoryPoolList.size() - 1; } else {
info.StartPosition = 0; // Remove file.
info.Size = size / sizeof(MemClass); fclose(fopen(logFileName, "wt"));
_arrayMemoryList[chunkAddress] = info; }
SetMultipleBlockBits(&info, false);
return chunkAddress;
} }
void* MemManager::AllocateChunkAndInitBitMap(void) { void TestIdentifiers(AllocationUnit* allocation) {
BitMapEntry mapEntry; for(int i = 0; i < numberPrefix; ++i) {
MemClass* memoryBeginAddress = reinterpret_cast<MemClass*>(new char[sizeof(MemClass) * BIT_MAP_SIZE]); if(allocation->prefixPointer[i] != memPrefix) {
_memoryPoolList.push_back(memoryBeginAddress); RemoveMessages();
mapEntry.index = _memoryPoolList.size() - 1; assert(!"Buffer prefix messed up!");
_bitMapEntryList.push_back(mapEntry); }
return memoryBeginAddress; }
for(int i = 0; i < numberPostfix; ++i) {
if(allocation->postfixPointer[i] != memPostfix) {
RemoveMessages();
assert(!"Buffer postfix messed up!");
}
}
} }
void MemManager::Free(void* object) { // After deinitialization, dump leak report on every deallocation.
if(_arrayMemoryList.find(object) == _arrayMemoryList.end()) struct InitializationTracker {
// Simple block deletion. static bool programExiting;
SetBlockBit(object, true);
else { InitializationTracker(void) {
// Memory block deletion. programExiting = false;
ArrayMemoryInfo *info = &_arrayMemoryList[object]; }
SetMultipleBlockBits(info, true);
} ~InitializationTracker(void) {
programExiting = true;
DumpLeakReport();
}
};
bool InitializationTracker::programExiting = false;
static InitializationTracker tracker;
void MarkLeakSnapshot(void) {
if(allocationCount > 0) {
int currentIndex = 0;
for(int i = 0; i < hashSize; ++i) {
AllocationLink* currentLink = hashMap[i].first;
while(currentLink != 0) {
currentLink->allocationUnit->markedSnapshot = true;
currentLink = currentLink->next;
}
}
}
} }
void MemManager::SetBlockBit(void* object, bool flag) { void DumpLeakSnapshot(bool fromStart) {
int i = _bitMapEntryList.size() - 1; if(allocationCount > 0) {
for(; i >= 0; i--) { FILE* fp = fopen(logFileName, "wt");
BitMapEntry* bitMap = &_bitMapEntryList[i]; if(fp == NULL) {
if((bitMap->Head() <= object) && (&(static_cast<MemClass*>(bitMap->Head()))[BIT_MAP_SIZE - 1] >= object)) { return;
int position = static_cast<MemClass*>(object)- static_cast<MemClass*>(bitMap->Head()); }
bitMap->SetBit(position, flag);
flag ? bitMap->blocksAvailable++ : bitMap->blocksAvailable--; if(!fromStart)
} fprintf(fp, "(SNAPSHOT)\n\n");
} fprintf(fp, "Peak memory usage: %d bytes\n", PeakMemoryUsage);
fprintf(fp, "Overall memory leaked: %d bytes\n", allocationMemory);
fprintf(fp, "Pointers left: %d\n\n", allocationCount);
int currentIndex = 0;
for(int i = 0; i < hashSize; ++i) {
AllocationLink* currentLink = hashMap[i].first;
while(currentLink != 0) {
if(!currentLink->allocationUnit->markedSnapshot || fromStart) {
//if(strcmp(currentLink->allocationUnit->allocatedFrom, "(???: line 0)") != 0)
if(!strstr(currentLink->allocationUnit->allocatedFrom, "???")) {
// Temp: show only over 2MB
//if(currentLink->allocationUnit->requestedSize > 1*1024*1024) {
fprintf(fp, "Allocation %d:\n", ++currentIndex);
fprintf(fp, "\tAllocated from: %s\n", currentLink->allocationUnit->allocatedFrom);
fprintf(fp, "\tAllocation size: %d bytes\n", currentLink->allocationUnit->requestedSize);
if(currentLink->allocationUnit->arrayAllocated == nonArrayAllocation)
fprintf(fp, "\tAllocated with new()\n");
else
fprintf(fp, "\tAllocated with new[]\n");
// To get the contents of some char array strings.
#define MEMMANAGER_MAX_PRINT_SIZE 80
int arraySize = currentLink->allocationUnit->requestedSize;
if(currentLink->allocationUnit->arrayAllocated == arrayAllocation && arraySize < MEMMANAGER_MAX_PRINT_SIZE) {
char* data = (char*)currentLink->allocationUnit->requestedSize;
char databuf[MEMMANAGER_MAX_PRINT_SIZE + 2];
bool noControlChars = true;
int j;
for(j = 0; j < arraySize; j++) {
if(data[j] == '\n' || data[j] == '\r')
databuf[j] = ' ';
else
databuf[j] = data[j];
if(data[j] < 32 && data[j] != '\n' && data[j] != '\r') {
if(data[j] != '\0') noControlChars = false;
break;
}
}
databuf[j] != '\0';
if(noControlChars) {
fprintf(fp, "\tData: \"%s\"\n", data);
}
}
fprintf(fp, "\n");
//}
}
}
currentLink = currentLink->next;
}
}
fclose(fp);
}
} }
void MemManager::SetMultipleBlockBits(ArrayMemoryInfo* info, bool flag) { char debugAllocInfo[256 + 1] = { 0 };
BitMapEntry* mapEntry = &_bitMapEntryList[info->memPoolListIndex]; int debugAllocatedSinceInfo = -1;
mapEntry->SetMultipleBits(info->StartPosition, flag, info->Size); // Just a hack to add extra info to allocations.
void DebugSetAllocationInfo(const char* allocationInfo) {
if(allocationInfo == NULL)
debugAllocInfo[0] = '\0';
else
strncpy(debugAllocInfo, allocationInfo, 256);
debugAllocatedSinceInfo = 0;
} }
vector<void*>& MemManager::GetMemoryPoolList(void) { // Operator new implementation.
return _memoryPoolList; void* operator new(size_t originalSize, const char* filename, int lineNumber, bool arrayAllocated) {
// Handle 0-byte request. we must return a unique pointer
// (or unique value actually).
if(originalSize == 0)
originalSize = 1;
// To 4-byte boundary (since our identifiers are unit32's).
if(int foo = originalSize % 4)
originalSize += 4 - foo;
// Make some room for prefix and postfix.
size_t size = originalSize;
size += numberPrefix * 4;
size += numberPostfix * 4;
// Yes, Infinate loop really is the way to go :)
while(true) {
AllocationUnit* allocation = CreateAllocationUnit();
void* buffer = malloc(size);
// Both have to succeed. We want to handle out-of-memory.
if((buffer) && (allocation)) {
char* info;
if(debugAllocInfo[0] != '\0' && debugAllocatedSinceInfo >= 0) {
info = static_cast<char*>(malloc(strlen(filename) + strlen(debugAllocInfo) + 60));
if(info) {
if(debugAllocatedSinceInfo == 0)
sprintf(info, "(%s: line %d)\t Info: \"%s\"", filename, lineNumber, debugAllocInfo);
else
sprintf(info, "(%s: line %d)\n\tInfo: (\"%s\", %d allocs ago)", filename, lineNumber, debugAllocInfo, debugAllocatedSinceInfo);
}
} else {
info = static_cast<char*> (malloc(strlen(filename) + 20));
if(info) {
sprintf(info, "(%s: line %d)", filename, lineNumber);
}
}
// Fill in allocation info.
allocation->prefixPointer = static_cast<uint32*> (buffer);
allocation->dataPointer = allocation->prefixPointer + numberPrefix;
allocation->postfixPointer = allocation->dataPointer + (originalSize / 4);
allocation->allocatedFrom = info;
if(arrayAllocated)
allocation->arrayAllocated = arrayAllocation;
else
allocation->arrayAllocated = nonArrayAllocation;
allocation->overallSize = size;
allocation->requestedSize = originalSize;
// Fill in our identifiers.
for(int i = 0; i < numberPrefix; ++i)
allocation->prefixPointer[i] = memPrefix;
for(int i = 0; i < int(originalSize / 4); ++i)
allocation->dataPointer[i] = memNotUsed;
for(int i = 0; i < numberPostfix; ++i)
allocation->postfixPointer[i] = memPostfix;
AddAllocation(allocation);
return allocation->dataPointer;
}
// If only one of them succeeded, free it first.
if(buffer)
free(buffer);
if(allocation)
deleteAllocationUnit(allocation);
// Test error-handling functions.
std::new_handler globalHandler = std::set_new_handler(0);
std::set_new_handler(globalHandler);
// If we have one, try it. otherwise throw a bad allocation.
// (And hope for someone to catch it).
if(globalHandler)
(*globalHandler) ();
else
throw std::bad_alloc();
}
}
void operator delete(void* buffer, bool arrayDeleted) throw() {
// Deleting null-pointer is legal.
if(buffer == 0)
return;
AllocationUnit* allocation = FindAllocation(buffer);
if(!allocation) {
RemoveMessages();
assert(allocation);
}
// Test out of bounds.
TestIdentifiers(allocation);
// Test that the block was allocated by memory manager.
// Test array operator mixing.
if(allocation->arrayAllocated != arrayAllocation && allocation->arrayAllocated != nonArrayAllocation) {
RemoveMessages();
assert(!"Deleting block with invalid allocation type");
} else {
if((arrayDeleted && allocation->arrayAllocated == nonArrayAllocation) || (!arrayDeleted && allocation->arrayAllocated == arrayAllocation)) {
RemoveMessages();
assert(!"Mixed array and normal versions");
}
}
RemoveAllocation(allocation);
// If quitting, dump report on each deallocation.
if(InitializationTracker::programExiting == true)
DumpLeakReport();
}
void* operator new(size_t size, const char* filename, int lineNumber) throw(std::bad_alloc) {
return operator new(size, filename, lineNumber, false);
}
void* operator new(size_t size) throw(std::bad_alloc) {
return operator new(size, "???", 0, false);
}
void* operator new[](size_t size, const char* filename, int lineNumber) throw(std::bad_alloc) {
return operator new(size, filename, lineNumber, true);
}
void* operator new[](size_t size) throw(std::bad_alloc) {
return operator new(size, "???", 0 , true);
}
void operator delete(void* buffer) throw() {
operator delete(buffer, false);
}
void operator delete[](void* buffer) throw() {
operator delete(buffer, true);
}
void MemManager::SetFailingPercentage(int percentage) {
}
void MemManager::ValidatePointer(void* pointer) {
AllocationUnit* allocation = FindAllocation(pointer);
if(!allocation) {
RemoveMessages();
assert(allocation);
return;
}
// Test out-of-bounds.
TestIdentifiers(allocation);
}
void MemManager::ValidateAllPointers(void) {
for(int i = 0; i < hashSize; ++i) {
AllocationLink* currentLink = hashMap[i].first;
while(currentLink != 0) {
if(currentLink)
TestIdentifiers(currentLink->allocationUnit);
currentLink = currentLink->next;
}
}
}
int MemManager::AmountOfMemoryAllocated(void* pointer, bool includeManagerExtra) {
return 0;
}
int MemManager::AmountOfMemoryInUse(void* pointer) {
int result = 0;
for(int i = 0; i < hashSize; ++i) {
AllocationLink* currentLink = hashMap[i].first;
while(currentLink != 0) {
if(currentLink)
result += currentLink->allocationUnit->requestedSize;
currentLink = currentLink->next;
}
}
return result;
}
void MemManager::LogStatistics(const char* filename) {
}
void MemManager::LogUnusedPointers(const char* filename, float freePercentage) {
}
int MemManager::AmountOfMemoryInUse(bool includeManagerExta) {
return allocationMemory;
}
int MemManager::AmountOfPeakMemoryInUse(bool includeManagerExtra) {
return 0;
}
int MemManager::AmountOfMemoryAllocations(void) {
return allocationCount;
}
int MemManager::AmountOfPeakMemoryAllocations(void) {
return 0;
} }

View File

@ -1,88 +1,53 @@
#pragma once #pragma once
#include <iostream>
#include <vector>
#include <string>
#include <string.h>
#include <vector>
#include <set>
#include <map>
#include <bitset>
using namespace std;
const int BIT_MAP_SIZE = 1024; #ifndef INCLUDED_NEW
const int INT_SIZE = sizeof(int) * 8; #define INCLUDED_NEW
const int BIT_MAP_ELEMENTS = BIT_MAP_SIZE / INT_SIZE; #include <new>
#endif
/* class MemManager {
* Memory Allocation Pattern. // Not implemented.
* 11111111 11111111 11111111 MemManager(void);
* 11111110 11111111 11111111 ~MemManager(void);
* 11111100 11111111 11111111
*
* If all bits for the first section becomes zero go to next section.
*
* 00000000 11111111 11111111
* 00000000 11111110 11111111
* 00000000 11111100 11111111
* 00000000 11111000 11111111
*
* The lookup inside the map becomes 0(1) for the first available free block.
*/
class MemClass;
typedef struct BitMapEntry {
int index;
int blocksAvailable;
int bitMap[BIT_MAP_SIZE];
public: public:
BitMapEntry():blocksAvailable(BIT_MAP_SIZE) { // Affect behavior.
// All blocks are free to begin with and bit value 1 static void SetFailingPercentage(int percentage);
// in the map denotes available blocks.
memset(bitMap, 0xff, BIT_MAP_SIZE / sizeof(char));
}
void SetBit(int position, bool flag); // Pointers.
void SetMultipleBits(int position, bool flag, int count); static void ValidatePointer(void* pointer);
void SetRangeOfInt(int* element, int msb, int lsb, bool flag); static void ValidateAllPointers(void);
MemClass* FirstFreeBlock(size_t size); static int AmountOfMemoryAllocated(void* pointer, bool includeManagerExtra = false);
MemClass* ComplexObjectAddress(int pos); static int AmountOfMemoryInUse(void* pointer);
void* Head(void);
} BitMapEntry;
typedef struct ArrayInfo { // Logging.
int memPoolListIndex; static void LogStatistics(const char* filename);
int StartPosition; static void LogUnusedPointers(const char* filename, float freePercentage);
int Size;
} ArrayMemoryInfo;
class IMemManager { // Memory statistics.
public: static int AmountOfMemoryInUse(bool includeManagerExta = false);
virtual void* Allocate(size_t size) = 0; static int AmountOfPeakMemoryInUse(bool includeManagerExtra = false);
virtual void Free(void* object) = 0; static int AmountOfMemoryAllocations(void);
static int AmountOfPeakMemoryAllocations(void);
}; };
class MemManager : public IMemManager { // Quick hack to get some extra information about allocations.
public: void DebugSetAllocationInfo(const char* allocationInfo);
MemManager(void) {} void DumpLeakSnapshot(bool fromStart = false);
~MemManager(void) {} void MarkLeakSnapshot(void);
void* Allocate(size_t size); // Global operators.
void Free(void* object); void* operator new(size_t size, const char* filename, int lineNumber) throw(std::bad_alloc);
vector<void*>& GetMemoryPoolList(void); void* operator new(size_t size) throw(std::bad_alloc);
void* operator new[](size_t size, const char* filename, int lineNumber) throw(std::bad_alloc);
void* operator new[](size_t size) throw(std::bad_alloc);
void operator delete(void* buffer) throw();
void operator delete[](void* buffer) throw();
private: // I don't think there are any compilers that don't define these, but just in case.
void* AllocateArrayMemory(size_t size); #ifndef __FILE__
void* AllocateChunkAndInitBitMap(void); #define __FILE__ "???"
void SetBlockBit(void* object, bool flag); #endif
void SetMultipleBlockBits(ArrayMemoryInfo* info, bool flag); #ifndef __LINE__
#define __LINE__ 0
// The following lists will maintain one to one correspondace #endif
// and should be the same size.
vector<void*> _memoryPoolList;
vector<BitMapEntry> _bitMapEntryList;
set<BitMapEntry*> _freeMapEntries;
map<void*, ArrayMemoryInfo> _arrayMemoryList;
};

View File

@ -3,8 +3,8 @@
#include "../System/Vec2.h" #include "../System/Vec2.h"
NPC::NPC(LevelGen* mapArg) : Character(mapArg) { NPC::NPC(LevelGen* mapArg) : Character(mapArg) {
_walkInPath = false; _walkInPath = false;
_moving = false; _moving = false;
} }
NPC::~NPC(void) { NPC::~NPC(void) {
@ -12,44 +12,44 @@ NPC::~NPC(void) {
} }
void NPC::ForceMove(void) { void NPC::ForceMove(void) {
tileX = x / AStarTile::FAKE_SIZE; tileX = x / AStarTile::FAKE_SIZE;
tileY = y / AStarTile::FAKE_SIZE; tileY = y / AStarTile::FAKE_SIZE;
} }
void NPC::Update(void) { void NPC::Update(void) {
// Store the NPC's health. // Store the NPC's health.
// int health = GetHealth(); // not referenced // int health = GetHealth(); // not referenced
Move(); Move();
if(xVel > 0) directionFacing = FACING_RIGHT; if(xVel > 0) directionFacing = FACING_RIGHT;
else if(xVel < 0) directionFacing = FACING_LEFT; else if(xVel < 0) directionFacing = FACING_LEFT;
else if(yVel > 0) directionFacing = FACING_DOWN; else if(yVel > 0) directionFacing = FACING_DOWN;
else if(yVel < 0) directionFacing = FACING_UP; else if(yVel < 0) directionFacing = FACING_UP;
_healthBar.SetProgress((float)GetHealth() / 100.0f); _healthBar.SetProgress((float)GetHealth() / 100.0f);
} }
void NPC::Move(void) { void NPC::Move(void) {
xVel = 0.0f; xVel = 0.0f;
yVel = 0.0f; yVel = 0.0f;
Character* player = map->GetPlayer(); Character* player = map->GetPlayer();
SDL_Rect selfRect; SDL_Rect selfRect;
selfRect.x = x - 5; selfRect.x = x - 5;
selfRect.y = y - 5; selfRect.y = y - 5;
selfRect.w = w + 5; selfRect.w = w + 5;
selfRect.h = h + 5; selfRect.h = h + 5;
SDL_Rect playerRect; SDL_Rect playerRect;
playerRect.x = player->GetX() - 5; playerRect.x = player->GetX() - 5;
playerRect.y = player->GetY() - 5; playerRect.y = player->GetY() - 5;
playerRect.w = player->GetWidth() + 5; playerRect.w = player->GetWidth() + 5;
playerRect.h = player->GetHeight() + 5; playerRect.h = player->GetHeight() + 5;
bool isNearPlayer = CheckCollisionRect(selfRect, playerRect); bool isNearPlayer = CheckCollisionRect(selfRect, playerRect);
if(isNearPlayer) { if(isNearPlayer) {
if(!attackTimer.IsStarted()) { if(!attackTimer.IsStarted()) {
attackTimer.Start(); attackTimer.Start();
@ -64,30 +64,30 @@ void NPC::Move(void) {
attackTimer.Stop(); attackTimer.Stop();
} }
} }
Character::HealthBarScroll(); Character::HealthBarScroll();
if(!_walkInPath) { if(!_walkInPath) {
return; return;
} }
Vec2 realPos(x, y); Vec2 realPos(x, y);
if(fabs((player->GetX() - x)) > 256 || fabs((player->GetY() - y)) > 256) { if(fabs((player->GetX() - x)) > 256 || fabs((player->GetY() - y)) > 256) {
return; return;
} }
if(isNearPlayer) { if(isNearPlayer) {
_walkInPath = false; _walkInPath = false;
return; return;
} }
float targetX = (float)(tileX * AStarTile::FAKE_SIZE); float targetX = (float)(tileX * AStarTile::FAKE_SIZE);
float targetY = (float)(tileY * AStarTile::FAKE_SIZE); float targetY = (float)(tileY * AStarTile::FAKE_SIZE);
float dx = targetX - realPos.x; float dx = targetX - realPos.x;
float dy = targetY - realPos.y; float dy = targetY - realPos.y;
if(dx > 0.0f) { if(dx > 0.0f) {
xVel = CHARACTER_SPEED; xVel = CHARACTER_SPEED;
} }
@ -99,16 +99,16 @@ void NPC::Move(void) {
} }
else if(dy < 0.0f) { else if(dy < 0.0f) {
yVel = -CHARACTER_SPEED; yVel = -CHARACTER_SPEED;
} }
if(xVel != 0.0f || yVel != 0.0f) { if(xVel != 0.0f || yVel != 0.0f) {
map->MoveIfPossible(this, xVel, yVel, false); map->MoveIfPossible(this, xVel, yVel, false);
} }
if(dx >= -CHARACTER_SPEED && dx <= CHARACTER_SPEED && if(dx >= -CHARACTER_SPEED && dx <= CHARACTER_SPEED &&
dy >= -CHARACTER_SPEED && dy <= CHARACTER_SPEED) { dy >= -CHARACTER_SPEED && dy <= CHARACTER_SPEED) {
_target = _astar.GetSolutionNext(); _target = _astar.GetSolutionNext();
if(_target == NULL || _target == _lastTarget) { if(_target == NULL || _target == _lastTarget) {
_walkInPath = false; _walkInPath = false;
} else { } else {
@ -122,30 +122,30 @@ void NPC::OnPlayerMove(Player* player) {
if(fabs((player->GetX() - x)) > 256 || fabs((player->GetY() - y)) > 256) { if(fabs((player->GetX() - x)) > 256 || fabs((player->GetY() - y)) > 256) {
return; return;
} }
AStarTile& start = map->GetAStarTile(x / AStarTile::FAKE_SIZE, y / AStarTile::FAKE_SIZE);
AStarTile& goal = map->GetAStarTile(player->GetX() / AStarTile::FAKE_SIZE, player->GetY() / AStarTile::FAKE_SIZE);
_astar.SetStartAndGoalStates(start, goal); AStarTile& start = map->GetAStarTile(x / AStarTile::FAKE_SIZE, y / AStarTile::FAKE_SIZE);
AStarTile& goal = map->GetAStarTile(player->GetX() / AStarTile::FAKE_SIZE, player->GetY() / AStarTile::FAKE_SIZE);
_walkInPath = false; _astar.SetStartAndGoalStates(start, goal);
while(true) { _walkInPath = false;
unsigned int state = _astar.SearchStep();
if(state == AStarSearch<AStarTile>::SEARCH_STATE_SUCCEEDED) { while(true) {
_walkInPath = true; unsigned int state = _astar.SearchStep();
break; if(state == AStarSearch<AStarTile>::SEARCH_STATE_SUCCEEDED) {
} else if(state != AStarSearch<AStarTile>::SEARCH_STATE_SEARCHING) { _walkInPath = true;
break; break;
} } else if(state != AStarSearch<AStarTile>::SEARCH_STATE_SEARCHING) {
} break;
}
}
if(_walkInPath) { if(_walkInPath) {
_lastTarget = _astar.GetSolutionEnd(); _lastTarget = _astar.GetSolutionEnd();
_target = _astar.GetSolutionStart(); _target = _astar.GetSolutionStart();
_target = _astar.GetSolutionNext(); _target = _astar.GetSolutionNext();
if(_target == NULL) { if(_target == NULL) {
_walkInPath = false; _walkInPath = false;
_target = NULL; _target = NULL;

View File

@ -9,27 +9,27 @@ class Player;
class NPC : public Character { class NPC : public Character {
public: public:
NPC(LevelGen* mapArg); NPC(LevelGen* mapArg);
~NPC(void); ~NPC(void);
void ForceMove(void); void ForceMove(void);
void Update(void); void Update(void);
void OnPlayerMove(Player* player); void OnPlayerMove(Player* player);
protected: protected:
void Move(void); void Move(void);
void AttackPlayer(void); void AttackPlayer(void);
private: private:
bool _moving; bool _moving;
AStarSearch<AStarTile> _astar; AStarSearch<AStarTile> _astar;
bool _walkInPath; bool _walkInPath;
AStarTile* _target; AStarTile* _target;
AStarTile* _lastTarget; AStarTile* _lastTarget;
Timer _attackTimer; Timer _attackTimer;
static const int ATTACK_FREQUENCY = 1000; static const int ATTACK_FREQUENCY = 1000;
}; };

View File

@ -9,72 +9,72 @@ ParticleEmitter::~ParticleEmitter(void) {
} }
void ParticleEmitter::SetXY(int xArg, int yArg) { void ParticleEmitter::SetXY(int xArg, int yArg) {
x = xArg; x = xArg;
y = yArg; y = yArg;
} }
void ParticleEmitter::ForceXY(int xArg, int yArg) { void ParticleEmitter::ForceXY(int xArg, int yArg) {
for(int i = 0; i < _particleCount; i++) { for(int i = 0; i < _particleCount; i++) {
m_particle[i].x = (float)xArg; m_particle[i].x = (float)xArg;
m_particle[i].y = (float)yArg; m_particle[i].y = (float)yArg;
} }
} }
void ParticleEmitter::SetParticleCount(int countArg) { void ParticleEmitter::SetParticleCount(int countArg) {
_particleCount = countArg; _particleCount = countArg;
m_particle.resize(_particleCount); m_particle.resize(_particleCount);
for(int i = 0; i < _particleCount; i++) { for(int i = 0; i < _particleCount; i++) {
m_particle[i].startTime = SDL_GetTicks(); m_particle[i].startTime = SDL_GetTicks();
} }
} }
void ParticleEmitter::SetParticleSpeed(float speedArg) { void ParticleEmitter::SetParticleSpeed(float speedArg) {
_particleSpeed = speedArg; _particleSpeed = speedArg;
} }
void ParticleEmitter::SetParticleType(string typeArg) { void ParticleEmitter::SetParticleType(string typeArg) {
if(!_particleTexture) { if(!_particleTexture) {
SDL_FreeSurface(_particleTexture); SDL_FreeSurface(_particleTexture);
} }
string textureFilename = "../../Data/Media/Images/Particles/" + typeArg + ".png"; string textureFilename = "../../Data/Media/Images/Particles/" + typeArg + ".png";
_particleTexture = LoadImageAlpha(textureFilename.c_str()); _particleTexture = LoadImageAlpha(textureFilename.c_str());
} }
void ParticleEmitter::SetParticleLifetime(int lifetimeArg) { void ParticleEmitter::SetParticleLifetime(int lifetimeArg) {
_particleLifetime = lifetimeArg; _particleLifetime = lifetimeArg;
for(int i = 0; i < _particleCount; i++) { for(int i = 0; i < _particleCount; i++) {
m_particle[i].lifetime = rand() % _particleLifetime + _particleLifetime / 4; m_particle[i].lifetime = rand() % _particleLifetime + _particleLifetime / 4;
} }
} }
void ParticleEmitter::Render(void) { void ParticleEmitter::Render(void) {
for(int i = 0; i < _particleCount; i++) { for(int i = 0; i < _particleCount; i++) {
ApplySurface((int)m_particle[i].x, (int)m_particle[i].y, _particleTexture, screen); ApplySurface((int)m_particle[i].x, (int)m_particle[i].y, _particleTexture, screen);
} }
} }
void ParticleEmitter::Update(void) { void ParticleEmitter::Update(void) {
for(int i = 0; i < _particleCount; i++) { for(int i = 0; i < _particleCount; i++) {
if((int)SDL_GetTicks() - m_particle[i].startTime > m_particle[i].lifetime) { if((int)SDL_GetTicks() - m_particle[i].startTime > m_particle[i].lifetime) {
// Reset the x and y coords. // Reset the x and y coords.
m_particle[i].x = (float)x; m_particle[i].x = (float)x;
m_particle[i].y = (float)y; m_particle[i].y = (float)y;
m_particle[i].xVel = (float)(rand() % 360); m_particle[i].xVel = (float)(rand() % 360);
m_particle[i].yVel = (float)(rand() % 360); m_particle[i].yVel = (float)(rand() % 360);
if(rand() % 2) if(rand() % 2)
m_particle[i].xVel = m_particle[i].xVel * -1.0f; m_particle[i].xVel = m_particle[i].xVel * -1.0f;
if(rand() % 2) if(rand() % 2)
m_particle[i].yVel = m_particle[i].yVel * -1.0f; m_particle[i].yVel = m_particle[i].yVel * -1.0f;
m_particle[i].startTime = SDL_GetTicks(); m_particle[i].startTime = SDL_GetTicks();
} else { } else {
m_particle[i].x += m_particle[i].xVel * _particleSpeed; m_particle[i].x += m_particle[i].xVel * _particleSpeed;
m_particle[i].y += m_particle[i].yVel * _particleSpeed; m_particle[i].y += m_particle[i].yVel * _particleSpeed;
} }
} }
} }

View File

@ -15,493 +15,493 @@ using namespace std;
// The search class. UserState is the users state space type. // The search class. UserState is the users state space type.
template<class UserState> class AStarSearch { template<class UserState> class AStarSearch {
public: public:
enum { enum {
SEARCH_STATE_NOT_INITIALIZED, SEARCH_STATE_NOT_INITIALIZED,
SEARCH_STATE_SEARCHING, SEARCH_STATE_SEARCHING,
SEARCH_STATE_SUCCEEDED, SEARCH_STATE_SUCCEEDED,
SEARCH_STATE_FAILED, SEARCH_STATE_FAILED,
SEARCH_STATE_OUT_OF_MEMORY, SEARCH_STATE_OUT_OF_MEMORY,
SEARCH_STATE_INVALID SEARCH_STATE_INVALID
}; };
// A node representing a possible state in the search. // A node representing a possible state in the search.
public: public:
class Node { class Node {
public: public:
// Keep a record of successor nodes. // Keep a record of successor nodes.
Node* parent; Node* parent;
// Used to view the search in reverse at the end. // Used to view the search in reverse at the end.
Node* child; Node* child;
float g; // Cost of this and it's predecessors. float g; // Cost of this and it's predecessors.
float h; // Heuristic estimate of the distance of the goal. float h; // Heuristic estimate of the distance of the goal.
float f; // Sum of cost and heuristic. float f; // Sum of cost and heuristic.
Node(UserState userState) : parent(0), child(0), g(0.0f), h(0.0f), f(0.0), _userState(userState) {} Node(UserState userState) : parent(0), child(0), g(0.0f), h(0.0f), f(0.0), _userState(userState) {}
UserState _userState; UserState _userState;
}; };
// Compare the f values of the two nodes. // Compare the f values of the two nodes.
class HeapCompare_f { class HeapCompare_f {
public: public:
bool operator()(const Node* x, const Node* y) const { bool operator()(const Node* x, const Node* y) const {
return x->f > y->f; return x->f > y->f;
} }
}; };
public: public:
AStarSearch(void) : AStarSearch(void) :
_state(SEARCH_STATE_NOT_INITIALIZED), _state(SEARCH_STATE_NOT_INITIALIZED),
_currentSolutionNode(NULL), _currentSolutionNode(NULL),
_allocateNodeCount(0), _allocateNodeCount(0),
_cancelRequest(false) {} _cancelRequest(false) {}
~AStarSearch(void) {} ~AStarSearch(void) {}
int GetState(void) { return _state; } int GetState(void) { return _state; }
// Cancel the search and free up the memory. -- This can be called at any time. // Cancel the search and free up the memory. -- This can be called at any time.
void CancelSearch(void) { _cancelRequest = true; } void CancelSearch(void) { _cancelRequest = true; }
// Set the start/goal state. // Set the start/goal state.
void SetStartAndGoalStates(UserState& start, UserState& goal) { void SetStartAndGoalStates(UserState& start, UserState& goal) {
_cancelRequest= false; _cancelRequest= false;
_start = AllocateNode(start); _start = AllocateNode(start);
_goal = AllocateNode(goal); _goal = AllocateNode(goal);
assert((_start != NULL && _goal != NULL)); assert((_start != NULL && _goal != NULL));
_state = SEARCH_STATE_SEARCHING; _state = SEARCH_STATE_SEARCHING;
// Initialize the AStar specific parts of the start node. // Initialize the AStar specific parts of the start node.
// You only need to fill out the state information. // You only need to fill out the state information.
_start->g = 0; _start->g = 0;
_start->h = _start->_userState.GoalDistanceEstimate(_goal->_userState); _start->h = _start->_userState.GoalDistanceEstimate(_goal->_userState);
_start->f = _start->g + _start->h; _start->f = _start->g + _start->h;
_start->parent = 0; _start->parent = 0;
// Push the start node onto the open list. // Push the start node onto the open list.
_openList.push_back(_start); // Heap is now unsorted. _openList.push_back(_start); // Heap is now unsorted.
// Sort back element into the heap. // Sort back element into the heap.
push_heap(_openList.begin(), _openList.end(), HeapCompare_f()); push_heap(_openList.begin(), _openList.end(), HeapCompare_f());
// Initialize counter for the search steps. // Initialize counter for the search steps.
_steps = 0; _steps = 0;
} }
// Search one step. // Search one step.
unsigned int SearchStep(void) { unsigned int SearchStep(void) {
// Break if the search has not been initialized. // Break if the search has not been initialized.
assert((_state > SEARCH_STATE_NOT_INITIALIZED) && ( _state < SEARCH_STATE_INVALID)); assert((_state > SEARCH_STATE_NOT_INITIALIZED) && ( _state < SEARCH_STATE_INVALID));
// Ensure it is safe to do a seach step once the seach has succeeded. // Ensure it is safe to do a seach step once the seach has succeeded.
if((_state == SEARCH_STATE_SUCCEEDED) || (_state == SEARCH_STATE_FAILED)) { return false; } if((_state == SEARCH_STATE_SUCCEEDED) || (_state == SEARCH_STATE_FAILED)) { return false; }
if(_openList.empty() || _cancelRequest) { if(_openList.empty() || _cancelRequest) {
// Then there is nothing left to search, so fail. // Then there is nothing left to search, so fail.
FreeAllNodes(); FreeAllNodes();
_state = SEARCH_STATE_FAILED; _state = SEARCH_STATE_FAILED;
return _state; return _state;
} }
_steps++; _steps++;
// Pop the best node. -- The one with the lowest f. // Pop the best node. -- The one with the lowest f.
Node* n = _openList.front(); // Get pointer to the node. Node* n = _openList.front(); // Get pointer to the node.
pop_heap(_openList.begin(), _openList.end(), HeapCompare_f()); pop_heap(_openList.begin(), _openList.end(), HeapCompare_f());
_openList.pop_back(); _openList.pop_back();
// Check for the goal, once we pop that, we are done. // Check for the goal, once we pop that, we are done.
if(n->_userState.IsGoal(_goal->_userState)) { if(n->_userState.IsGoal(_goal->_userState)) {
// Copy the parent pointer of n, as we will use the passed in goal node. // Copy the parent pointer of n, as we will use the passed in goal node.
_goal->parent = n->parent; _goal->parent = n->parent;
// If the goal was passed in at the start.. // If the goal was passed in at the start..
if(false == n->_userState.IsSameState(_start->_userState)) { if(false == n->_userState.IsSameState(_start->_userState)) {
FreeNode(n); FreeNode(n);
// Set the child pointers in each node, apart from goal, as it has no child. // Set the child pointers in each node, apart from goal, as it has no child.
Node* nodeChild = _goal; Node* nodeChild = _goal;
Node* nodeParent = _goal->parent; Node* nodeParent = _goal->parent;
while(nodeChild != _start) { while(nodeChild != _start) {
// Start is always the first node by definition. // Start is always the first node by definition.
nodeParent->child = nodeChild; nodeParent->child = nodeChild;
nodeChild = nodeParent; nodeChild = nodeParent;
nodeParent = nodeParent->parent; nodeParent = nodeParent->parent;
} }
} }
// Delete nodes that are not needed for the solution. // Delete nodes that are not needed for the solution.
FreeUnusedNodes(); FreeUnusedNodes();
_state = SEARCH_STATE_SUCCEEDED; _state = SEARCH_STATE_SUCCEEDED;
return _state; return _state;
} else { } else {
// Not goal. // Not goal.
/* /*
* Generate the successors of this node. * Generate the successors of this node.
* The user helps us to do this, and we keep * The user helps us to do this, and we keep
* the new nodes in _successors. * the new nodes in _successors.
*/ */
_successors.clear(); // empty the vector of successor nodes to n. _successors.clear(); // empty the vector of successor nodes to n.
// The user provides this functions and uses AddSuccessor to add each // The user provides this functions and uses AddSuccessor to add each
// successor of node 'n' to _successors. // successor of node 'n' to _successors.
bool ret = n->_userState.GetSuccessors(this/*, n->parent ? &n->parent->_userState : NULL*/); bool ret = n->_userState.GetSuccessors(this/*, n->parent ? &n->parent->_userState : NULL*/);
if(!ret) { if(!ret) {
typename vector<Node*>::iterator successor; typename vector<Node*>::iterator successor;
// Free the nodes that may have previously been added. // Free the nodes that may have previously been added.
for(successor = _successors.begin(); successor != _successors.end(); successor++) { for(successor = _successors.begin(); successor != _successors.end(); successor++) {
FreeNode((*successor)); FreeNode((*successor));
} }
// Empty vector of successor nodes nodes to n. // Empty vector of successor nodes nodes to n.
_successors.clear(); _successors.clear();
// Free up everything else we allocated along the way. // Free up everything else we allocated along the way.
FreeAllNodes(); FreeAllNodes();
_state = SEARCH_STATE_OUT_OF_MEMORY; _state = SEARCH_STATE_OUT_OF_MEMORY;
return _state; return _state;
} }
// Now handle each successor to the current node.. // Now handle each successor to the current node..
for(typename vector<Node*>::iterator successor = _successors.begin(); successor != _successors.end(); successor++) { for(typename vector<Node*>::iterator successor = _successors.begin(); successor != _successors.end(); successor++) {
// The g value for this successor. // The g value for this successor.
float newg = n->g + n->_userState.GetCost((*successor)->_userState); float newg = n->g + n->_userState.GetCost((*successor)->_userState);
/* /*
* We need to see whether the node is on the open or closed * We need to see whether the node is on the open or closed
* list. If it is, but the node that is already on them is better * list. If it is, but the node that is already on them is better
* (lower g) then we can forget about this successor. * (lower g) then we can forget about this successor.
* *
* First linear search of open list to find node. * First linear search of open list to find node.
*/ */
typename vector<Node*>::iterator openlist_result; typename vector<Node*>::iterator openlist_result;
for(openlist_result = _openList.begin(); openlist_result != _openList.end(); openlist_result++) { for(openlist_result = _openList.begin(); openlist_result != _openList.end(); openlist_result++) {
if((*openlist_result)->_userState.IsSameState((*successor)->_userState)) { if((*openlist_result)->_userState.IsSameState((*successor)->_userState)) {
break; break;
} }
} }
if(openlist_result != _openList.end()) { if(openlist_result != _openList.end()) {
// We found this state open. // We found this state open.
if((*openlist_result)->g <= newg) { if((*openlist_result)->g <= newg) {
FreeNode((*successor)); FreeNode((*successor));
// The one on the open list is cheaper than this one. // The one on the open list is cheaper than this one.
continue; continue;
} }
} }
typename vector<Node*>::iterator closedlist_result; typename vector<Node*>::iterator closedlist_result;
for(closedlist_result = _closedList.begin(); closedlist_result != _closedList.end(); closedlist_result++) { for(closedlist_result = _closedList.begin(); closedlist_result != _closedList.end(); closedlist_result++) {
if((*closedlist_result)->_userState.IsSameState((*successor)->_userState)) { if((*closedlist_result)->_userState.IsSameState((*successor)->_userState)) {
break; break;
} }
} }
if(closedlist_result != _closedList.end()) { if(closedlist_result != _closedList.end()) {
// We found this state closed. // We found this state closed.
if((*closedlist_result)->g <= newg) { if((*closedlist_result)->g <= newg) {
// The one on the closed list is cheaper than this one. // The one on the closed list is cheaper than this one.
FreeNode((*successor)); FreeNode((*successor));
continue; continue;
} }
} }
// This node is the best node so fat with this particular state. // This node is the best node so fat with this particular state.
// So lets keep it, and set up its AStar specific data.. // So lets keep it, and set up its AStar specific data..
(*successor)->parent = n; (*successor)->parent = n;
(*successor)->g = newg; (*successor)->g = newg;
(*successor)->h = (*successor)->_userState.GoalDistanceEstimate(_goal->_userState); (*successor)->h = (*successor)->_userState.GoalDistanceEstimate(_goal->_userState);
(*successor)->f = (*successor)->g + (*successor)->h; (*successor)->f = (*successor)->g + (*successor)->h;
// Remove successor from closed if it was on it. // Remove successor from closed if it was on it.
if(closedlist_result != _closedList.end()) { if(closedlist_result != _closedList.end()) {
// Remove it from the closed list. // Remove it from the closed list.
FreeNode((*closedlist_result)); FreeNode((*closedlist_result));
_closedList.erase(closedlist_result); _closedList.erase(closedlist_result);
// Now remake the heap!! // Now remake the heap!!
make_heap(_openList.begin(), _openList.end(), HeapCompare_f()); make_heap(_openList.begin(), _openList.end(), HeapCompare_f());
} }
// The heap is now unsorted. // The heap is now unsorted.
_openList.push_back((*successor)); _openList.push_back((*successor));
// Sort back elements into the heap. // Sort back elements into the heap.
push_heap(_openList.begin(), _openList.end(), HeapCompare_f()); push_heap(_openList.begin(), _openList.end(), HeapCompare_f());
} }
// push n onto the closed list as it has now been expanded. // push n onto the closed list as it has now been expanded.
_closedList.push_back(n); _closedList.push_back(n);
} // (Not goal, so expand) } // (Not goal, so expand)
return _state; // Succeeded bool should be false at this point. return _state; // Succeeded bool should be false at this point.
} }
// Call this to add a successor to a list of // Call this to add a successor to a list of
// successors when expanding the seach frontier. // successors when expanding the seach frontier.
bool AddSuccessor(UserState& state) { bool AddSuccessor(UserState& state) {
Node* node = AllocateNode(state); Node* node = AllocateNode(state);
if(node) { if(node) {
node->_userState = state; node->_userState = state;
_successors.push_back(node); _successors.push_back(node);
return true; return true;
} }
return false; return false;
} }
// Free the solution nodes. // Free the solution nodes.
// This is done to clean up all used nodes in memory when you are // This is done to clean up all used nodes in memory when you are
// done with the search. // done with the search.
void FreeSolutionNodes(void) { void FreeSolutionNodes(void) {
Node* n = _start; Node* n = _start;
if(_start->child) { if(_start->child) {
while(n != _goal) { while(n != _goal) {
Node* del = n; Node* del = n;
n = n->child; n = n->child;
FreeNode(del); FreeNode(del);
del = NULL; del = NULL;
} }
FreeNode(n); // Delete the goal. FreeNode(n); // Delete the goal.
} else { } else {
// If the start node is the solution, we need to just // If the start node is the solution, we need to just
// delete the start goal nodes. // delete the start goal nodes.
FreeNode(_start); FreeNode(_start);
FreeNode(_goal); FreeNode(_goal);
} }
} }
// -- Some methods for travelling through the solution. -- // -- Some methods for travelling through the solution. --
// Get the start node. // Get the start node.
UserState* GetSolutionStart(void) { UserState* GetSolutionStart(void) {
_currentSolutionNode = _start; _currentSolutionNode = _start;
if(_start) { if(_start) {
return &_start->_userState; return &_start->_userState;
} else { } else {
return NULL; return NULL;
} }
} }
// Get the next node. // Get the next node.
UserState* GetSolutionNext(void) { UserState* GetSolutionNext(void) {
if(_currentSolutionNode) { if(_currentSolutionNode) {
if(_currentSolutionNode->child) { if(_currentSolutionNode->child) {
Node* child = _currentSolutionNode->child; Node* child = _currentSolutionNode->child;
_currentSolutionNode = _currentSolutionNode->child; _currentSolutionNode = _currentSolutionNode->child;
return &child->_userState; return &child->_userState;
} }
} }
return NULL; return NULL;
} }
// Get the end node. // Get the end node.
UserState* GetSolutionEnd(void) { UserState* GetSolutionEnd(void) {
_currentSolutionNode = _goal; _currentSolutionNode = _goal;
if(_goal) { if(_goal) {
return &_goal->_userState; return &_goal->_userState;
} else { } else {
return NULL; return NULL;
} }
} }
// Step through the solution backwards. // Step through the solution backwards.
UserState* GetSolutionPrev(void) { UserState* GetSolutionPrev(void) {
if(_currentSolutionNode) { if(_currentSolutionNode) {
if(_currentSolutionNode->parent) { if(_currentSolutionNode->parent) {
Node* parent = _currentSolutionNode->parent; Node* parent = _currentSolutionNode->parent;
_currentSolutionNode = _currentSolutionNode->parent; _currentSolutionNode = _currentSolutionNode->parent;
return &parent->_userState; return &parent->_userState;
} }
} }
return NULL; return NULL;
} }
// It will be useful to be able to view the open // It will be useful to be able to view the open
// and closed lists at each step for debugging. // and closed lists at each step for debugging.
UserState* GetOpenListStart(void) { UserState* GetOpenListStart(void) {
float f, g, h; float f, g, h;
return GetOpenListStart(f, g, h); return GetOpenListStart(f, g, h);
} }
UserState* GetOpenListStart(float& f, float& g, float& h) { UserState* GetOpenListStart(float& f, float& g, float& h) {
iterDbgOpen = _openList.begin(); iterDbgOpen = _openList.begin();
if(iterDbgOpen != _openList.end()) { if(iterDbgOpen != _openList.end()) {
f = (*iterDbgOpen)->f; f = (*iterDbgOpen)->f;
g = (*iterDbgOpen)->g; g = (*iterDbgOpen)->g;
h = (*iterDbgOpen)->h; h = (*iterDbgOpen)->h;
return &(*iterDbgOpen)->_userState; return &(*iterDbgOpen)->_userState;
} }
return NULL; return NULL;
} }
UserState* GetOpenListNext(void) { UserState* GetOpenListNext(void) {
float f, g, h; float f, g, h;
return GetOpenListNext(f, g, h); return GetOpenListNext(f, g, h);
} }
UserState* GetOpenListNext(float& f, float& g, float& h) { UserState* GetOpenListNext(float& f, float& g, float& h) {
iterDbgOpen++; iterDbgOpen++;
if(iterDbgOpen != _openList.end()) { if(iterDbgOpen != _openList.end()) {
f = (*iterDbgOpen)->f; f = (*iterDbgOpen)->f;
g = (*iterDbgOpen)->g; g = (*iterDbgOpen)->g;
h = (*iterDbgOpen)->h; h = (*iterDbgOpen)->h;
return &(*iterDbgOpen)->_userState; return &(*iterDbgOpen)->_userState;
} }
return NULL; return NULL;
} }
// Closes states. // Closes states.
UserState* GetClosedListStart(void) { UserState* GetClosedListStart(void) {
float f, g, h; float f, g, h;
return GetClosedListStart(f, g, h); return GetClosedListStart(f, g, h);
} }
UserState* GetClosedListStart(float& f, float& g, float& h) { UserState* GetClosedListStart(float& f, float& g, float& h) {
iterDbgClosed = _closedList.begin(); iterDbgClosed = _closedList.begin();
if(iterDbgClosed != _closedList.begin()) { if(iterDbgClosed != _closedList.begin()) {
f = (*iterDbgClosed)->f; f = (*iterDbgClosed)->f;
g = (*iterDbgClosed)->g; g = (*iterDbgClosed)->g;
h = (*iterDbgClosed)->h; h = (*iterDbgClosed)->h;
return &(iterDbgClosed)->_userState; return &(iterDbgClosed)->_userState;
} }
return NULL; return NULL;
} }
UserState* GetClosedListNext(void) { UserState* GetClosedListNext(void) {
float f, g, h; float f, g, h;
return GetClosedListNext(f, g, h); return GetClosedListNext(f, g, h);
} }
UserState* GetClosedListNext(float& f, float& g, float& h) { UserState* GetClosedListNext(float& f, float& g, float& h) {
iterDbgClosed++; iterDbgClosed++;
if(iterDbgClosed != _closedList.end()) { if(iterDbgClosed != _closedList.end()) {
f = (*iterDbgClosed)->f; f = (*iterDbgClosed)->f;
g = (*iterDbgClosed)->g; g = (*iterDbgClosed)->g;
h = (*iterDbgClosed)->h; h = (*iterDbgClosed)->h;
return &(*iterDbgClosed)->_userState; return &(*iterDbgClosed)->_userState;
} }
return NULL; return NULL;
} }
// Get the number of steps. // Get the number of steps.
int GetStepCount(void) {return _steps; } int GetStepCount(void) {return _steps; }
private: private:
// Called when a search fails or is cancelled to free up all unused memory. // Called when a search fails or is cancelled to free up all unused memory.
void FreeAllNodes(void) { void FreeAllNodes(void) {
// Iterate the open list and delete all nodes. // Iterate the open list and delete all nodes.
typename vector<Node*>::iterator iterOpen = _openList.begin(); typename vector<Node*>::iterator iterOpen = _openList.begin();
while(iterOpen != _openList.end()) { while(iterOpen != _openList.end()) {
Node* n = (*iterOpen); Node* n = (*iterOpen);
FreeNode(n); FreeNode(n);
iterOpen++; iterOpen++;
} }
_openList.clear(); _openList.clear();
// Iterate closed list and delete unused nodes. // Iterate closed list and delete unused nodes.
typename vector<Node*>::iterator iterClosed; typename vector<Node*>::iterator iterClosed;
for(iterClosed = _closedList.begin(); iterClosed != _closedList.end(); iterClosed++) { for(iterClosed = _closedList.begin(); iterClosed != _closedList.end(); iterClosed++) {
Node* n = (*iterClosed); Node* n = (*iterClosed);
FreeNode(n); FreeNode(n);
} }
_closedList.clear(); _closedList.clear();
// Delete the goal. // Delete the goal.
FreeNode(_goal); FreeNode(_goal);
} }
/* /*
* Called when the search ends. A lot of nodes may * Called when the search ends. A lot of nodes may
* be created that are still present when the search * be created that are still present when the search
* ends. They will be deleted with this method. * ends. They will be deleted with this method.
*/ */
void FreeUnusedNodes(void) { void FreeUnusedNodes(void) {
// Iterate open list and delete unused nodes. // Iterate open list and delete unused nodes.
typename vector<Node*>::iterator iterOpen = _openList.begin(); typename vector<Node*>::iterator iterOpen = _openList.begin();
while(iterOpen != _openList.end()) { while(iterOpen != _openList.end()) {
Node *n = (*iterOpen); Node *n = (*iterOpen);
if(!n->child) { if(!n->child) {
FreeNode(n); FreeNode(n);
n = NULL; n = NULL;
} }
iterOpen++; iterOpen++;
} }
_openList.clear(); _openList.clear();
// Iterate closed list and delete all unused nodes. // Iterate closed list and delete all unused nodes.
typename vector<Node*>::iterator iterClosed; typename vector<Node*>::iterator iterClosed;
for(iterClosed = _closedList.begin(); iterClosed != _closedList.end(); iterClosed++) { for(iterClosed = _closedList.begin(); iterClosed != _closedList.end(); iterClosed++) {
Node *n = (*iterClosed); Node *n = (*iterClosed);
if(!n->child) { if(!n->child) {
FreeNode(n); FreeNode(n);
n = NULL; n = NULL;
} }
} }
_closedList.clear(); _closedList.clear();
} }
Node* AllocateNode(UserState& userState) { Node* AllocateNode(UserState& userState) {
Node *p = new Node(userState); Node *p = new Node(userState);
return p; return p;
} }
void FreeNode(Node* node) { void FreeNode(Node* node) {
_allocateNodeCount--; _allocateNodeCount--;
delete node; delete node;
} }
// Data. // Data.
private: private:
// Heap. // Heap.
vector<Node*> _openList; vector<Node*> _openList;
vector<Node*> _closedList; vector<Node*> _closedList;
vector<Node*> _successors; vector<Node*> _successors;
// State. // State.
unsigned int _state; unsigned int _state;
// Count steps. // Count steps.
int _steps; int _steps;
// Start/Goal state pointers. // Start/Goal state pointers.
Node* _start; Node* _start;
Node* _goal; Node* _goal;
Node* _currentSolutionNode; Node* _currentSolutionNode;
// Debug // Debug
typename vector<Node*>::iterator iterDbgOpen; typename vector<Node*>::iterator iterDbgOpen;
typename vector<Node*>::iterator iterDbgClosed; typename vector<Node*>::iterator iterDbgClosed;
// Count memory allocations and free. // Count memory allocations and free.
int _allocateNodeCount; int _allocateNodeCount;
bool _cancelRequest; bool _cancelRequest;
}; };

View File

@ -13,5 +13,5 @@ void Spells::CastSpell() {
} }
void Spells::Render(void) { void Spells::Render(void) {
//_particle->Render(); //_particle->Render();
} }

View File

@ -5,18 +5,18 @@
class Spells { class Spells {
public: public:
Spells(void); Spells(void);
~Spells(void); ~Spells(void);
enum { enum {
FIREBALL, FIREBALL,
ICE ICE
}; };
void CastSpell(/*Player* player*/); void CastSpell(/*Player* player*/);
void Render(void); void Render(void);
private: private:
Timer* _timeBetweenCast; Timer* _timeBetweenCast;
ParticleEmitter* _particle; ParticleEmitter* _particle;
}; };

View File

@ -5,190 +5,190 @@
#include "../UI/EventHistory.h" #include "../UI/EventHistory.h"
WorldManager::WorldManager(LevelGen* level) { WorldManager::WorldManager(LevelGen* level) {
_level = level; _level = level;
} }
WorldManager::~WorldManager(void) { WorldManager::~WorldManager(void) {
for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) { for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) {
NPC* npc = (*i); NPC* npc = (*i);
delete npc; delete npc;
} }
} }
void WorldManager::Update(void) { void WorldManager::Update(void) {
for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) { for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) {
NPC* npc = (*i); NPC* npc = (*i);
npc->Update(); npc->Update();
} }
} }
void WorldManager::Render(void) { void WorldManager::Render(void) {
for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) { for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) {
NPC* npc = (*i); NPC* npc = (*i);
npc->Render(); npc->Render();
} }
} }
void WorldManager::AddNPC(NPC* npc) { void WorldManager::AddNPC(NPC* npc) {
_npcs.push_back(npc); _npcs.push_back(npc);
} }
void WorldManager::RemoveNPC(int index) { void WorldManager::RemoveNPC(int index) {
int npcsIndex = 0; int npcsIndex = 0;
for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) { for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) {
NPC* npc = (*i); NPC* npc = (*i);
if(npcsIndex == index) { if(npcsIndex == index) {
_npcs.erase(i); _npcs.erase(i);
delete npc; delete npc;
} }
npcsIndex++; npcsIndex++;
} }
} }
NPC* WorldManager::GetNPC(int index) { NPC* WorldManager::GetNPC(int index) {
int npcsIndex = 0; int npcsIndex = 0;
for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) { for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) {
NPC* npc = (*i); NPC* npc = (*i);
if(npcsIndex == index) { if(npcsIndex == index) {
return npc; return npc;
} }
npcsIndex++; npcsIndex++;
} }
return NULL; return NULL;
} }
NPC* WorldManager::GetNPCAt(int xArg, int yArg) { NPC* WorldManager::GetNPCAt(int xArg, int yArg) {
for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) { for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) {
NPC* npc = (*i); NPC* npc = (*i);
if(xArg >= npc->GetX() && xArg <= (npc->GetX() + npc->GetWidth()) && if(xArg >= npc->GetX() && xArg <= (npc->GetX() + npc->GetWidth()) &&
yArg >= npc->GetY() && yArg <= (npc->GetY() + npc->GetHeight())) { yArg >= npc->GetY() && yArg <= (npc->GetY() + npc->GetHeight())) {
return npc; return npc;
} }
} }
return NULL; return NULL;
} }
void WorldManager::CreateNPC(int x, int y) { void WorldManager::CreateNPC(int x, int y) {
NPC* npc = new NPC(_level); NPC* npc = new NPC(_level);
npc->SetXY(x, y); npc->SetXY(x, y);
npc->ForceMove(); npc->ForceMove();
npc->LoadSprites("../Data/Media/Images/Characters/template.png", 40,45); npc->LoadSprites("../Data/Media/Images/Characters/template.png", 40,45);
_npcs.push_back(npc); _npcs.push_back(npc);
} }
bool WorldManager::CheckCollision(const SDL_Rect& charRect, Character* exclude) { bool WorldManager::CheckCollision(const SDL_Rect& charRect, Character* exclude) {
for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) { for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) {
NPC* npc = (*i); NPC* npc = (*i);
if(npc == exclude) {
continue;
}
if(npc == exclude) {
continue;
}
SDL_Rect npcRect; SDL_Rect npcRect;
npcRect.x = npc->GetX(); npcRect.x = npc->GetX();
npcRect.y = npc->GetY()/* + (npc->GetHeight() / 4) * 3*/; npcRect.y = npc->GetY()/* + (npc->GetHeight() / 4) * 3*/;
npcRect.w = npc->GetWidth(); npcRect.w = npc->GetWidth();
npcRect.h = npc->GetHeight()/* / 4*/; npcRect.h = npc->GetHeight()/* / 4*/;
if(CheckCollisionRect(npcRect, charRect)) { if(CheckCollisionRect(npcRect, charRect)) {
return true; return true;
} }
} }
return false; return false;
} }
void WorldManager::OnPlayerAttack(Player* player) { void WorldManager::OnPlayerAttack(Player* player) {
int playerX = (int)(player->GetX() / 32.0f); int playerX = (int)(player->GetX() / 32.0f);
int playerY = (int)(player->GetY() / 32.0f); int playerY = (int)(player->GetY() / 32.0f);
int playerDir = player->GetDirectionFacing(); int playerDir = player->GetDirectionFacing();
std::list<NPC*>::iterator i = _npcs.begin(); std::list<NPC*>::iterator i = _npcs.begin();
while(i != _npcs.end()) { while(i != _npcs.end()) {
NPC* npc = (*i); NPC* npc = (*i);
int npcX = (int)(npc->GetX() / 32.0f); int npcX = (int)(npc->GetX() / 32.0f);
int npcY = (int)(npc->GetY() / 32.0f); int npcY = (int)(npc->GetY() / 32.0f);
int diffX = npcX - playerX; int diffX = npcX - playerX;
int diffY = npcY - playerY; int diffY = npcY - playerY;
// Not in player's line of sight. // Not in player's line of sight.
if(diffX != 0 && diffY != 0) { if(diffX != 0 && diffY != 0) {
++i; ++i;
continue; continue;
} }
// Distance is greater than 2. // Distance is greater than 2.
if(abs(diffX) > 2 || abs(diffY) > 2) { if(abs(diffX) > 2 || abs(diffY) > 2) {
++i; ++i;
continue; continue;
} }
// Player not facing the npc. // Player not facing the npc.
if((diffX < 0 && playerDir != Character::FACING_LEFT) || if((diffX < 0 && playerDir != Character::FACING_LEFT) ||
(diffX > 0 && playerDir != Character::FACING_RIGHT) || (diffX > 0 && playerDir != Character::FACING_RIGHT) ||
(diffY < 0 && playerDir != Character::FACING_UP) || (diffY < 0 && playerDir != Character::FACING_UP) ||
(diffY > 0 && playerDir != Character::FACING_DOWN)) (diffY > 0 && playerDir != Character::FACING_DOWN))
{ {
++i; ++i;
continue; continue;
} }
npc->SetHealth(npc->GetHealth() - 20); npc->SetHealth(npc->GetHealth() - 20);
npc->OnAttack(); npc->OnAttack();
if(npc->GetHealth() <= 0) { if(npc->GetHealth() <= 0) {
// Please note: // Please note:
// Naked dudes are known to be sensitive to spicy food. // Naked dudes are known to be sensitive to spicy food.
std::string waysOfDeath[] = { std::string waysOfDeath[] = {
"Choked Naked Dude!", "Choked Naked Dude!",
"Stabbed Naked Dude!", "Stabbed Naked Dude!",
"Urinated Acid on Naked Dude!", "Urinated Acid on Naked Dude!",
"Killed Naked Dude with a dildo!", "Killed Naked Dude with a dildo!",
"Poured Tabasco on Naked Dude!", "Poured Tabasco on Naked Dude!",
"Threw Acid on Naked Dude!", "Threw Acid on Naked Dude!",
"Slapped Naked Dude with Dead Fish!", "Slapped Naked Dude with Dead Fish!",
"Killed Naked Dude with a Pistol!", "Killed Naked Dude with a Pistol!",
"Ate Naked Dude's brain!", "Ate Naked Dude's brain!",
"Slaughtered Naked Dude!", "Slaughtered Naked Dude!",
"Roasted Naked Dude!", "Roasted Naked Dude!",
"Pepper Sprayed Naked Dude!", "Pepper Sprayed Naked Dude!",
"Stoned Naked Dude!", "Stoned Naked Dude!",
"Slayed Naked Dude with a Katana!", "Slayed Naked Dude with a Katana!",
"Threw Chili Peppers on Naked Dude!", "Threw Chili Peppers on Naked Dude!",
"Used Karate on Naked Dude!", "Used Karate on Naked Dude!",
"Beat the shit out of Naked Dude!", "Beat the shit out of Naked Dude!",
"FUS RO DAH!" "FUS RO DAH!"
}; };
eventHistory->LogEvent(waysOfDeath[rand() % (sizeof(waysOfDeath)/sizeof(std::string))]); eventHistory->LogEvent(waysOfDeath[rand() % (sizeof(waysOfDeath)/sizeof(std::string))]);
int expGain = 3 + (rand() % 2); int expGain = 3 + (rand() % 2);
player->SetExp(player->GetExp() + expGain); player->SetExp(player->GetExp() + expGain);
i = _npcs.erase(i); i = _npcs.erase(i);
delete npc; delete npc;
if(_npcs.empty()) { if(_npcs.empty()) {
_level->New(); _level->New();
int spawnX; int spawnX;
int spawnY; int spawnY;
_level->FindSpawnPoint(spawnX, spawnY, player->GetWidth(),player->GetHeight()); _level->FindSpawnPoint(spawnX, spawnY, player->GetWidth(),player->GetHeight());
player->SetXY(spawnX, spawnY); player->SetXY(spawnX, spawnY);
} }
} }
else { else {
++i; ++i;
} }
} }
} }
void WorldManager::OnPlayerMove(Player* player) { void WorldManager::OnPlayerMove(Player* player) {
for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) { for(std::list<NPC*>::iterator i = _npcs.begin(); i != _npcs.end(); ++i) {
(*i)->OnPlayerMove(player); (*i)->OnPlayerMove(player);
} }
} }

View File

@ -10,26 +10,26 @@ class LevelGen;
class WorldManager { class WorldManager {
public: public:
WorldManager(LevelGen* level); WorldManager(LevelGen* level);
~WorldManager(void); ~WorldManager(void);
void Update(void); void Update(void);
void Render(void); void Render(void);
void AddNPC(NPC* npc); void AddNPC(NPC* npc);
void RemoveNPC(int index); void RemoveNPC(int index);
NPC* GetNPC(int index); NPC* GetNPC(int index);
NPC* GetNPCAt(int xArg, int yArg); NPC* GetNPCAt(int xArg, int yArg);
void CreateNPC(int x, int y); void CreateNPC(int x, int y);
bool CheckCollision(const SDL_Rect& charRect, Character* exclude); bool CheckCollision(const SDL_Rect& charRect, Character* exclude);
int GetNPCCount() { return _npcs.size(); } int GetNPCCount() { return _npcs.size(); }
void OnPlayerAttack(Player* player); void OnPlayerAttack(Player* player);
void OnPlayerMove(Player* player); void OnPlayerMove(Player* player);
private: private:
LevelGen* _level; LevelGen* _level;
std::list<NPC*> _npcs; std::list<NPC*> _npcs;
}; };

View File

@ -24,7 +24,7 @@ bool AStarTile::GetSuccessors(AStarSearch<AStarTile>* search) {
if(!_level) { if(!_level) {
return false; return false;
} }
if(x > 0) { if(x > 0) {
AStarTile& successor = _level->GetAStarTile(x - 1, y); AStarTile& successor = _level->GetAStarTile(x - 1, y);
if(successor._passable) { if(successor._passable) {

View File

@ -15,42 +15,42 @@ LevelGen::~LevelGen(void) {
void LevelGen::New(void) { void LevelGen::New(void) {
Unload(); Unload();
_world = WorldManager(this); _world = WorldManager(this);
for(x = 0; x < TILE_ARRAY_WIDTH; x++) { for(x = 0; x < TILE_ARRAY_WIDTH; x++) {
for(y = 0; y < TILE_ARRAY_HEIGHT; y++) { for(y = 0; y < TILE_ARRAY_HEIGHT; y++) {
_tile[x][y].SetTileTextureName("grass"); _tile[x][y].SetTileTextureName("grass");
stringstream tilePath; stringstream tilePath;
tilePath << "../Data/Media/Images/Tiles/" << _tile[x][y].GetTileTextureName() << ".png"; tilePath << "../Data/Media/Images/Tiles/" << _tile[x][y].GetTileTextureName() << ".png";
_tile[x][y].SetTileTexture(_tileTextures.Add(tilePath.str())); _tile[x][y].SetTileTexture(_tileTextures.Add(tilePath.str()));
_tile[x][y].SetTileSolidity(false); _tile[x][y].SetTileSolidity(false);
_tile[x][y].SetTileXY(x * TILE_WIDTH, y * TILE_HEIGHT); _tile[x][y].SetTileXY(x * TILE_WIDTH, y * TILE_HEIGHT);
_tile[x][y].SetEntitySolidity(false); _tile[x][y].SetEntitySolidity(false);
} }
} }
// procedural generation // procedural generation
DoMagic(); DoMagic();
// pathfinding // pathfinding
UpdateAStarTiles(); UpdateAStarTiles();
} }
void LevelGen::Load(const string& filename) { void LevelGen::Load(const string& filename) {
Unload(); Unload();
_currentMap = filename; _currentMap = filename;
string fullMapPath = "../Data/Media/Maps/" + filename; string fullMapPath = "../Data/Media/Maps/" + filename;
Serialiser serialiser; Serialiser serialiser;
serialiser.Load(fullMapPath); serialiser.Load(fullMapPath);
Inflate(&serialiser); Inflate(&serialiser);
_world = WorldManager(this); _world = WorldManager(this);
GenerateEnemies(); GenerateEnemies();
UpdateAStarTiles(); UpdateAStarTiles();
@ -59,32 +59,32 @@ void LevelGen::Load(const string& filename) {
void LevelGen::Save(const string& filename) { void LevelGen::Save(const string& filename) {
Serialiser serialiser; Serialiser serialiser;
Deflate(&serialiser); Deflate(&serialiser);
_currentMap = filename; _currentMap = filename;
string fullMapPath = "../Data/Media/Maps/" + filename; string fullMapPath = "../Data/Media/Maps/" + filename;
serialiser.Save(fullMapPath); serialiser.Save(fullMapPath);
} }
void LevelGen::Update(void) { void LevelGen::Update(void) {
_world.Update(); _world.Update();
// Update the map so we can render when camera moves. // Update the map so we can render when camera moves.
} }
void LevelGen::Render(void) { void LevelGen::Render(void) {
for(int i = 0; i < TILE_ARRAY_WIDTH; i++) { for(int i = 0; i < TILE_ARRAY_WIDTH; i++) {
for(int j = 0; j < TILE_ARRAY_HEIGHT; j++) { for(int j = 0; j < TILE_ARRAY_HEIGHT; j++) {
_tile[i][j].Render(); _tile[i][j].Render();
} }
} }
_world.Render(); _world.Render();
} }
void LevelGen::Unload(void) { void LevelGen::Unload(void) {
_tileTextures.Unload(); _tileTextures.Unload();
_entityTextures.Unload(); _entityTextures.Unload();
for(int x = 0; x < TILE_ARRAY_WIDTH; x++) { for(int x = 0; x < TILE_ARRAY_WIDTH; x++) {
for(int y = 0; y < TILE_ARRAY_HEIGHT; y++) { for(int y = 0; y < TILE_ARRAY_HEIGHT; y++) {
_tile[x][y] = MapTile(); _tile[x][y] = MapTile();
@ -100,75 +100,75 @@ void LevelGen::DoMagic(void) {
GenerateEntities("barrel2", 100); GenerateEntities("barrel2", 100);
GenerateEntities("stone", 55); GenerateEntities("stone", 55);
GenerateEntities("stone2", 55); GenerateEntities("stone2", 55);
GenerateEntities("chest", 120); GenerateEntities("chest", 120);
GenerateEntities("chest2", 170); GenerateEntities("chest2", 170);
GenerateEntities("chest3", 270); GenerateEntities("chest3", 270);
MakeWalkingPaths(); MakeWalkingPaths();
GenerateEnemies(); GenerateEnemies();
} }
void LevelGen::GenerateEntities(const string& name, int frequency) { void LevelGen::GenerateEntities(const string& name, int frequency) {
int nextEntityGen = 1 + (rand() % frequency); int nextEntityGen = 1 + (rand() % frequency);
std::string filename = "../Data/Media/Images/Entities/" + name + ".png"; std::string filename = "../Data/Media/Images/Entities/" + name + ".png";
for(int x = 0; x < (TILE_ARRAY_WIDTH - 1); x++) { for(int x = 0; x < (TILE_ARRAY_WIDTH - 1); x++) {
for(int y = 0; y < (TILE_ARRAY_HEIGHT - 1); y++) { for(int y = 0; y < (TILE_ARRAY_HEIGHT - 1); y++) {
nextEntityGen--; nextEntityGen--;
if(!_tile[x][y].GetTileSolidity() && !_tile[x][y].GetEntitySolitity() && nextEntityGen <= 0) { if(!_tile[x][y].GetTileSolidity() && !_tile[x][y].GetEntitySolitity() && nextEntityGen <= 0) {
_tile[x][y].SetEntityTextureName(name); _tile[x][y].SetEntityTextureName(name);
_tile[x][y].SetEntityTexture(_entityTextures.AddAlpha(filename)); _tile[x][y].SetEntityTexture(_entityTextures.AddAlpha(filename));
_tile[x][y].SetEntityXY(_tile[x][y].GetTileX() + TILE_WIDTH / 2 - _tile[x][y].GetEntityWidth() / 2, _tile[x][y].SetEntityXY(_tile[x][y].GetTileX() + TILE_WIDTH / 2 - _tile[x][y].GetEntityWidth() / 2,
_tile[x][y].GetTileY() + TILE_HEIGHT / 2 - _tile[x][y].GetEntityHeight() / 2); _tile[x][y].GetTileY() + TILE_HEIGHT / 2 - _tile[x][y].GetEntityHeight() / 2);
_tile[x][y].SetEntitySolidity(true); _tile[x][y].SetEntitySolidity(true);
nextEntityGen = 1 + (rand() % frequency); nextEntityGen = 1 + (rand() % frequency);
} }
} }
} }
} }
void LevelGen::MakeWalkingPaths(void) { void LevelGen::MakeWalkingPaths(void) {
int lastOpenY = rand() % 5; int lastOpenY = rand() % 5;
for(int x = 0; x < TILE_ARRAY_WIDTH; x++) { for(int x = 0; x < TILE_ARRAY_WIDTH; x++) {
bool pathFound = false; bool pathFound = false;
for(int y = 0; y < TILE_ARRAY_HEIGHT; y++) { for(int y = 0; y < TILE_ARRAY_HEIGHT; y++) {
if(!_tile[x][y].GetEntitySolitity()) { if(!_tile[x][y].GetEntitySolitity()) {
pathFound = true; pathFound = true;
break; break;
} else { } else {
lastOpenY = y; lastOpenY = y;
} }
} }
if(!pathFound) { if(!pathFound) {
_tile[x][lastOpenY].SetEntityTexture(NULL); _tile[x][lastOpenY].SetEntityTexture(NULL);
_tile[x][lastOpenY].SetEntitySolidity(false); _tile[x][lastOpenY].SetEntitySolidity(false);
} }
} }
} }
void LevelGen::FindSpawnPoint(int& xArg, int& yArg, int objWidth, int objHeight) { void LevelGen::FindSpawnPoint(int& xArg, int& yArg, int objWidth, int objHeight) {
xArg = rand() % ((TILE_ARRAY_WIDTH - 1) * TILE_WIDTH); xArg = rand() % ((TILE_ARRAY_WIDTH - 1) * TILE_WIDTH);
yArg = rand() % ((TILE_ARRAY_HEIGHT - 1) * TILE_HEIGHT); yArg = rand() % ((TILE_ARRAY_HEIGHT - 1) * TILE_HEIGHT);
if((xArg + objWidth + 1) > SCREEN_WIDTH) { if((xArg + objWidth + 1) > SCREEN_WIDTH) {
xArg = SCREEN_WIDTH - objWidth - 1; xArg = SCREEN_WIDTH - objWidth - 1;
} }
if((yArg + objHeight + 1) > SCREEN_HEIGHT) { if((yArg + objHeight + 1) > SCREEN_HEIGHT) {
yArg = SCREEN_HEIGHT - objHeight - 1; yArg = SCREEN_HEIGHT - objHeight - 1;
} }
SDL_Rect objRect; SDL_Rect objRect;
objRect.x = xArg; objRect.x = xArg;
objRect.y = yArg; objRect.y = yArg;
objRect.w = objWidth; objRect.w = objWidth;
objRect.h = objHeight; objRect.h = objHeight;
NPC* npc = _world.GetNPCAt(xArg, yArg); NPC* npc = _world.GetNPCAt(xArg, yArg);
if(npc) { if(npc) {
SDL_Rect npcRect; SDL_Rect npcRect;
@ -176,13 +176,13 @@ void LevelGen::FindSpawnPoint(int& xArg, int& yArg, int objWidth, int objHeight)
npcRect.y = npc->GetY(); npcRect.y = npc->GetY();
npcRect.w = npc->GetWidth(); npcRect.w = npc->GetWidth();
npcRect.h = npc->GetHeight(); npcRect.h = npc->GetHeight();
if(CheckCollisionRect(npcRect, objRect)) { if(CheckCollisionRect(npcRect, objRect)) {
FindSpawnPoint(xArg, yArg, objWidth, objHeight); FindSpawnPoint(xArg, yArg, objWidth, objHeight);
return; return;
} }
} }
for(int i = 0; i < TILE_ARRAY_WIDTH; i++) { for(int i = 0; i < TILE_ARRAY_WIDTH; i++) {
for(int j = 0; j < TILE_ARRAY_HEIGHT; j++) { for(int j = 0; j < TILE_ARRAY_HEIGHT; j++) {
if(_tile[i][j].GetEntitySolitity()) { if(_tile[i][j].GetEntitySolitity()) {
@ -190,8 +190,8 @@ void LevelGen::FindSpawnPoint(int& xArg, int& yArg, int objWidth, int objHeight)
entityRect.x = _tile[i][j].GetEntityX(); entityRect.x = _tile[i][j].GetEntityX();
entityRect.y = _tile[i][j].GetEntityY(); entityRect.y = _tile[i][j].GetEntityY();
entityRect.w = _tile[i][j].GetEntityWidth(); entityRect.w = _tile[i][j].GetEntityWidth();
entityRect.h = _tile[i][j].GetEntityHeight(); entityRect.h = _tile[i][j].GetEntityHeight();
if(CheckCollisionRect(entityRect, objRect)) { if(CheckCollisionRect(entityRect, objRect)) {
FindSpawnPoint(xArg, yArg, objWidth, objHeight); FindSpawnPoint(xArg, yArg, objWidth, objHeight);
return; return;
@ -203,12 +203,12 @@ void LevelGen::FindSpawnPoint(int& xArg, int& yArg, int objWidth, int objHeight)
void LevelGen::GenerateEnemies(void) { void LevelGen::GenerateEnemies(void) {
int npcsToGen = (_player->GetLevel() * 2) + (rand() % 4); int npcsToGen = (_player->GetLevel() * 2) + (rand() % 4);
for(int i = 0; i < npcsToGen; i++) { for(int i = 0; i < npcsToGen; i++) {
int spawnX; int spawnX;
int spawnY; int spawnY;
FindSpawnPoint(spawnX, spawnY, 40,45); FindSpawnPoint(spawnX, spawnY, 40,45);
_world.CreateNPC(spawnX, spawnY); _world.CreateNPC(spawnX, spawnY);
} }
} }
@ -217,62 +217,62 @@ void LevelGen::MoveIfPossible(Character* character, float xVel, float yVel, bool
if(xVel == 0.0f && yVel == 0.0f) { if(xVel == 0.0f && yVel == 0.0f) {
return; return;
} }
float targetX = character->GetX() + xVel; float targetX = character->GetX() + xVel;
float targetY = character->GetY() + yVel; float targetY = character->GetY() + yVel;
if(targetX < 0 || targetX > (SCREEN_WIDTH - character->GetWidth()) || if(targetX < 0 || targetX > (SCREEN_WIDTH - character->GetWidth()) ||
targetY < 0 || targetY > (SCREEN_HEIGHT - character->GetHeight())) { targetY < 0 || targetY > (SCREEN_HEIGHT - character->GetHeight())) {
return; return;
} }
int targetTileX = targetX / TILE_WIDTH; int targetTileX = targetX / TILE_WIDTH;
int targetTileY = targetY / TILE_HEIGHT; int targetTileY = targetY / TILE_HEIGHT;
if(_tile[targetTileX][targetTileY].GetTileSolidity()) { if(_tile[targetTileX][targetTileY].GetTileSolidity()) {
return; return;
} }
SDL_Rect charRect; SDL_Rect charRect;
charRect.x = targetX; charRect.x = targetX;
charRect.y = targetY + (character->GetHeight() / 4) * 3; charRect.y = targetY + (character->GetHeight() / 4) * 3;
charRect.w = character->GetWidth(); charRect.w = character->GetWidth();
charRect.h = character->GetHeight() / 4; charRect.h = character->GetHeight() / 4;
for(int i = 0; i < TILE_ARRAY_WIDTH; i++) { for(int i = 0; i < TILE_ARRAY_WIDTH; i++) {
for(int j = 0; j < TILE_ARRAY_HEIGHT; j++) { for(int j = 0; j < TILE_ARRAY_HEIGHT; j++) {
if(!_tile[i][j].GetEntitySolitity()) { if(!_tile[i][j].GetEntitySolitity()) {
continue; continue;
} }
SDL_Rect entityRect; SDL_Rect entityRect;
entityRect.x = _tile[i][j].GetEntityX(); entityRect.x = _tile[i][j].GetEntityX();
entityRect.y = _tile[i][j].GetEntityY(); entityRect.y = _tile[i][j].GetEntityY();
entityRect.w = _tile[i][j].GetEntityWidth(); entityRect.w = _tile[i][j].GetEntityWidth();
entityRect.h = _tile[i][j].GetEntityHeight(); entityRect.h = _tile[i][j].GetEntityHeight();
if(CheckCollisionRect(entityRect, charRect)) { if(CheckCollisionRect(entityRect, charRect)) {
return; return;
} }
} }
} }
if(_world.CheckCollision(charRect, character)) { if(_world.CheckCollision(charRect, character)) {
return; return;
} }
if(!isPlayer) { if(!isPlayer) {
SDL_Rect playerRect; SDL_Rect playerRect;
playerRect.x = _player->GetX(); playerRect.x = _player->GetX();
playerRect.y = _player->GetY(); playerRect.y = _player->GetY();
playerRect.w = _player->GetWidth(); playerRect.w = _player->GetWidth();
playerRect.h = _player->GetHeight(); playerRect.h = _player->GetHeight();
if(CheckCollisionRect(playerRect, charRect)) { if(CheckCollisionRect(playerRect, charRect)) {
return; return;
} }
} }
character->SetXY(targetX, targetY); character->SetXY(targetX, targetY);
} }
@ -288,13 +288,13 @@ bool LevelGen::AStarTilePassable(int xArg, int yArg) {
if(!_tile[i][j].GetEntitySolitity()) { if(!_tile[i][j].GetEntitySolitity()) {
continue; continue;
} }
SDL_Rect entityRect; SDL_Rect entityRect;
entityRect.x = _tile[i][j].GetEntityX(); entityRect.x = _tile[i][j].GetEntityX();
entityRect.y = _tile[i][j].GetEntityY(); entityRect.y = _tile[i][j].GetEntityY();
entityRect.w = _tile[i][j].GetEntityWidth(); entityRect.w = _tile[i][j].GetEntityWidth();
entityRect.h = _tile[i][j].GetEntityHeight(); entityRect.h = _tile[i][j].GetEntityHeight();
if(CheckCollisionRect(tileRect, entityRect)) { if(CheckCollisionRect(tileRect, entityRect)) {
return false; return false;
} }
@ -338,7 +338,7 @@ void LevelGen::Deflate(Serialiser* serialiser) {
void LevelGen::Inflate(Serialiser* serialiser) { void LevelGen::Inflate(Serialiser* serialiser) {
serialiser->FirstElement("map"); serialiser->FirstElement("map");
x = 0; x = 0;
y = 0; y = 0;
@ -360,7 +360,7 @@ void LevelGen::Inflate(Serialiser* serialiser) {
_tile[x][y].SetTileXY(x * TILE_WIDTH, y * TILE_HEIGHT); _tile[x][y].SetTileXY(x * TILE_WIDTH, y * TILE_HEIGHT);
} }
string entityTextureName = _tile[x][y].GetEntityTextureName(); string entityTextureName = _tile[x][y].GetEntityTextureName();
if(entityTextureName != "null") { if(entityTextureName != "null") {
_tile[x][y].SetEntityTexture(_entityTextures.AddAlpha("../Data/Media/Images/Entities/" + entityTextureName + ".png")); _tile[x][y].SetEntityTexture(_entityTextures.AddAlpha("../Data/Media/Images/Entities/" + entityTextureName + ".png"));
_tile[x][y].SetEntityXY(_tile[x][y].GetTileX() + TILE_WIDTH / 2 - _tile[x][y].GetEntityWidth() / 2, _tile[x][y].SetEntityXY(_tile[x][y].GetTileX() + TILE_WIDTH / 2 - _tile[x][y].GetEntityWidth() / 2,
@ -371,45 +371,45 @@ void LevelGen::Inflate(Serialiser* serialiser) {
} }
string LevelGen::GetCurrentMap(void) { string LevelGen::GetCurrentMap(void) {
return _currentMap; return _currentMap;
} }
bool LevelGen::GetTileSolidity(int xArg, int yArg) { bool LevelGen::GetTileSolidity(int xArg, int yArg) {
return _tile[xArg + 1][yArg + 1].GetTileSolidity(); return _tile[xArg + 1][yArg + 1].GetTileSolidity();
} }
int LevelGen::GetTileX(int xArg, int yArg) { int LevelGen::GetTileX(int xArg, int yArg) {
return _tile[xArg + 1][yArg + 1].GetTileX(); return _tile[xArg + 1][yArg + 1].GetTileX();
} }
int LevelGen::GetTileY(int xArg, int yArg) { int LevelGen::GetTileY(int xArg, int yArg) {
return _tile[xArg + 1][yArg + 1].GetTileY(); return _tile[xArg + 1][yArg + 1].GetTileY();
} }
bool LevelGen::GetEntitySolidity(int xArg, int yArg) { bool LevelGen::GetEntitySolidity(int xArg, int yArg) {
if(xArg > x || yArg > y || yArg < 0 || yArg < 0) { if(xArg > x || yArg > y || yArg < 0 || yArg < 0) {
return false; return false;
} }
return _tile[xArg + 1][yArg + 1].GetEntitySolitity(); return _tile[xArg + 1][yArg + 1].GetEntitySolitity();
} }
int LevelGen::GetEntityX(int xArg, int yArg) { int LevelGen::GetEntityX(int xArg, int yArg) {
return _tile[xArg + 1][yArg + 1].GetEntityX(); return _tile[xArg + 1][yArg + 1].GetEntityX();
} }
int LevelGen::GetEntityY(int xArg, int yArg) { int LevelGen::GetEntityY(int xArg, int yArg) {
return _tile[xArg + 1][yArg + 1].GetEntityY(); return _tile[xArg + 1][yArg + 1].GetEntityY();
} }
int LevelGen::GetEntityWidth(int xArg, int yArg) { int LevelGen::GetEntityWidth(int xArg, int yArg) {
return _tile[xArg + 1][yArg + 1].GetEntityWidth(); return _tile[xArg + 1][yArg + 1].GetEntityWidth();
} }
int LevelGen::GetEntityHeight(int xArg, int yArg) { int LevelGen::GetEntityHeight(int xArg, int yArg) {
return _tile[xArg + 1][yArg + 1].GetEntityHeight(); return _tile[xArg + 1][yArg + 1].GetEntityHeight();
} }
AStarTile& LevelGen::GetAStarTile(int xArg, int yArg) { AStarTile& LevelGen::GetAStarTile(int xArg, int yArg) {
return _astarTile[xArg][yArg]; return _astarTile[xArg][yArg];
} }

View File

@ -24,39 +24,39 @@ class Player;
class LevelGen : public Serialisable { class LevelGen : public Serialisable {
public: public:
LevelGen(void); LevelGen(void);
~LevelGen(void); ~LevelGen(void);
void New(void); void New(void);
void Load(const string& filename); void Load(const string& filename);
void Save(const string& filename); void Save(const string& filename);
void Update(void); void Update(void);
void Render(void); void Render(void);
void FindSpawnPoint(int& xArg, int& yArg, int objWidth, int objHeight); void FindSpawnPoint(int& xArg, int& yArg, int objWidth, int objHeight);
void MoveIfPossible(Character* character, float xVel, float yVel, bool isPlayer = false); void MoveIfPossible(Character* character, float xVel, float yVel, bool isPlayer = false);
bool GetTileSolidity(int xArg, int yArg);
int GetTileX(int xArg, int yArg);
int GetTileY(int xArg, int yArg);
bool GetEntitySolidity(int xArg, int yArg); bool GetTileSolidity(int xArg, int yArg);
int GetEntityX(int xArg, int yArg); int GetTileX(int xArg, int yArg);
int GetEntityY(int xArg, int yArg); int GetTileY(int xArg, int yArg);
int GetEntityWidth(int xArg, int yArg);
int GetEntityHeight(int xArg, int yArg);
int GetTileZLevel(int xArg, int yArg); bool GetEntitySolidity(int xArg, int yArg);
int GetEntityX(int xArg, int yArg);
int GetEntityY(int xArg, int yArg);
int GetEntityWidth(int xArg, int yArg);
int GetEntityHeight(int xArg, int yArg);
int GetTileZLevel(int xArg, int yArg);
AStarTile& GetAStarTile(int xArg, int yArg); AStarTile& GetAStarTile(int xArg, int yArg);
string GetCurrentMap(void); string GetCurrentMap(void);
WorldManager& GetWorld(void) { return _world; } WorldManager& GetWorld(void) { return _world; }
void SetPlayer(Player* player) { _player = player; } void SetPlayer(Player* player) { _player = player; }
Player* GetPlayer() { return _player; } Player* GetPlayer() { return _player; }
static const int TILE_ARRAY_WIDTH = (SCREEN_WIDTH / TILE_WIDTH) + 1; static const int TILE_ARRAY_WIDTH = (SCREEN_WIDTH / TILE_WIDTH) + 1;
static const int TILE_ARRAY_HEIGHT = (SCREEN_HEIGHT / TILE_HEIGHT) + 1; static const int TILE_ARRAY_HEIGHT = (SCREEN_HEIGHT / TILE_HEIGHT) + 1;
static const int ASTAR_ARRAY_WIDTH = TILE_ARRAY_WIDTH * (TILE_WIDTH / AStarTile::FAKE_SIZE); static const int ASTAR_ARRAY_WIDTH = TILE_ARRAY_WIDTH * (TILE_WIDTH / AStarTile::FAKE_SIZE);
@ -85,6 +85,6 @@ private:
TextureManager _entityTextures; TextureManager _entityTextures;
WorldManager _world; WorldManager _world;
Player* _player; Player* _player;
}; };

View File

@ -30,7 +30,7 @@ bool MapElement::GetSolidity(void) {
void MapElement::SetXY(int xArg, int yArg) { void MapElement::SetXY(int xArg, int yArg) {
x = xArg, x = xArg,
y = yArg; y = yArg;
} }
int MapElement::GetX(void) { return x; } int MapElement::GetX(void) { return x; }
@ -39,4 +39,4 @@ int MapElement::GetWidth(void) { return _texture->w; }
int MapElement::GetHeight(void) { return _texture->h; } int MapElement::GetHeight(void) { return _texture->h; }
void MapElement::SetTextureName(string name) { _textureName = name; } void MapElement::SetTextureName(string name) { _textureName = name; }
string MapElement::GetTextureName(void) { return _textureName; } string MapElement::GetTextureName(void) { return _textureName; }

View File

@ -25,7 +25,7 @@ public:
int GetY(void); int GetY(void);
int GetWidth(void); int GetWidth(void);
int GetHeight(void); int GetHeight(void);
void SetTextureName(string path); void SetTextureName(string path);
string GetTextureName(void); string GetTextureName(void);

View File

@ -39,4 +39,4 @@ void MapTile::Inflate(Serialiser* serialiser) {
_entity.SetTextureName(entityTexture); _entity.SetTextureName(entityTexture);
_entity.SetSolidity(solidEntity); _entity.SetSolidity(solidEntity);
} }

View File

@ -16,7 +16,7 @@ public:
MapTile(void) { } MapTile(void) { }
~MapTile(void) { } ~MapTile(void) { }
void Render(void) { _tile.Render(), _entity.Render(); } void Render(void) { _tile.Render(), _entity.Render(); }
void Deflate(Serialiser* serialiser); void Deflate(Serialiser* serialiser);
void Inflate(Serialiser* serialiser); void Inflate(Serialiser* serialiser);
@ -34,19 +34,19 @@ public:
int GetTileX(void) { return _tile.GetX(); } int GetTileX(void) { return _tile.GetX(); }
int GetTileY(void) { return _tile.GetY(); } int GetTileY(void) { return _tile.GetY(); }
// Entity Mutators. // Entity Mutators.
void SetEntityTexture(SDL_Surface* arg) { _entity.SetTexture(arg); } void SetEntityTexture(SDL_Surface* arg) { _entity.SetTexture(arg); }
void SetEntityTextureName(string path) { _entity.SetTextureName(path); } void SetEntityTextureName(string path) { _entity.SetTextureName(path); }
void SetEntityXY(int xArg, int yArg) { _entity.SetXY(xArg, yArg); } void SetEntityXY(int xArg, int yArg) { _entity.SetXY(xArg, yArg); }
void SetEntitySolidity(bool arg) { _entity.SetSolidity(arg); } void SetEntitySolidity(bool arg) { _entity.SetSolidity(arg); }
bool GetEntitySolitity(void) { return _entity.GetSolidity(); } bool GetEntitySolitity(void) { return _entity.GetSolidity(); }
// Entity Mutators. // Entity Mutators.
int GetEntityX(void) { return _entity.GetX(); } int GetEntityX(void) { return _entity.GetX(); }
int GetEntityY(void) { return _entity.GetY(); } int GetEntityY(void) { return _entity.GetY(); }
int GetEntityWidth(void) { return _entity.GetWidth(); } int GetEntityWidth(void) { return _entity.GetWidth(); }
int GetEntityHeight(void) { return _entity.GetHeight(); } int GetEntityHeight(void) { return _entity.GetHeight(); }
string GetEntityTextureName(void) { return _entity.GetTextureName(); } string GetEntityTextureName(void) { return _entity.GetTextureName(); }
private: private:
MapElement _tile; MapElement _tile;

View File

@ -34,13 +34,13 @@ Debug::Debug(bool logToFile) {
Debug::~Debug(void) { Debug::~Debug(void) {
time_t timestamp; time_t timestamp;
// We only need to close the log if it is open. // We only need to close the log if it is open.
if(_logFile) { if(_logFile) {
// Give it a closing timestamp. // Give it a closing timestamp.
timestamp = time(NULL); timestamp = time(NULL);
_logFile << endl << "Log Closed: " << ctime(&timestamp) << endl; _logFile << endl << "Log Closed: " << ctime(&timestamp) << endl;
// Close the log file. // Close the log file.
_logFile.close(); _logFile.close();
} }
@ -73,11 +73,11 @@ void Debug::message(const char *msg, ...) {
if(outLen >= sizeof(outBuf)) { if(outLen >= sizeof(outBuf)) {
outLen = sizeof(outBuf); outLen = sizeof(outBuf);
} }
if(_logFile) { if(_logFile) {
_logFile << outBuf << endl; _logFile << outBuf << endl;
} }
cerr << outBuf << endl; cerr << outBuf << endl;
} }

View File

@ -12,9 +12,9 @@ public:
void message(const char *msg, ...); void message(const char *msg, ...);
static bool openLog(bool logToFile); static bool openLog(bool logToFile);
static void closeLog(void); static void closeLog(void);
static Debug *logger; static Debug *logger;
private: private:
std::ofstream _logFile; std::ofstream _logFile;
}; };

View File

@ -31,6 +31,9 @@ bool CreateInput(void) {
memcpy(keyboard.keys, tempKeys, sizeof(char) * keyboard.keycount); memcpy(keyboard.keys, tempKeys, sizeof(char) * keyboard.keycount);
mouse.buttons = SDL_GetMouseState(&mouse.dx, &mouse.dy); mouse.buttons = SDL_GetMouseState(&mouse.dx, &mouse.dy);
if(&keyboard > 0 || &mouse > 0){
Debug::logger->message("Input device registered");
}
return true; return true;
} }
@ -79,4 +82,5 @@ bool MouseStillUp(int button) { return(!_curr_mouse(button) && !_old_mouse(b
void DestroyInput(void) { void DestroyInput(void) {
free(keyboard.keys); free(keyboard.keys);
free(keyboard.oldKeys); free(keyboard.oldKeys);
Debug::logger->message("Input device destroyed");
} }

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <SDL/SDL.h> #include <SDL/SDL.h>
#include "../System/Debug.h"
typedef struct mouse_s { typedef struct mouse_s {
int dx, dy; int dx, dy;
int oldx, oldy; int oldx, oldy;
@ -21,23 +23,23 @@ typedef struct input_s {
keyboard_t keyboard; keyboard_t keyboard;
} input_t; } input_t;
bool CreateInput(void); bool CreateInput(void);
void UpdateInput(void); void UpdateInput(void);
char GetKey(void); char GetKey(void);
unsigned int GetX(void); unsigned int GetX(void);
unsigned int GetY(void); unsigned int GetY(void);
unsigned int GetOldX(void); unsigned int GetOldX(void);
unsigned int GetOldY(void); unsigned int GetOldY(void);
unsigned int GetMods(void); unsigned int GetMods(void);
bool KeyDown(int index); bool KeyDown(int index);
bool KeyStillDown(int index); bool KeyStillDown(int index);
bool KeyUp(int index); bool KeyUp(int index);
bool KeyStillUp(int index); bool KeyStillUp(int index);
bool MouseDown(int button); bool MouseDown(int button);
bool MouseStillDown(int button); bool MouseStillDown(int button);
bool MouseUp(int button); bool MouseUp(int button);
bool MouseStillUp(int button); bool MouseStillUp(int button);
void DestroyInput(void); void DestroyInput(void);

View File

@ -3,36 +3,36 @@
class MathBox { class MathBox {
public: public:
// A templated max function that returns none other than the max of two values. // A templated max function that returns none other than the max of two values.
template<typename T> template<typename T>
static T Max(T value1, T value2) { static T Max(T value1, T value2) {
return value1 > value2 ? value1 : value2; return value1 > value2 ? value1 : value2;
} }
// A templated min function that returns none other than the min of two values. // A templated min function that returns none other than the min of two values.
template<typename T> template<typename T>
static T Min(T value1, T value2) { static T Min(T value1, T value2) {
return value1 < value2 ? value1 : value2; return value1 < value2 ? value1 : value2;
} }
// Linear interpolation between two values. // Linear interpolation between two values.
template<typename T> template<typename T>
static T Lerp(T value1, T value2, float amount) { static T Lerp(T value1, T value2, float amount) {
return T(value1 + ((T)(value2 - value1) * amount)); return T(value1 + ((T)(value2 - value1) * amount));
} }
// Clamp an integer to a specified range. // Clamp an integer to a specified range.
static int Clamp(int value, int min, int max) { static int Clamp(int value, int min, int max) {
return Max(min, Min(max, value)); return Max(min, Min(max, value));
} }
// Clamp a float to a specified range. // Clamp a float to a specified range.
static float Clamp(float value, float min, float max) { static float Clamp(float value, float min, float max) {
return Max(min, Min(max, value)); return Max(min, Min(max, value));
} }
// Clamp a double-precision to a specified range. // Clamp a double-precision to a specified range.
static double Clamp(double value, double min, double max) { static double Clamp(double value, double min, double max) {
return Max(min, Min(max, value)); return Max(min, Min(max, value));
} }
}; };

View File

@ -24,7 +24,7 @@ void Serialiser::StepOut(void) {
} }
TiXmlElement* parentElement = _parentElements.back(); TiXmlElement* parentElement = _parentElements.back();
// This happens when stepping out of root. // This happens when stepping out of root.
if(parentElement == _currentElement) { if(parentElement == _currentElement) {
return; return;
@ -55,7 +55,7 @@ bool Serialiser::FirstElement(const string& name) {
return false; return false;
} }
if(oldElement) { if(oldElement) {
// Save the old element as parent. // Save the old element as parent.
_parentElements.push_back(oldElement); _parentElements.push_back(oldElement);
@ -78,7 +78,7 @@ bool Serialiser::NextElement(const string& name) {
if(!_currentElement) { if(!_currentElement) {
// Restore the old element if new one was not found. // Restore the old element if new one was not found.
_currentElement = oldElement; _currentElement = oldElement;
return false; return false;
} }
@ -110,7 +110,7 @@ void Serialiser::WriteMembers(void) {
//Debug::logger->message("WriteMembers()"); //Debug::logger->message("WriteMembers()");
std::stringstream sstream; std::stringstream sstream;
for(list<SerialiserMember>::iterator i = _members.begin(); i != _members.end(); ++i) { for(list<SerialiserMember>::iterator i = _members.begin(); i != _members.end(); ++i) {
TiXmlText* text = NULL; TiXmlText* text = NULL;
@ -146,7 +146,7 @@ void Serialiser::WriteMembers(void) {
void Serialiser::ReadMembers(void) { void Serialiser::ReadMembers(void) {
for(list<SerialiserMember>::iterator i = _members.begin(); i != _members.end(); ++i) { for(list<SerialiserMember>::iterator i = _members.begin(); i != _members.end(); ++i) {
TiXmlElement* element = _currentElement->FirstChildElement(i->_name.c_str()); TiXmlElement* element = _currentElement->FirstChildElement(i->_name.c_str());
if(!element) { if(!element) {
continue; continue;
} }

View File

@ -22,134 +22,134 @@ Vec2::Vec2(const Vec2i &copy) : x(copy.x), y(copy.y) {
} }
float Vec2::Length(void) { float Vec2::Length(void) {
return sqrt(LengthSquared()); return sqrt(LengthSquared());
} }
float Vec2::LengthSquared(void) { float Vec2::LengthSquared(void) {
return (x * x) + (y * y); return (x * x) + (y * y);
} }
// Static. // Static.
float Vec2::Distance(const Vec2& value1, const Vec2& value2) { float Vec2::Distance(const Vec2& value1, const Vec2& value2) {
return (value1 - value2).Length(); return (value1 - value2).Length();
} }
// Static. // Static.
float Vec2::DistanceSquared(const Vec2& value1, const Vec2& value2) { float Vec2::DistanceSquared(const Vec2& value1, const Vec2& value2) {
return (value1 - value2).LengthSquared(); return (value1 - value2).LengthSquared();
} }
// Static. // Static.
float Vec2::Dot(const Vec2& value1, const Vec2& value2) { float Vec2::Dot(const Vec2& value1, const Vec2& value2) {
return (value1.x * value2.x) - (value1.y * value2.y); return (value1.x * value2.x) - (value1.y * value2.y);
} }
// Static. // Static.
float Vec2::Cross(const Vec2& value1, Vec2& value2) { float Vec2::Cross(const Vec2& value1, Vec2& value2) {
return (value1.x * value2.y) - (value1.y * value2.x); return (value1.x * value2.y) - (value1.y * value2.x);
} }
void Vec2::Normalize(void) { void Vec2::Normalize(void) {
float len = Length(); float len = Length();
if(len < 1e-7f) { if(len < 1e-7f) {
if(y > x) if(y > x)
*this = UnitY; *this = UnitY;
else else
*this = UnitX; *this = UnitX;
} else { } else {
*this = *this / len; *this = *this / len;
} }
} }
// Static. // Static.
Vec2 Vec2::Normalize(const Vec2& value) { Vec2 Vec2::Normalize(const Vec2& value) {
Vec2 retVal(value); Vec2 retVal(value);
retVal.Normalize(); retVal.Normalize();
return retVal; return retVal;
} }
// Static. // Static.
Vec2 Vec2::Reflect(const Vec2& vector, const Vec2& normal) { Vec2 Vec2::Reflect(const Vec2& vector, const Vec2& normal) {
return vector - (normal * 2.0f * Dot(vector, normal)); return vector - (normal * 2.0f * Dot(vector, normal));
} }
// Static. // Static.
Vec2 Vec2::Min(const Vec2& value1, const Vec2& value2) { Vec2 Vec2::Min(const Vec2& value1, const Vec2& value2) {
return Vec2(MathBox::Min(value1.x, value2.x), MathBox::Min(value1.y, value2.y)); return Vec2(MathBox::Min(value1.x, value2.x), MathBox::Min(value1.y, value2.y));
} }
// Static. // Static.
Vec2 Vec2::Max(const Vec2& value1, const Vec2& value2) { Vec2 Vec2::Max(const Vec2& value1, const Vec2& value2) {
return Vec2(MathBox::Max(value1.x, value2.x), MathBox::Max(value1.y, value2.y)); return Vec2(MathBox::Max(value1.x, value2.x), MathBox::Max(value1.y, value2.y));
} }
// Static. // Static.
Vec2 Vec2::Clamp(const Vec2& value, const Vec2& min, const Vec2& max) { Vec2 Vec2::Clamp(const Vec2& value, const Vec2& min, const Vec2& max) {
return Vec2(MathBox::Clamp(value.x, min.x, max.x), MathBox::Clamp(value.y, min.y, max.y)); return Vec2(MathBox::Clamp(value.x, min.x, max.x), MathBox::Clamp(value.y, min.y, max.y));
} }
// Static. // Static.
Vec2 Vec2::Lerp(const Vec2& value1, const Vec2& value2, float amount) { Vec2 Vec2::Lerp(const Vec2& value1, const Vec2& value2, float amount) {
return Vec2(MathBox::Lerp(value1.x, value2.x, amount), MathBox::Lerp(value1.y, value2.y, amount)); return Vec2(MathBox::Lerp(value1.x, value2.x, amount), MathBox::Lerp(value1.y, value2.y, amount));
} }
// Static. // Static.
Vec2 Vec2::Negate(const Vec2& value) { Vec2 Vec2::Negate(const Vec2& value) {
return -value; return -value;
} }
// Static. // Static.
Vec2 Vec2::Rotate(const Vec2& value, const float radians) { Vec2 Vec2::Rotate(const Vec2& value, const float radians) {
float c = cos(radians); float c = cos(radians);
float s = sin(radians); float s = sin(radians);
return Vec2(value.x * c - value.y * s, value.y * c + value.x * s); return Vec2(value.x * c - value.y * s, value.y * c + value.x * s);
} }
// Overload some operators.. // Overload some operators..
bool Vec2::operator==(const Vec2& v) const { bool Vec2::operator==(const Vec2& v) const {
return x == v.x && y == v.y; return x == v.x && y == v.y;
} }
bool Vec2::operator!=(const Vec2& v) const { bool Vec2::operator!=(const Vec2& v) const {
return !(*this == v); return !(*this == v);
} }
Vec2 Vec2::operator-(void) const { Vec2 Vec2::operator-(void) const {
return Vec2::Zero - *this; return Vec2::Zero - *this;
} }
Vec2 Vec2::operator-(const Vec2& v) const { Vec2 Vec2::operator-(const Vec2& v) const {
return Vec2(x - v.x, y - v.y); return Vec2(x - v.x, y - v.y);
} }
Vec2 Vec2::operator+(const Vec2& v) const { Vec2 Vec2::operator+(const Vec2& v) const {
return Vec2(x + v.x, y + v.y); return Vec2(x + v.x, y + v.y);
} }
Vec2 Vec2::operator/(float divider) const { Vec2 Vec2::operator/(float divider) const {
return Vec2(x / divider, y / divider); return Vec2(x / divider, y / divider);
} }
Vec2 Vec2::operator*(float scaleFactor) const { Vec2 Vec2::operator*(float scaleFactor) const {
return Vec2(x * scaleFactor, y * scaleFactor); return Vec2(x * scaleFactor, y * scaleFactor);
} }
Vec2& Vec2::operator+=(const Vec2& v) { Vec2& Vec2::operator+=(const Vec2& v) {
x += v.x, y += v.y; x += v.x, y += v.y;
return *this; return *this;
} }
Vec2& Vec2::operator-=(const Vec2& v) { Vec2& Vec2::operator-=(const Vec2& v) {
x -= v.x, y -= v.y; x -= v.x, y -= v.y;
return *this; return *this;
} }
Vec2& Vec2::operator*=(float scaleFactor) { Vec2& Vec2::operator*=(float scaleFactor) {
x *= scaleFactor, y *= scaleFactor; x *= scaleFactor, y *= scaleFactor;
return *this; return *this;
} }
Vec2& Vec2::operator/=(float scaleFactor) { Vec2& Vec2::operator/=(float scaleFactor) {
x /= scaleFactor, y /= scaleFactor; x /= scaleFactor, y /= scaleFactor;
return *this; return *this;
} }

View File

@ -6,98 +6,98 @@
// A handy structure for passing around 2D integer coords. // A handy structure for passing around 2D integer coords.
struct Vec2i { struct Vec2i {
int x, y; int x, y;
Vec2i(int xArg, int yArg) : x(xArg), y(yArg) {} Vec2i(int xArg, int yArg) : x(xArg), y(yArg) {}
Vec2i(void) : x(0), y(0) {} Vec2i(void) : x(0), y(0) {}
}; };
struct Vec2 { struct Vec2 {
// Initialize a zero-length vector (0, 0). // Initialize a zero-length vector (0, 0).
Vec2(void); Vec2(void);
// Initialize a vector to a set dimension. // Initialize a vector to a set dimension.
Vec2(float xArg, float yArg); Vec2(float xArg, float yArg);
// Initialize a vector to a uniform dimension // Initialize a vector to a uniform dimension
Vec2(float value); Vec2(float value);
// Copy from the Vec2i to be converted into a Vec2 // Copy from the Vec2i to be converted into a Vec2
Vec2(const Vec2i& copy); Vec2(const Vec2i& copy);
// A reference to a zero-length vector (0, 0) // A reference to a zero-length vector (0, 0)
static Vec2 Zero; static Vec2 Zero;
// A reference to a (1, 1) vector. // A reference to a (1, 1) vector.
static Vec2 One; static Vec2 One;
// A reference to a (1, 0) vecor. // A reference to a (1, 0) vecor.
static Vec2 UnitX; static Vec2 UnitX;
// A reference to a (0, 1) vector. // A reference to a (0, 1) vector.
static Vec2 UnitY; static Vec2 UnitY;
// Get the absolute magnitude of the vector. -- Uses a square root. // Get the absolute magnitude of the vector. -- Uses a square root.
float Length(void); float Length(void);
// Get the squared magnitude of the vector -- Just in case we only care about comparison. // Get the squared magnitude of the vector -- Just in case we only care about comparison.
float LengthSquared(void); float LengthSquared(void);
// Get absolute distance between two points. -- Uses a square root. // Get absolute distance between two points. -- Uses a square root.
static float Distance(const Vec2& value1, const Vec2& value2); static float Distance(const Vec2& value1, const Vec2& value2);
// In case we only care about comparison.. // In case we only care about comparison..
static float DistanceSquared(const Vec2& value1, const Vec2& value2); static float DistanceSquared(const Vec2& value1, const Vec2& value2);
// Get the dot product of two vectors. // Get the dot product of two vectors.
static float Dot(const Vec2& value1, const Vec2& value2); static float Dot(const Vec2& value1, const Vec2& value2);
/* Get the cross product of two vectors. Note that the \b mathmatical /* Get the cross product of two vectors. Note that the \b mathmatical
* definition of a cross product results in another vector oeroendicular * definition of a cross product results in another vector oeroendicular
* to the two inputs, but since both of our vectors are 2D, the returned * to the two inputs, but since both of our vectors are 2D, the returned
* vector will always have x and y components of 0. This this function * vector will always have x and y components of 0. This this function
* returns what would be the z component vector. * returns what would be the z component vector.
*/ */
static float Cross(const Vec2& value1, Vec2& value2); static float Cross(const Vec2& value1, Vec2& value2);
// Normalize a vector in place. // Normalize a vector in place.
void Normalize(void); void Normalize(void);
// Get the normalized value for a Vec2 without affecting the original. // Get the normalized value for a Vec2 without affecting the original.
static Vec2 Normalize(const Vec2& value); static Vec2 Normalize(const Vec2& value);
// Reflect the vector around another. // Reflect the vector around another.
static Vec2 Reflect(const Vec2& vector, const Vec2& normal); static Vec2 Reflect(const Vec2& vector, const Vec2& normal);
// Get a new vector from the minimum x and y. // Get a new vector from the minimum x and y.
static Vec2 Min(const Vec2& value1, const Vec2& value2); static Vec2 Min(const Vec2& value1, const Vec2& value2);
// Get a new vector from the maximum x and y. // Get a new vector from the maximum x and y.
static Vec2 Max(const Vec2& value1, const Vec2& value2); static Vec2 Max(const Vec2& value1, const Vec2& value2);
// Clamp a vector to a given min and max. // Clamp a vector to a given min and max.
static Vec2 Clamp(const Vec2& value, const Vec2& min, const Vec2& max); static Vec2 Clamp(const Vec2& value, const Vec2& min, const Vec2& max);
// Perform a linear interplolation between two vectors. // Perform a linear interplolation between two vectors.
static Vec2 Lerp(const Vec2& value1, const Vec2& value2, float amount); static Vec2 Lerp(const Vec2& value1, const Vec2& value2, float amount);
// Get a negated vector. // Get a negated vector.
static Vec2 Negate(const Vec2& value); static Vec2 Negate(const Vec2& value);
static Vec2 Rotate(const Vec2& value, const float radians); static Vec2 Rotate(const Vec2& value, const float radians);
bool operator==(const Vec2& v) const; bool operator==(const Vec2& v) const;
bool operator!=(const Vec2& v) const; bool operator!=(const Vec2& v) const;
Vec2 operator-(void) const; Vec2 operator-(void) const;
Vec2 operator-(const Vec2& v) const; Vec2 operator-(const Vec2& v) const;
Vec2 operator+(const Vec2& v) const; Vec2 operator+(const Vec2& v) const;
Vec2 operator/(float divider) const; Vec2 operator/(float divider) const;
Vec2 operator*(float scaleFactor) const; Vec2 operator*(float scaleFactor) const;
Vec2& operator+=(const Vec2& v); Vec2& operator+=(const Vec2& v);
Vec2& operator-=(const Vec2& v); Vec2& operator-=(const Vec2& v);
Vec2& operator*=(float f); Vec2& operator*=(float f);
Vec2& operator/=(float f); Vec2& operator/=(float f);
float x; float x;
float y; float y;
}; };
typedef std::vector<Vec2> Vector2List; typedef std::vector<Vec2> Vector2List;

View File

@ -21,10 +21,10 @@ void Bar::SetWidthHeight(int wArg, int hArg) {
if(width == wArg && height == hArg) { if(width == wArg && height == hArg) {
return; return;
} }
width = wArg; width = wArg;
height = hArg; height = hArg;
_bgRect.SetWidthHeight(width, height); _bgRect.SetWidthHeight(width, height);
SetProgress(_progress); SetProgress(_progress);
@ -48,7 +48,7 @@ void Bar::SetForegroundRGB(SDL_Color colour) {
void Bar::SetProgress(float progress) { void Bar::SetProgress(float progress) {
_progress = progress; _progress = progress;
_fgRect.SetWidthHeight((int)(progress * width), height); _fgRect.SetWidthHeight((int)(progress * width), height);
} }

View File

@ -32,7 +32,7 @@ public:
private: private:
Rect _bgRect; // background Rect _bgRect; // background
Rect _fgRect; // foreground Rect _fgRect; // foreground
float _progress; float _progress;
int x; int x;

View File

@ -84,7 +84,7 @@ bool Button::CheckMouseOver(void) {
return false; return false;
} }
void Button::SetHighlighted(bool highlighted) { void Button::SetHighlighted(bool highlighted) {
if(_highlighted != highlighted) { if(_highlighted != highlighted) {
if(highlighted) { if(highlighted) {
_button.SetRGB(_highlightColour); _button.SetRGB(_highlightColour);

View File

@ -15,9 +15,9 @@ EventHistory::EventHistory(void) {
_titleText.SetXY(_bgx + BOX_WIDTH/2, _bgy + 5); _titleText.SetXY(_bgx + BOX_WIDTH/2, _bgy + 5);
_titleText.SetTextBlended("Unuk Log", small, 0, 255, 255); _titleText.SetTextBlended("Unuk Log", small, 0, 255, 255);
_titleText.SetXY(_titleText.GetX() - _titleText.GetWidth()/2, _titleText.GetY()); _titleText.SetXY(_titleText.GetX() - _titleText.GetWidth()/2, _titleText.GetY());
_text.SetXY(_bgx + 5, _bgy + 30); _text.SetXY(_bgx + 5, _bgy + 30);
_visible = false; _visible = false;
} }
@ -42,9 +42,9 @@ void EventHistory::LogEvent(const std::string& evtText) {
void EventHistory::Render(void) { void EventHistory::Render(void) {
if(_visible && (_timeToVanish.GetTicks() >= 5000)) { if(_visible && (_timeToVanish.GetTicks() >= 5000)) {
_timeToVanish.Stop(); _timeToVanish.Stop();
_events.erase(_events.begin()); _events.erase(_events.begin());
if(_events.empty()) { if(_events.empty()) {
_visible = false; _visible = false;
} else { } else {
@ -56,18 +56,18 @@ void EventHistory::Render(void) {
if(!_visible) { if(!_visible) {
return; return;
} }
roundedBoxRGBA(screen, roundedBoxRGBA(screen,
_bgx, _bgy, _bgx, _bgy,
_bgx + BOX_WIDTH, _bgy + BOX_HEIGHT, _bgx + BOX_WIDTH, _bgy + BOX_HEIGHT,
8, 8,
0, 0, 0, 128); 0, 0, 0, 128);
roundedRectangleRGBA(screen, roundedRectangleRGBA(screen,
_bgx, _bgy, _bgx, _bgy,
_bgx + BOX_WIDTH, _bgy + BOX_HEIGHT, _bgx + BOX_WIDTH, _bgy + BOX_HEIGHT,
8, 8,
0, 255, 255, 255); 0, 255, 255, 255);
_titleText.RenderLiteral(); _titleText.RenderLiteral();
_text.RenderLiteral(); _text.RenderLiteral();
@ -80,6 +80,6 @@ void EventHistory::BakeText(void) {
textStr.append("\n"); textStr.append("\n");
} }
_text.SetTextBlended(textStr, small, 255, 255, 255); _text.SetTextBlended(textStr, small, 255, 255, 255);
} }

View File

@ -17,7 +17,7 @@ public:
private: private:
void BakeText(void); void BakeText(void);
std::list<std::string> _events; std::list<std::string> _events;
Text _titleText; Text _titleText;
Text _text; Text _text;

View File

@ -71,22 +71,22 @@ ingameMenuNavVal_t IngameMenu::HandleInput(void) {
_buttons.SelectPrevious(); _buttons.SelectPrevious();
} else if(event.key.keysym.sym == SDLK_RETURN) { } else if(event.key.keysym.sym == SDLK_RETURN) {
switch(_buttons.GetSelectedButton()) { switch(_buttons.GetSelectedButton()) {
case 0: return ingameMenuResume; case 0: return ingameMenuResume;
case 1: return ingameMenuSaveGame; case 1: return ingameMenuSaveGame;
case 2: return ingameMenuLoadGame; case 2: return ingameMenuLoadGame;
case 3: return ingameMenuOptions; case 3: return ingameMenuOptions;
case 4: return ingameMenuMainMenu; case 4: return ingameMenuMainMenu;
} }
} }
} }
else if(event.type == SDL_MOUSEBUTTONUP) { else if(event.type == SDL_MOUSEBUTTONUP) {
if(event.button.button == SDL_BUTTON_LEFT) { if(event.button.button == SDL_BUTTON_LEFT) {
switch(_buttons.CheckMouseOver()) { switch(_buttons.CheckMouseOver()) {
case 0: return ingameMenuResume; case 0: return ingameMenuResume;
case 1: return ingameMenuSaveGame; case 1: return ingameMenuSaveGame;
case 2: return ingameMenuLoadGame; case 2: return ingameMenuLoadGame;
case 3: return ingameMenuOptions; case 3: return ingameMenuOptions;
case 4: return ingameMenuMainMenu; case 4: return ingameMenuMainMenu;
} }
} }
} }
@ -96,4 +96,4 @@ ingameMenuNavVal_t IngameMenu::HandleInput(void) {
void IngameMenu::Render(void) { void IngameMenu::Render(void) {
_buttons.RenderLiteral(); _buttons.RenderLiteral();
} }

View File

@ -35,7 +35,7 @@ MainMenu::MainMenu(void) {
btnExit->SetText("Exit"); btnExit->SetText("Exit");
btnExit->SetHighlightRGB(255, 128, 0); btnExit->SetHighlightRGB(255, 128, 0);
btnExit->SetHighlighted(false); btnExit->SetHighlighted(false);
btnExit->SetXY(100, 300); btnExit->SetXY(100, 300);
grpMain.AddButton(btnNewGame); grpMain.AddButton(btnNewGame);
grpMain.AddButton(btnLoadGame); grpMain.AddButton(btnLoadGame);
@ -116,15 +116,15 @@ mainMenuNavVal_t MainMenu::Run(void) {
} else if(event.key.keysym.sym == SDLK_RETURN) { } else if(event.key.keysym.sym == SDLK_RETURN) {
if(btnNewGameActive) { if(btnNewGameActive) {
switch(grpNewGame.GetSelectedButton()) { switch(grpNewGame.GetSelectedButton()) {
case 0: return mainMenuNewGame; break; case 0: return mainMenuNewGame; break;
case 1: btnNewGameActive = false; break; case 1: btnNewGameActive = false; break;
} }
} else { } else {
switch(grpMain.GetSelectedButton()) { switch(grpMain.GetSelectedButton()) {
case 0: btnNewGameActive = !btnNewGameActive; break; case 0: btnNewGameActive = !btnNewGameActive; break;
case 1: return mainMenuLoadGame; case 1: return mainMenuLoadGame;
case 2: return mainMenuOptions; case 2: return mainMenuOptions;
case 3: return mainMenuExitGame; case 3: return mainMenuExitGame;
} }
} }
} else if(event.key.keysym.sym == SDLK_ESCAPE) { } else if(event.key.keysym.sym == SDLK_ESCAPE) {
@ -134,16 +134,16 @@ mainMenuNavVal_t MainMenu::Run(void) {
else if(event.type == SDL_MOUSEBUTTONUP) { else if(event.type == SDL_MOUSEBUTTONUP) {
if(event.button.button == SDL_BUTTON_LEFT) { if(event.button.button == SDL_BUTTON_LEFT) {
switch(grpMain.CheckMouseOver()) { switch(grpMain.CheckMouseOver()) {
case 0: btnNewGameActive = !btnNewGameActive; break; case 0: btnNewGameActive = !btnNewGameActive; break;
case 1: return mainMenuLoadGame; case 1: return mainMenuLoadGame;
case 2: return mainMenuOptions; case 2: return mainMenuOptions;
case 3: return mainMenuExitGame; case 3: return mainMenuExitGame;
} }
if(btnNewGameActive) { if(btnNewGameActive) {
switch(grpNewGame.CheckMouseOver()) { switch(grpNewGame.CheckMouseOver()) {
case 0: return mainMenuNewGame; break; case 0: return mainMenuNewGame; break;
case 1: btnNewGameActive = false; break; case 1: btnNewGameActive = false; break;
} }
} }
} }

View File

@ -24,7 +24,7 @@ public:
private: private:
void Render(void); void Render(void);
LevelGen _background; LevelGen _background;
Text lblMenu; Text lblMenu;

View File

@ -8,7 +8,7 @@
SavegameMenu::SavegameMenu(void) { SavegameMenu::SavegameMenu(void) {
_title.SetXY(BOX_SPACING_X, 25); _title.SetXY(BOX_SPACING_X, 25);
_title.SetTextBlended("Choose Savegame: ", vlarge, 0, 255, 255); _title.SetTextBlended("Choose Savegame: ", vlarge, 0, 255, 255);
for(int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++) {
std::stringstream capText; std::stringstream capText;
if(i != 3) { if(i != 3) {
@ -16,16 +16,16 @@ SavegameMenu::SavegameMenu(void) {
} else { } else {
capText << "Cancel"; capText << "Cancel";
} }
_captions[i].SetXY(BOX_SPACING_X + BOX_WIDTH/2, _captions[i].SetXY(BOX_SPACING_X + BOX_WIDTH/2,
BOXES_OFFSET_Y + (i * BOX_SPACING_Y) + (i * BOX_HEIGHT) + BOX_HEIGHT/2); BOXES_OFFSET_Y + (i * BOX_SPACING_Y) + (i * BOX_HEIGHT) + BOX_HEIGHT/2);
_captions[i].SetTextBlended(capText.str(), large, 0, 255, 255); _captions[i].SetTextBlended(capText.str(), large, 0, 255, 255);
_captions[i].SetXY(_captions[i].GetX() - _captions[i].GetWidth()/2, _captions[i].SetXY(_captions[i].GetX() - _captions[i].GetWidth()/2,
_captions[i].GetY() - _captions[i].GetHeight()/2); _captions[i].GetY() - _captions[i].GetHeight()/2);
} }
_selection = 0; _selection = 0;
} }
@ -34,11 +34,11 @@ SavegameMenu::~SavegameMenu(void) {
savegameMenuNavVal_t SavegameMenu::Run(void) { savegameMenuNavVal_t SavegameMenu::Run(void) {
SDL_FillRect(screen, NULL, 0); SDL_FillRect(screen, NULL, 0);
while(true) { while(true) {
Render(); Render();
SDL_Flip(screen); SDL_Flip(screen);
SDL_Event event; SDL_Event event;
while(SDL_PollEvent(&event)) { while(SDL_PollEvent(&event)) {
switch(event.type) { switch(event.type) {
@ -62,18 +62,18 @@ savegameMenuNavVal_t SavegameMenu::Run(void) {
} }
} }
} }
return savegameMenuCancel; return savegameMenuCancel;
} }
void SavegameMenu::Render(void) { void SavegameMenu::Render(void) {
_title.RenderLiteral(); _title.RenderLiteral();
for(int i = 0; i < 4; i++) { for(int i = 0; i < 4; i++) {
int borderRed; int borderRed;
int borderGreen; int borderGreen;
int borderBlue; int borderBlue;
if(i == _selection) { if(i == _selection) {
borderRed = 255; borderRed = 255;
borderGreen = 128; borderGreen = 128;
@ -83,19 +83,19 @@ void SavegameMenu::Render(void) {
borderGreen = 255; borderGreen = 255;
borderBlue = 255; borderBlue = 255;
} }
roundedBoxRGBA(screen, roundedBoxRGBA(screen,
BOX_SPACING_X, BOXES_OFFSET_Y + (i * BOX_SPACING_Y) + (i * BOX_HEIGHT), BOX_SPACING_X, BOXES_OFFSET_Y + (i * BOX_SPACING_Y) + (i * BOX_HEIGHT),
BOX_SPACING_X + BOX_WIDTH, BOXES_OFFSET_Y + (i * BOX_SPACING_Y) + (i * BOX_HEIGHT) + BOX_HEIGHT, BOX_SPACING_X + BOX_WIDTH, BOXES_OFFSET_Y + (i * BOX_SPACING_Y) + (i * BOX_HEIGHT) + BOX_HEIGHT,
5, 5,
0, 0, 128, 255); 0, 0, 128, 255);
roundedRectangleRGBA(screen, roundedRectangleRGBA(screen,
BOX_SPACING_X, BOXES_OFFSET_Y + (i * BOX_SPACING_Y) + (i * BOX_HEIGHT), BOX_SPACING_X, BOXES_OFFSET_Y + (i * BOX_SPACING_Y) + (i * BOX_HEIGHT),
BOX_SPACING_X + BOX_WIDTH, BOXES_OFFSET_Y + (i * BOX_SPACING_Y) + (i * BOX_HEIGHT) + BOX_HEIGHT, BOX_SPACING_X + BOX_WIDTH, BOXES_OFFSET_Y + (i * BOX_SPACING_Y) + (i * BOX_HEIGHT) + BOX_HEIGHT,
5, 5,
borderRed, borderGreen, borderBlue, 255); borderRed, borderGreen, borderBlue, 255);
_captions[i].RenderLiteral(); _captions[i].RenderLiteral();
} }
} }

View File

@ -9,20 +9,20 @@ class SavegameMenu
public: public:
SavegameMenu(void); SavegameMenu(void);
~SavegameMenu(void); ~SavegameMenu(void);
savegameMenuNavVal_t Run(void); savegameMenuNavVal_t Run(void);
int GetSelection(void) { return _selection; } int GetSelection(void) { return _selection; }
private: private:
void Render(void); void Render(void);
Text _title; Text _title;
Text _captions[4]; Text _captions[4];
int _selection; int _selection;
static const int BOX_WIDTH = 400; static const int BOX_WIDTH = 400;
static const int BOX_HEIGHT = 100; static const int BOX_HEIGHT = 100;
static const int BOX_SPACING_X = 25; static const int BOX_SPACING_X = 25;
static const int BOX_SPACING_Y = 25; static const int BOX_SPACING_Y = 25;
static const int BOXES_OFFSET_Y = 100; static const int BOXES_OFFSET_Y = 100;

View File

@ -88,7 +88,7 @@ int Text::SetTextBlended(string textArg, textSizes_t size, SDL_Color colour,bool
if(wordWrap) { if(wordWrap) {
finalTextContents = DoWordWrap(font, finalTextContents); finalTextContents = DoWordWrap(font, finalTextContents);
} }
std::list<std::string> lines; std::list<std::string> lines;
std::string line; std::string line;
for(int i = 0; i < (int)finalTextContents.size(); i++) { for(int i = 0; i < (int)finalTextContents.size(); i++) {
@ -115,7 +115,7 @@ int Text::SetTextBlended(string textArg, textSizes_t size, SDL_Color colour,bool
w = linePixelWidth; w = linePixelWidth;
} }
h += linePixelHeight + lineSpacing; h += linePixelHeight + lineSpacing;
_lines.push_back(lineSurf); _lines.push_back(lineSurf);
} }
@ -183,7 +183,7 @@ int Text::SetTextShaded(string textArg, textSizes_t size, SDL_Color colour, SDL_
w = linePixelWidth; w = linePixelWidth;
} }
h += linePixelHeight + lineSpacing; h += linePixelHeight + lineSpacing;
_lines.push_back(lineSurf); _lines.push_back(lineSurf);
} }
@ -201,8 +201,8 @@ void Text::Render(void) {
int yOffset = 0; int yOffset = 0;
for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) { for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) {
SDL_Surface* lineSurf = *it; SDL_Surface* lineSurf = *it;
ApplySurface(x, y + yOffset, lineSurf, screen); ApplySurface(x, y + yOffset, lineSurf, screen);
yOffset += lineSurf->h + lineSpacing; yOffset += lineSurf->h + lineSpacing;
} }
} }
@ -210,8 +210,8 @@ void Text::Render(int xArg, int yArg) {
int yOffset = 0; int yOffset = 0;
for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) { for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) {
SDL_Surface* lineSurf = *it; SDL_Surface* lineSurf = *it;
ApplySurface(x + xArg, y + yArg + yOffset, lineSurf, screen); ApplySurface(x + xArg, y + yArg + yOffset, lineSurf, screen);
yOffset += lineSurf->h + lineSpacing; yOffset += lineSurf->h + lineSpacing;
} }
} }
@ -219,8 +219,8 @@ void Text::RenderLiteral(void) {
int yOffset = 0; int yOffset = 0;
for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) { for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) {
SDL_Surface* lineSurf = *it; SDL_Surface* lineSurf = *it;
ApplySurfaceLiteral(x, y + yOffset, lineSurf, screen); ApplySurfaceLiteral(x, y + yOffset, lineSurf, screen);
yOffset += lineSurf->h + lineSpacing; yOffset += lineSurf->h + lineSpacing;
} }
} }
@ -228,8 +228,8 @@ void Text::RenderLiteral(int xArg, int yArg) {
int yOffset = 0; int yOffset = 0;
for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) { for(std::list<SDL_Surface*>::iterator it = _lines.begin(); it != _lines.end(); ++it) {
SDL_Surface* lineSurf = *it; SDL_Surface* lineSurf = *it;
ApplySurfaceLiteral(x + xArg, y + yArg + yOffset, lineSurf, screen); ApplySurfaceLiteral(x + xArg, y + yArg + yOffset, lineSurf, screen);
yOffset += lineSurf->h + lineSpacing; yOffset += lineSurf->h + lineSpacing;
} }
} }
@ -263,7 +263,7 @@ std::string Text::DoWordWrap(TTF_Font* fontArg, const std::string& textArg) {
word = strtok(NULL, " "); word = strtok(NULL, " ");
} }
// delete[] tokenizedText; // delete[] tokenizedText;
return wrappedText; return wrappedText;
} }