diff --git a/asteroids/AsteroidsEvents.h b/asteroids/AsteroidsEvents.h index e416ebe..a25531c 100644 --- a/asteroids/AsteroidsEvents.h +++ b/asteroids/AsteroidsEvents.h @@ -6,6 +6,7 @@ BEGIN_ENUM(Event) { DECL_ENUM_ELEMENT(EventAccelerateStart), DECL_ENUM_ELEMENT(EventAccelerateStop), + DECL_ENUM_ELEMENT(EventLevelComplete), DECL_ENUM_ELEMENT(EventShipExplode) } END_ENUM(Event) diff --git a/asteroids/MenuOverlay.cc b/asteroids/MenuOverlay.cc index 362be25..8a0fd66 100644 --- a/asteroids/MenuOverlay.cc +++ b/asteroids/MenuOverlay.cc @@ -153,8 +153,18 @@ void MenuOverlay::DrawPlayerDied () { void MenuOverlay::DrawGameOverScreen() { std::ostringstream topbar_stream; - topbar_stream << "That was pathetic! "; - Engine::DrawGLString ( right * 0.5 - 80, bottom * 0.5 - 8, topbar_stream.str().c_str ()); + + Engine::DrawGLString ( right * 0.5 - 60, bottom * 0.5 - 8 - 64, "G a m e O v e r"); + + if (mModel->GetPlayerLives() == 0) { + topbar_stream << "That was pathetic! "; + Engine::DrawGLString ( right * 0.5 - 80, bottom * 0.5 - 8, topbar_stream.str().c_str ()); + } else { + Engine::DrawGLString ( right * 0.5 - 80, bottom * 0.5 - 32, "You earned yourself the"); + Engine::DrawGLString ( right * 0.5 - 60, bottom * 0.5 + 0, "You Rock(TM) award."); + Engine::DrawGLString ( right * 0.5 - 70, bottom * 0.5 + 32, "Go tell your friends."); + } + } void MenuOverlay::DrawGameMenu() { diff --git a/asteroids/Model.cc b/asteroids/Model.cc index 1126ecc..141c5fb 100644 --- a/asteroids/Model.cc +++ b/asteroids/Model.cc @@ -1,11 +1,14 @@ #include #include +#include +#include #include "Model.h" #include "Physics.h" #include "PhysicsBase.h" #include "EntityFactory.h" +#include "AsteroidsEvents.h" #include @@ -24,6 +27,15 @@ int Model::OnInit (int argc, char* argv[]) { mGameState = GameStateMainMenu; mLastGameState = GameStateMainMenu; + /// \TODO use or similar for initialization of mCurrentLevelIndex + mCurrentLevelIndex = 99999; + + if (InitLevelList() == 0) + Engine::LogError ("No levels found!"); + + mLevelCompleteEventHandler = new LevelCompleteEventHandler (this); + Engine::RegisterListener (mLevelCompleteEventHandler, EventLevelComplete); + Engine::LogMessage ("Model Initialization!"); return result; @@ -43,8 +55,8 @@ void Model::Process () { if (mLastGameState == GameStateMainMenu && mGameState == GameStateRunning) { mPlayerLives = 3; - mLevel = 1; - DoLoadLevel ("./data/levels/default.txt"); + mCurrentLevelIndex = 0; + DoLoadLevel (mLevelList[mCurrentLevelIndex].c_str()); } else if (mLastGameState == GameStateRunning && mGameState == GameStatePlayerDied) { mPlayerLives --; @@ -54,10 +66,17 @@ void Model::Process () { if (mPlayerLives == 0) mGameState = GameStateGameOver; } - else if (mLastGameState == GameStateLevelComplete && mGameState == GameStateRunning) - DoLoadLevel ("./data/levels/default.txt"); + else if (mLastGameState == GameStateLevelComplete && mGameState == GameStateRunning) { + mCurrentLevelIndex++; + if (mCurrentLevelIndex == mLevelList.size()) { + SetGameState(GameStateGameOver); + } else { + DoLoadLevel(mLevelList[mCurrentLevelIndex].c_str()); + } + } else if (mLastGameState == GameStatePlayerDied && mGameState == GameStateRunning) - DoLoadLevel ("./data/levels/default.txt"); + // DoLoadLevel (mLevelPath); + assert (0); else if (mLastGameState == GameStateRunning && mGameState == GameStateGameOver) ClearEntities(); @@ -67,6 +86,41 @@ void Model::Process () { mLastGameState = mGameState; } +void DoLoadLevel (unsigned int level_index) { +} + +unsigned int Model::InitLevelList () { + const char* level_dir_name = "./data/levels/"; + Engine::LogDebug ("Searching for levels in %s", level_dir_name); + + mLevelList.clear(); + + boost::filesystem::path level_dir(level_dir_name); + + if (!boost::filesystem::exists(level_dir)) { + Engine::LogError ("Could not init level list: %s does not exist!"); + } + + if (!boost::filesystem::is_directory(level_dir)) { + Engine::LogError ("Could not init level list: %s is not a directory!"); + } + + + boost::filesystem::directory_iterator end_iter; + for (boost::filesystem::directory_iterator dir_iter(level_dir); + dir_iter != end_iter; + ++dir_iter) { + if (boost::filesystem::is_regular_file (dir_iter->status())) { + mLevelList.push_back (std::string(level_dir_name) + dir_iter->path().filename()); + Engine::LogDebug ("Found level %s", mLevelList[mLevelList.size()-1].c_str()); + } + } + + std::sort(mLevelList.begin(), mLevelList.end()); + + return mLevelList.size(); +} + int Model::DoLoadLevel (const char* filename) { Engine::LogMessage ("Loading level from %s", filename); std::fstream level_file (filename, std::ios::in); @@ -171,6 +225,16 @@ int Model::DoSaveLevel (const char* filename) { return 0; } +bool Model::OnLevelComplete() { + Engine::LogMessage ("Level complete!"); + + if (mCurrentLevelIndex + 1== mLevelList.size()) { + SetGameState(GameStateGameOver); + } else { + SetGameState (GameStateLevelComplete); + } +} + void Model::OnCreateEntity (const int type, const unsigned int id) { GameEntityType entity_type = (GameEntityType) type; @@ -194,7 +258,10 @@ void Model::OnKillEntity (const Engine::EntityBase *entity) { } if (mAsteroids.size() == 0) { - SetGameState (GameStateLevelComplete); + Engine::EventBasePtr level_complete_event (new Engine::EventBase()); + level_complete_event->mEventType = EventLevelComplete; + TriggerEvent (level_complete_event); +// SetGameState (GameStateLevelComplete); } } } diff --git a/asteroids/Model.h b/asteroids/Model.h index 0051cd1..f916ce9 100644 --- a/asteroids/Model.h +++ b/asteroids/Model.h @@ -12,6 +12,7 @@ class Model : public Engine::ModelBase { virtual void Process(); int DoLoadLevel (const char* filename); int DoSaveLevel (const char* filename); + bool OnLevelComplete(); void SetGameState (const GameState &state) { mLastGameState = mGameState; @@ -30,6 +31,7 @@ class Model : public Engine::ModelBase { virtual void OnDestroy() { Engine::ModelBase::OnDestroy(); mAsteroids.clear(); + delete mLevelCompleteEventHandler; }; virtual void OnRegisterCommands (); @@ -37,6 +39,8 @@ class Model : public Engine::ModelBase { virtual void OnKillEntity (const Engine::EntityBase *entity); private: + unsigned int InitLevelList (); + /** \brief Keeps a list of all asteroids */ std::vector mAsteroids; @@ -44,7 +48,23 @@ class Model : public Engine::ModelBase { GameState mLastGameState; int mPlayerLives; - int mLevel; + std::vector mLevelList; + unsigned int mCurrentLevelIndex; + + /* event handler class definitions */ + class LevelCompleteEventHandler : public Engine::EventListenerBase { + public: + explicit LevelCompleteEventHandler (Model *view) : mModel (view) {}; + virtual bool HandleEvent (const Engine::EventBasePtr &event) const { + return mModel->OnLevelComplete(); + } + private: + LevelCompleteEventHandler() {}; + Model *mModel; + }; + + /* event handler member variables */ + LevelCompleteEventHandler *mLevelCompleteEventHandler; friend class View; }; diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index bee5431..7942131 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -6,6 +6,9 @@ FIND_PACKAGE (SDL REQUIRED) FIND_PACKAGE (OpenGL REQUIRED) FIND_PACKAGE (PNG REQUIRED) FIND_PACKAGE (FreeType2 REQUIRED) +FIND_PACKAGE (Boost COMPONENTS filesystem REQUIRED) + +INCLUDE_DIRECTORIES (${Boost_INCLUDE_DIRS} ) ADD_SUBDIRECTORY ( libraries ) @@ -52,6 +55,7 @@ TARGET_LINK_LIBRARIES ( Engine ${SDL_LIBRARY} ${OPENGL_LIBRARIES} ${PNG_LIBRARIES} + ${Boost_LIBRARIES} mathlib oglft coll2d