#include #include #include #include #include "Model.h" #include "Physics.h" #include "PhysicsBase.h" #include "EntityFactory.h" #include "AsteroidsEvents.h" #include "AsteroidEntity.h" #include namespace asteroids { static Model* ModelInstance = NULL; /* * Inherited Module functions */ int Model::OnInit (int argc, char* argv[]) { int result = Engine::ModelBase::OnInit (argc, argv); ModelInstance = this; 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; } void Model::Process () { if (mLastGameState == mGameState) { if (mGameState == GameStateRunning) { Engine::ModelBase::Process(); } return; } // when we are here we know that something has changed so we need to take // some action. Engine::LogDebug ("Switching from %s->%s", GetStringGameState(mLastGameState), GetStringGameState(mGameState)); if (mLastGameState == GameStateMainMenu && mGameState == GameStateRunning) { mPlayerLives = 3; mCurrentLevelIndex = 0; mPoints = 0; DoLoadLevel (mLevelList[mCurrentLevelIndex].c_str()); } else if (mLastGameState == GameStateRunning && mGameState == GameStatePlayerDied) { mPlayerLives --; ClearEntities(); if (mPlayerLives == 0) mGameState = GameStateGameOver; } 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(mLevelList[mCurrentLevelIndex].c_str()); else if (mLastGameState == GameStateRunning && mGameState == GameStateGameOver) ClearEntities(); // ... and we have to set the last game state to the current gamestate // otherwise we end up in an infinit loop of performing the switching // action. 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())) { std::string level_relative_path (level_dir_name); level_relative_path += dir_iter->path().filename(); mLevelList.push_back (level_relative_path); 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); if (!level_file) { Engine::LogError ("Unable to open file %s for writing!", filename); exit (-1); } ClearEntities(); mAsteroids.clear(); std::string entity_type_str; int entity_count = 0; while (level_file >> entity_type_str) { if (entity_type_str[0] == '#') { getline (level_file, entity_type_str); Engine::LogDebug ("Read Comment: %s", entity_type_str.c_str()); continue; } GameEntityType entity_type = GameEntityTypeUnknown; if (entity_type_str == "GameEntityTypeShip") entity_type = GameEntityTypeShip; else if (entity_type_str == "GameEntityTypeAsteroid") entity_type = GameEntityTypeAsteroid; else { Engine::LogError ("Unknown Entity type: %s", entity_type_str.c_str()); exit (-1); } Engine::EntityBase* entity = CreateEntity (entity_type); bool is_player; level_file >> is_player; if (is_player) mPlayerEntityId = entity->mId; level_file >> entity->mPhysicState->mPosition[0]; level_file >> entity->mPhysicState->mPosition[1]; level_file >> entity->mPhysicState->mPosition[2]; level_file >> entity->mPhysicState->mOrientation[0]; level_file >> entity->mPhysicState->mOrientation[1]; level_file >> entity->mPhysicState->mOrientation[2]; level_file >> entity->mPhysicState->mVelocity[0]; level_file >> entity->mPhysicState->mVelocity[1]; level_file >> entity->mPhysicState->mVelocity[2]; level_file >> entity->mPhysicState->mAngleVelocity; entity_count ++; } level_file.close(); Engine::LogDebug ("%d Entities loaded!", mEntities.size()); return 0; } int Model::DoSaveLevel (const char* filename) { Engine::LogMessage ("Saving level to %s", filename); std::fstream level_file (filename, std::ios::out); if (!level_file) { Engine::LogError ("Unable to open file %s for writing!", filename); exit (-1); } level_file << "# Format" << std::endl; level_file << "# " << std::endl; std::map::iterator iter = mEntities.begin(); unsigned int player_id = GetPlayerEntityId(); for (iter = mEntities.begin(); iter != mEntities.end(); iter++) { Engine::EntityBase* game_entity = iter->second; level_file << GetStringGameEntityType((GameEntityType)game_entity->mType) << "\t" // this stores the player id << (game_entity->mId == player_id) << "\t" << game_entity->mPhysicState->mPosition[0] << "\t" << game_entity->mPhysicState->mPosition[1] << "\t" << game_entity->mPhysicState->mPosition[2] << "\t" << game_entity->mPhysicState->mOrientation[0] << "\t" << game_entity->mPhysicState->mOrientation[1] << "\t" << game_entity->mPhysicState->mOrientation[2] << "\t" << game_entity->mPhysicState->mVelocity[0] << "\t" << game_entity->mPhysicState->mVelocity[1] << "\t" << game_entity->mPhysicState->mVelocity[2] << "\t" << game_entity->mPhysicState->mAngleVelocity << "\t" << std::endl; } level_file.close(); 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; if (entity_type == GameEntityTypeAsteroid) { mAsteroids.push_back (id); } } void Model::OnKillEntity (const Engine::EntityBase *entity) { GameEntityType entity_type = (GameEntityType) entity->mType; if (entity_type == GameEntityTypeAsteroid) { unsigned int i; const AsteroidEntity *asteroid = static_cast(entity); mPoints += 150 + asteroid->mSubAsteroidsCount * 75; for (i = 0; i < mAsteroids.size(); i++) { if (mAsteroids.at(i) == entity->mId) { std::vector::iterator entity_iter = mAsteroids.begin() + i; mAsteroids.erase (entity_iter); break; } } if (mAsteroids.size() == 0) { Engine::EventBasePtr level_complete_event (new Engine::EventBase()); level_complete_event->mEventType = EventLevelComplete; TriggerEvent (level_complete_event); // SetGameState (GameStateLevelComplete); } } } float Model::GetWorldWidth () { return static_cast(mPhysics)->GetWorldWidth(); } float Model::GetWorldHeight () { return static_cast(mPhysics)->GetWorldHeight(); } }