diff --git a/asteroids/Model.cc b/asteroids/Model.cc index 0d5e76e..4fa206b 100644 --- a/asteroids/Model.cc +++ b/asteroids/Model.cc @@ -64,6 +64,7 @@ int Model::OnInit (int argc, char* argv[]) { Engine::RegisterListener (this, EventAccelerateStart); Engine::RegisterListener (this, EventAccelerateStop); + Engine::RegisterListener (this, EventLevelComplete); return result; } @@ -88,6 +89,9 @@ bool Model::OnReceiveEvent (const Engine::EventBasePtr &event) { case EventShipExplode: OnShipExplode(); break; + case EventLevelComplete: + OnLevelComplete (); + break; case EventGameOver: return OnGameOver(); break; @@ -319,6 +323,15 @@ bool Model::PullGlobalHighscore(std::stringstream &highscore_stream) { ip_address[2] = static_cast(ip_address_char[2]); ip_address[3] = static_cast(ip_address_char[3]); + if (ip_address[0] < 0) + ip_address[0] += 256; + if (ip_address[1] < 0) + ip_address[1] += 256; + if (ip_address[2] < 0) + ip_address[2] += 256; + if (ip_address[3] < 0) + ip_address[3] += 256; + Engine::LogMessage ("Pulling global highscore from server %s (%d.%d.%d.%d)", Model::HighscoreServerName.GetStringValue().c_str(), ip_address[0], @@ -394,6 +407,16 @@ bool Model::SubmitGlobalHigscoreEntry (const std::string &name, const unsigned i ip_address[2] = static_cast(ip_address_char[2]); ip_address[3] = static_cast(ip_address_char[3]); + if (ip_address[0] < 0) + ip_address[0] += 256; + if (ip_address[1] < 0) + ip_address[1] += 256; + if (ip_address[2] < 0) + ip_address[2] += 256; + if (ip_address[3] < 0) + ip_address[3] += 256; + + Engine::LogDebug ("Submitting highscore player_name='%s' score_value='%d' to server %s (%d.%d.%d.%d)", name.c_str(), points, @@ -505,6 +528,7 @@ int Model::DoLoadLevel (const char* filename) { mLevelTimeSeconds = 0.f; mLevelParTimeSeconds = -1.f; mLevelPoints = 0; + mLevelTimeBonusPoints = 0; while (level_file >> entity_type_str) { if (entity_type_str[0] == '#') { @@ -710,6 +734,35 @@ void Model::OnShipExplode () { } } +void Model::OnLevelComplete() { + // calculate the bonus points + float level_time = roundf(mLevelTimeSeconds); + float level_par_time = roundf(mLevelParTimeSeconds); + int bonus_points = 0; + + if (level_time <= level_par_time) { + // secret time bonus formula + float a = 1.8, + b = -4.2, + c = 2; + float t_n = mLevelTimeSeconds / mLevelParTimeSeconds; + float bonus_points_f = roundf ( (a * t_n * t_n + b * t_n + c) * static_cast( mLevelPoints )); + if (bonus_points_f < 0.) + bonus_points_f = 0.; + + bonus_points_f = roundf (bonus_points_f / 10.) * 10. + 100.; + mLevelTimeBonusPoints = static_cast (bonus_points_f); + + Engine::LogMessage("Bonus Points: t_n = %f bonus_points_f = %f bonus_points = %u", t_n, bonus_points_f, mLevelTimeBonusPoints); + + } else { + mLevelTimeBonusPoints = 0; + } + + mLevelPoints += mLevelTimeBonusPoints; + mPoints += mLevelPoints; +} + void Model::OnCreateEntity (const int type, const unsigned int id) { GameEntityType entity_type = (GameEntityType) type; @@ -742,6 +795,7 @@ void Model::OnKillEntity (const Engine::EntityBase *entity) { if (mAsteroids.size() == 0) { Engine::EventBasePtr level_complete_event (new Engine::EventBase()); level_complete_event->mEventType = EventLevelComplete; + QueueEvent (level_complete_event); } } diff --git a/asteroids/Model.h b/asteroids/Model.h index 7a06f6b..5faa7dc 100644 --- a/asteroids/Model.h +++ b/asteroids/Model.h @@ -19,6 +19,7 @@ class Model : public Engine::ModelBase { /** \brief Resets values from a previous game */ void OnNewGame (); void OnShipExplode (); + void OnLevelComplete (); /* Level loading etc. */ int DoLoadLevel (const char* filename); @@ -32,6 +33,7 @@ class Model : public Engine::ModelBase { void SetPlayerLives (int lives) { mPlayerLives = lives; }; unsigned int GetPoints () { return mPoints; }; unsigned int GetLevelPoints () { return mLevelPoints; }; + unsigned int GetLevelTimeBonusPoints () { return mLevelTimeBonusPoints; }; std::string GetPlayerName() { return mPlayerName; }; void SetPlayerName(const std::string &name) { Engine::LogDebug("new player name: %s", name.c_str()); @@ -114,6 +116,7 @@ class Model : public Engine::ModelBase { float mLevelTimeSeconds; // par time (= my run through, rounded down + 30 seconds float mLevelParTimeSeconds; + unsigned int mLevelTimeBonusPoints; static Engine::Variable HighscoreServerName; static Engine::Variable HighscoreServerPath; diff --git a/asteroids/View.cc b/asteroids/View.cc index be49684..79bb8bc 100644 --- a/asteroids/View.cc +++ b/asteroids/View.cc @@ -20,6 +20,7 @@ #include #include +#include // #define DRAW_BOUNDARIES #ifdef DRAW_BOUNDARIES @@ -528,21 +529,27 @@ void View::DrawUiMainMenu() { void View::DrawUiGameRunning() { // We choose a different font and also draw it aligned to the right as this // looks nicer with the points - SelectFont ("AldotheApache.ttf size=20 color=#ffffff"); - SetFontJustification (Engine::FontJustificationRight); +// SelectFont ("AldotheApache.ttf size=20 color=#ffffff"); + SelectFont("console.ttf size=23 color=#ffffff"); + float str_width, str_height; std::ostringstream out_stream; - out_stream << GetModel()->GetPlayerLives() << " x "; - DrawGLString (screen_right - 64, screen_bottom - 20, out_stream.str().c_str()); - mGUIShipSprite.DrawAt2D (screen_right - 32 - 10, screen_bottom - 16); + out_stream << GetModel()->GetPlayerLives() << " x "; + DrawGLStringMeasure (out_stream.str().c_str(), &str_width, &str_height); + Engine::GUI::Label (1, out_stream.str().c_str(), screen_right - str_width - 45, screen_bottom - 5); + + mGUIShipSprite.DrawAt2D (screen_right - 20, screen_bottom - 8); out_stream.str(""); - out_stream << GetModel()->GetPoints(); - DrawGLString (screen_right - 30, 40, out_stream.str().c_str()); + out_stream << "Level Score: " << setw(5) << GetModel()->GetLevelPoints(); + DrawGLStringMeasure (out_stream.str().c_str(), &str_width, &str_height); + Engine::GUI::Label (1, out_stream.str().c_str(), screen_right - str_width - 12, str_height + 48); - // revert the font justification - SetFontJustification (Engine::FontJustificationLeft); + out_stream.str(""); + out_stream << "Score: " << GetModel()->GetPoints(); + DrawGLStringMeasure (out_stream.str().c_str(), &str_width, &str_height); + Engine::GUI::Label (1, out_stream.str().c_str(), screen_left + 3, str_height + 48); if (level_assemble_mode) { if (Engine::GUI::CheckKeyPress(SDLK_PAGEDOWN)) { @@ -757,26 +764,57 @@ void View::DrawUiLevelComplete() { int level_time_xpos, level_time_ypos; - temp_stream << "Your time: " << time_seconds_to_string (GetModel()->GetLevelTimeSeconds()); + float level_time = roundf(GetModel()->GetLevelTimeSeconds()); + float level_par_time = roundf(GetModel()->GetLevelParTimeSeconds()); - level_time_xpos = (screen_right - screen_left) * 0.5 - 120; + const static int value_width = 10; + + // ----- Your Time ----- + temp_stream << "Your time: " << setw(value_width) << time_seconds_to_string (level_time); + + level_time_xpos = (screen_right - screen_left) * 0.5 - 170; level_time_ypos = 250; Engine::GUI::Label (1, temp_stream.str().c_str(), level_time_xpos, level_time_ypos + 3 ); + // ----- PAR Time ----- temp_stream.str(""); - temp_stream << "PAR time: " << time_seconds_to_string (GetModel()->GetLevelParTimeSeconds()); + temp_stream << "PAR time: " << setw(value_width) << time_seconds_to_string (level_par_time); - level_time_xpos = (screen_right - screen_left) * 0.5 - 120; level_time_ypos += 32; Engine::GUI::Label (1, temp_stream.str().c_str(), level_time_xpos, level_time_ypos + 3 ); + + // ----- Bonus Points ----- + unsigned int bonus_points = GetModel()->GetLevelTimeBonusPoints(); + temp_stream.str(""); + temp_stream << "Time Bonus: " << setw(value_width) << bonus_points; + + level_time_ypos += 32; + + Engine::GUI::Label (1, temp_stream.str().c_str(), + level_time_xpos, level_time_ypos + 3 + ); + + // ----- New Score ----- + unsigned int player_points = GetModel()->GetPoints(); + + temp_stream.str(""); + temp_stream << "New Score: " << setw(value_width) << player_points; + + level_time_ypos += 32; + + Engine::GUI::Label (1, temp_stream.str().c_str(), + level_time_xpos, level_time_ypos + 3 + ); + + level_time_ypos += 64; - if(Engine::GUI::Button (1, "Next level ...", (screen_right - button_width) * 0.5, screen_bottom * 0.5 + 60, button_width, button_height)) { + if(Engine::GUI::Button (1, "Next level ...", (screen_right - button_width) * 0.5, level_time_ypos, button_width, button_height)) { PopViewState(); // we have to take care when we are testing the level to not proceed to // the next level... @@ -904,10 +942,9 @@ void View::DrawUiHighscore() { float xpos = (screen_right - width) * 0.5; float ypos = 180; - Engine::GUI::Label (4, "Highscores", xpos - 2, ypos + 2); - + DrawGLString (xpos, ypos, "Highscores"); SelectFont("console.ttf size=46 color=#ffffff"); - Engine::GUI::Label (4, "Highscores", xpos, ypos); + DrawGLString (xpos, ypos, "Highscores"); if (GetModel()->GetHighscoreIsOnline()) { SelectFont("console.ttf size=23 color=#887500"); @@ -917,10 +954,9 @@ void View::DrawUiHighscore() { float xpos = (screen_right - width) * 0.5; float ypos = 130; - Engine::GUI::Label (4, title.c_str(), xpos - 1, ypos + 1); - - SelectFont("console.ttf size=23 color=#e8d500"); Engine::GUI::Label (4, title.c_str(), xpos, ypos); + SelectFont("console.ttf size=23 color=#e8d500"); + DrawGLString (xpos, ypos - 1, title.c_str()); } else { SelectFont("console.ttf size=23 color=#808080"); std::string title= "-offline-"; @@ -929,8 +965,6 @@ void View::DrawUiHighscore() { float xpos = (screen_right - width) * 0.5; float ypos = 130; - Engine::GUI::Label (4, title.c_str(), xpos - 1, ypos + 1); - SelectFont("console.ttf size=23 color=#ffffff"); Engine::GUI::Label (4, title.c_str(), xpos, ypos); }