#include "View.h" #include "CameraBase.h" #include "SimpleConsoleOverlay.h" #include "IMGUIControls.h" #include "keytable.h" #include "DrawingsGL.h" #include "Engine.h" #include "Physics.h" #include "Model.h" #include "Controller.h" #include "EventBase.h" #include "Game.h" #include "ShipEntity.h" #include "AsteroidEntity.h" #include "AsteroidsEvents.h" #include "RocketEntity.h" #include #include #include // #define DRAW_BOUNDARIES #ifdef DRAW_BOUNDARIES #include "coll2d.h" #include "DrawingsGL.h" #endif using namespace std; namespace asteroids { static Engine::Variable VarCheatMode ("cheat_mode", "false"); int View::OnInit (int argc, char* argv[]) { ViewBase::OnInit (argc, argv); /* // We want the console mConsoleOverlay = boost::shared_ptr (new Engine::SimpleConsoleOverlay); // We also want to display the log bar mConsoleOverlay->SetDrawLogBar (true); mOverlayManager.Register (mConsoleOverlay, GameStateMainMenu); */ LoadFont("AldotheApache.ttf size=20 color=#000000"); button_width = 250; button_height = 40; // This is a simple star field that makes the game so spacy int i; for (i = 0; i < 200; i++) { BackgroundStar star; star.position[0] = rand() / float(RAND_MAX) * 1.2; star.position[1] = rand() / float(RAND_MAX) * 1.2; star.position[2] = rand() / float(RAND_MAX) * 1.2; mBackgroundStars.push_back (star); } // Editor default variables mEditorEntityId = 0; mEditorState = EditorStateUnknown; mGUIShipSprite.LoadFromPNG(Engine::GetResourceFullPath("/data/textures/ship.png")); mGUIShipSprite.SetScale (0.1); mAsteroidSprite.LoadFromPNG (Engine::GetResourceFullPath("/data/textures/asteroid.png")); mShipSprite.LoadFromPNG (Engine::GetResourceFullPath("/data/textures/ship.png")); mShipThrustSprite.LoadFromPNG (Engine::GetResourceFullPath("/data/textures/ship_thrust.png")); mShipThrustSprite.SetAnimation (4, 8); mShipPartsSprite.LoadFromPNG (Engine::GetResourceFullPath("/data/textures/ship_parts.png")); mShipPartsSprite.SetSubSpriteCount (10); Engine::RegisterListener (this, EventAccelerateStart); Engine::RegisterListener (this, EventAccelerateStop); Engine::RegisterListener (this, EventShipExplode); Engine::RegisterListener (this, EventPlayerDied); Engine::RegisterListener (this, EventGameOver); Engine::RegisterListener (this, EventLevelComplete); PushViewState (ViewStateMainMenu); mCreditsPageIndex = 0; return 0; } void View::OnDestroy() { mBackgroundStars.clear(); mShipPartsEntityIds.clear(); Engine::ViewBase::OnDestroy(); } bool View::OnReceiveEvent (const Engine::EventBasePtr &event) { switch (event->mEventType) { case EventAccelerateStart: case EventAccelerateStop: if (event->mEventType == EventAccelerateStart) mShipThrustSprite.ResetAnimation(); Engine::LogDebug ("Received Acceleration Event: %d", event->mEventType); return true; break; case EventLevelComplete: if (GetModel()->GetGameState() == GameStateRunning) { PushViewState(ViewStateLevelComplete); GetController()->ResetPlayerEntity(); } break; case EventGameOver: mFadeTimerSecValue = 2.; PopViewState(); PushViewState(ViewStateGameOver); GetController()->ResetPlayerEntity(); break; case EventPlayerDied: mFadeTimerSecValue = 2.; PushViewState(ViewStatePlayerDied); GetController()->ResetPlayerEntity(); break; case EventShipExplode: { // This event is fired when the ship explodes. Note: this event is not // sufficient for EventPlayerDied! Engine::LogDebug ("Received PlayerDied Event: %d", event->mEventType); // insert sprits that contains parts of the ship Engine::EntityBase *ship_entity = Engine::GetEntity (event->mEventUnsignedInt); vector3d position = ship_entity->mPhysicState->mPosition; vector3d orientation = ship_entity->mPhysicState->mOrientation; vector3d velocity = ship_entity->mPhysicState->mVelocity; vector3d rel_velocity = event->mVector3d; unsigned int i; mShipPartsEntityIds.clear(); for (i = 0; i < mShipPartsSprite.GetSubSpriteCount(); i++) { Engine::EntityBase* part_sprite_particle = Engine::CreateEntity (GameEntityTypeShipPart); part_sprite_particle->mPhysicState->mPosition = position; part_sprite_particle->mPhysicState->mOrientation = orientation; vector3d part_velocity ( rel_velocity[0] * (rand()/float(RAND_MAX)) * 1.7, 0., rel_velocity[2] * (rand()/float(RAND_MAX)) * 1.5 ); part_sprite_particle->mPhysicState->mVelocity = part_velocity * -1.; part_sprite_particle->mPhysicState->mAngleVelocity = (rand()/float(RAND_MAX) - 0.5 ) * 100.; mShipPartsEntityIds.push_back(part_sprite_particle->mId); } // We do not need the entity anymore Engine::KillEntity(event->mEventUnsignedInt); return true; break; } default: Engine::LogWarning ("Received Event with type %d but don't know what to do with it!", event->mEventType); break; } return false; } /* * Module specific functions */ void View::UpdateCamera () { mCamera->SetEye ( 0., 9.5, 0. ); mCamera->SetPointOfIntrest ( 0., 0., 0. ); mCamera->SetUp ( 0., 0., -1. ); mCamera->Update (); } void View::DrawStars() { unsigned int i; float world_width, world_height; world_width = static_cast(mModel)->GetWorldWidth(); world_height = static_cast(mModel)->GetWorldHeight(); vector3d velocity (1., 0., 0.); glPushMatrix(); glTranslatef(-world_width * 0.5, 0, -world_height * 0.5); glColor3f (1., 1., 1.); glPointSize(2.); glBegin(GL_POINTS); float z_value; for (i = 0; i < mBackgroundStars.size(); i++) { // glPointSize (2. + 300. *mBackgroundStars.at(i).position[1]); z_value = mBackgroundStars.at(i).position[1] + 0.1; glColor3f (z_value, z_value, z_value); glVertex3f (mBackgroundStars.at(i).position[0] * world_width, -1., mBackgroundStars.at(i).position[2] * world_height); mBackgroundStars.at(i).position -= vector3d(Engine::GetFrameDuration() * 0.7 * mBackgroundStars.at(i).position[1] / world_width, 0., 0.); // we move the stars a little more such that they are not blende out too early // \todo compute proper bounds from Physics world size! if (mBackgroundStars.at(i).position[0] < -0.1) mBackgroundStars.at(i).position[0] += 1.2; if (mBackgroundStars.at(i).position[0] >= 1.1) mBackgroundStars.at(i).position[0] -= 1.2; } glEnd(); glPopMatrix(); } void View::Draw() { PreDraw(); mFadeTimerSecValue -= GetModel()->GetFrameDuration(); // Actual Drawing UpdateCamera (); if (mDrawGrid) DrawGrid (); /* if (mDrawAxis) DrawAxis (); */ std::map::iterator entity_iterator; Model *game_model = static_cast (mModel); unsigned int game_state = game_model->GetGameState(); unsigned int view_state = GetViewState(); DrawStars (); if ( game_state == GameStateRunning || view_state == ViewStateLevelIntro || view_state == ViewStateEditor) { DrawWorld (); } DrawUi (); // Perform post-Draw actions PostDraw(); } void View::DrawWorld() { std::map::iterator entity_iterator; Model *game_model = static_cast (mModel); ViewBase::DrawWorld(); for (entity_iterator = game_model->mEntities.begin (); entity_iterator != game_model->mEntities.end(); entity_iterator++) { Engine::EntityBase* entity = entity_iterator->second; // Perform multiple drawing if the entity is at the border Physics* game_physics = (Physics*) game_model->mPhysics; float world_width = game_physics->GetWorldWidth(); float world_height = game_physics->GetWorldHeight(); // if we are in Edit mode and are currently editing the velocity we must // make sure that we display it if (GetViewState() == ViewStateEditor) { if (mEditorState == EditorStateEntityVelocity) { DrawVector (entity->mPhysicState->GetPosition(), entity->mPhysicState->GetPosition() + entity->mPhysicState->GetVelocity()); } } // Drawing at the original position: glPushMatrix (); glTranslatef (entity->mPhysicState->mPosition[0], entity->mPhysicState->mPosition[1], entity->mPhysicState->mPosition[2]); glRotatef(entity->mPhysicState->mOrientation[0], 0., 0., 1.); glRotatef(entity->mPhysicState->mOrientation[1], 0., 1., 0.); glRotatef(entity->mPhysicState->mOrientation[2], 1., 0., 0.); glColor3f (1., 1., 1.); DrawEntity (entity); glPopMatrix (); // If we move out the right side if (entity->mPhysicState->mPosition[0] + entity->mPhysicState->mRadius * 2 >= world_width * 0.5) { glPushMatrix (); glTranslatef (entity->mPhysicState->mPosition[0] - world_width, entity->mPhysicState->mPosition[1], entity->mPhysicState->mPosition[2]); glRotatef(entity->mPhysicState->mOrientation[0], 0., 0., 1.); glRotatef(entity->mPhysicState->mOrientation[1], 0., 1., 0.); glRotatef(entity->mPhysicState->mOrientation[2], 1., 0., 0.); glColor3f (1., 1., 1.); DrawEntity (entity); glPopMatrix (); } // if we move out the left side if (entity->mPhysicState->mPosition[0] - entity->mPhysicState->mRadius * 2 < - world_width * 0.5) { glPushMatrix (); glTranslatef (entity->mPhysicState->mPosition[0] + world_width, entity->mPhysicState->mPosition[1], entity->mPhysicState->mPosition[2]); glRotatef(entity->mPhysicState->mOrientation[0], 0., 0., 1.); glRotatef(entity->mPhysicState->mOrientation[1], 0., 1., 0.); glRotatef(entity->mPhysicState->mOrientation[2], 1., 0., 0.); glColor3f (1., 1., 1.); DrawEntity (entity); glPopMatrix (); } // If we move out the bottom side if (entity->mPhysicState->mPosition[2] + entity->mPhysicState->mRadius * 2 >= world_height * 0.5) { glPushMatrix (); glTranslatef (entity->mPhysicState->mPosition[0], entity->mPhysicState->mPosition[1], entity->mPhysicState->mPosition[2] - world_height); glRotatef(entity->mPhysicState->mOrientation[0], 0., 0., 1.); glRotatef(entity->mPhysicState->mOrientation[1], 0., 1., 0.); glRotatef(entity->mPhysicState->mOrientation[2], 1., 0., 0.); glColor3f (1., 1., 1.); DrawEntity (entity); glPopMatrix (); } // if we move out the left side if (entity->mPhysicState->mPosition[2] - entity->mPhysicState->mRadius * 2 < - world_height* 0.5) { glPushMatrix (); glTranslatef (entity->mPhysicState->mPosition[0], entity->mPhysicState->mPosition[1], entity->mPhysicState->mPosition[2] + world_height); glRotatef(entity->mPhysicState->mOrientation[0], 0., 0., 1.); glRotatef(entity->mPhysicState->mOrientation[1], 0., 1., 0.); glRotatef(entity->mPhysicState->mOrientation[2], 1., 0., 0.); glColor3f (1., 1., 1.); DrawEntity (entity); glPopMatrix (); } } } /* * Userinterface */ void View::DrawUi () { glClearColor (0.1, 0.1, 0.1, 1.); screen_right = static_cast (Engine::GetWindowWidth()); screen_bottom = static_cast (Engine::GetWindowHeight()); // we switch to orthographic projection and draw the contents of the 2d // overlay on top of the previous drawings glMatrixMode (GL_PROJECTION); glPushMatrix (); glLoadIdentity (); // first we have to get the size of the current viewport to set up the // orthographic projection correctly GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); gluOrtho2D (viewport[0], viewport[2], viewport[3], viewport[1]); glMatrixMode (GL_MODELVIEW); glPushMatrix (); glLoadIdentity (); unsigned int game_state = GetModel()->GetGameState(); SelectFont("console.ttf"); SetFontJustification (Engine::FontJustificationLeft); ViewState current_view_state = GetViewState(); /* SelectFont ("console.ttf size=12"); Engine::GUI::Label (99999, GetStringViewState(current_view_state), 8, 16); */ switch (current_view_state) { case ViewStateMainMenu: DrawUiMainMenu(); break; case ViewStateGameRunning: DrawUiGameRunning(); break; case ViewStatePaused: DrawUiGamePaused(); break; case ViewStatePlayerDied: DrawUiPlayerDied(); break; case ViewStateLevelIntro: DrawUiLevelIntro(); break; case ViewStateLevelComplete: DrawUiLevelComplete(); break; case ViewStateShowHighscore: DrawUiHighscore(); break; case ViewStateOptions: DrawUiOptions(); break; case ViewStateEnterPlayername: DrawUiEnterPlayername(); break; case ViewStateGameOver: DrawUiGameOver(); break; case ViewStateEditor: DrawUiEditor(); break; case ViewStateCredits: DrawUiCredits(); break; default: Engine::LogWarning ("Trying to draw unknown ViewState: %s (%d)", GetStringViewState (game_state), game_state); break; } glPopMatrix (); glMatrixMode (GL_PROJECTION); glPopMatrix (); glMatrixMode (GL_MODELVIEW); } void View::DrawPageTitle (const std::string& title) { SelectFont("console.ttf size=46 color=#808080"); float width, height; DrawGLStringMeasure(title.c_str(), &width, &height); float xpos = (screen_right - width) * 0.5 - 40; float ypos = 180; DrawGLString (xpos - 2, ypos + 2, title.c_str()); SelectFont("console.ttf size=46 color=#ffffff"); DrawGLString (xpos, ypos, title.c_str()); } void View::DrawUiMainMenu() { DrawPageTitle ("Asteroids"); SelectFont("console.ttf size=23 color=#444444"); DrawGLString( screen_right - 272, screen_bottom - 16, "http://www.fysx.org"); SelectFont("console.ttf size=23 color=#cccccc"); DrawGLString( screen_right - 270, screen_bottom - 18, "http://www.fysx.org"); SelectFont("console.ttf size=23"); if (Engine::GUI::Button (1, "New Game", screen_right * 0.5 - 100, 200, button_width, button_height)) { PushViewState(ViewStateEnterPlayername); } if (Engine::GUI::Button (2, "Options", screen_right * 0.5 - 100, 250, button_width, button_height)) { PushViewState (ViewStateOptions); } if (Engine::GUI::Button (3, "Highscores", screen_right * 0.5 - 100, 300, button_width, button_height)) { GetModel()->LoadHighscoreList(); PushViewState(ViewStateShowHighscore); } if (Engine::GUI::Button (4, "Credits", screen_right * 0.5 - 100, 350, button_width, button_height)) { mCreditsPageIndex = 0; PushViewState(ViewStateCredits); } if (Engine::GUI::Button (5, "Quit", screen_right * 0.5 - 100, 430, button_width, button_height)) { Engine::RunCommand("quit"); } } void View::DrawUiGameRunning() { SelectFont("console.ttf size=23 color=#ffffff"); float str_width, str_height; std::ostringstream out_stream; // --- Player Lives --- 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); // --- Level Score --- out_stream.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); // --- Game Score --- 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 (VarCheatMode.GetBoolValue()) { if (Engine::GUI::CheckKeyPress(SDLK_PAGEDOWN)) { Engine::EventBasePtr level_complete_event (new Engine::EventBase()); level_complete_event->mEventType = EventLevelComplete; QueueEvent (level_complete_event); } else if (Engine::GUI::CheckKeyPress(SDLK_PAGEUP)) { unsigned int current_level = GetModel()->GetCurrentLevelIndex(); if (current_level > 0) { GetModel()->SetGameState(GameStatePaused); GetModel()->LoadLevelFromIndex(current_level - 1); PushViewState(ViewStateLevelIntro); Engine::StartTimer ("LevelIntroLevelNumber", 0.4); Engine::StartTimer ("LevelIntroLevelTitle", 0.6); Engine::StartTimer ("LevelIntroLevelAuthor", 0.8); Engine::StartTimer ("LevelIntroLevelStart", 1.0); } } } if (Engine::GUI::CheckKeyPress(SDLK_ESCAPE)) { PushViewState(ViewStatePaused); GetModel()->SetGameState(GameStatePaused); } } void View::DrawUiGameOver() { DrawPageTitle ("Game Over"); SelectFont("console.ttf size=23 color=#ffffff"); if (GetModel()->GetPlayerLives() == 0) { int text_xpos = screen_right * 0.5, text_ypos = screen_bottom * 0.5 - 64; Engine::GUI::LabelCentered(5, "That was pathetic!", text_xpos, text_ypos); const static int value_width = 10; text_ypos += 48; // ----- New Score ----- unsigned int player_points = GetModel()->GetPoints(); if (player_points != 0) { Engine::GUI::LabelCentered (1, "At least you made a score of:", text_xpos, text_ypos + 3 ); text_ypos += 32; stringstream temp_stream; temp_stream.str(""); temp_stream << player_points << " points."; Engine::GUI::LabelCentered (1, temp_stream.str().c_str(), text_xpos, text_ypos + 3 ); } else { Engine::GUI::LabelCentered (1, "In fact, it's embarrassing, as you", text_xpos, text_ypos + 3 ); text_ypos += 32; Engine::GUI::LabelCentered (1, "did not even finish a single level.", text_xpos, text_ypos + 3 ); } text_ypos += 48; Engine::GUI::LabelCentered (1, "Play harder!", text_xpos, text_ypos + 3 ); } else { Engine::GUI::LabelCentered (6, "You earned yourself the", screen_right * 0.5, screen_bottom * 0.5 - 32); Engine::GUI::LabelCentered (7, "You Rock(TM) award.", screen_right * 0.5, screen_bottom * 0.5 + 0); Engine::GUI::LabelCentered (8, "Go tell your friends.", screen_right * 0.5, screen_bottom * 0.5 + 32); } if (mFadeTimerSecValue > 0.) return; if (Engine::GUI::Button (2, "Highscores", (screen_right - button_width) * 0.5, screen_bottom * 0.5 + 100, button_width, button_height)) { // We do not want the background to show the remaining bits of the game GetModel()->SetGameState(GameStatePaused); GetModel()->SubmitHighscoreEntry(GetModel()->GetPlayerName(), GetModel()->GetPoints()); PopViewState(); PushViewState(ViewStateShowHighscore); } } void View::DrawUiLevelIntro() { SelectFont ("console.ttf size=23"); if (VarCheatMode.GetBoolValue()) { GetModel()->SetPlayerLives(100); } stringstream level_info_stream; level_info_stream << "Level " << GetModel()->GetCurrentLevelIndex() + 1; int level_number_dest_x = (screen_right - screen_left) * 0.5 - 180; int level_number_dest_y = (screen_bottom - screen_top) * 0.5 - 60; int level_number_start_x = level_number_dest_x; int level_number_start_y = (screen_top); int level_number_delta_x = level_number_dest_x - level_number_start_x; int level_number_delta_y = level_number_dest_y - level_number_start_y; Engine::GUI::Label (20, level_info_stream.str().c_str(), level_number_dest_x - Engine::GetTimer("LevelIntroLevelNumber") * level_number_delta_x, level_number_dest_y - Engine::GetTimer("LevelIntroLevelNumber") * level_number_delta_y ); int level_title_dest_x = (screen_right - screen_left) * 0.5; int level_title_dest_y = (screen_bottom) * 0.5 - 36; int level_title_start_x = (screen_right - screen_left) * 0.5; int level_title_start_y = (screen_bottom); int level_title_delta_x = level_title_dest_x - level_title_start_x; int level_title_delta_y = level_title_dest_y - level_title_start_y; SelectFont("console.ttf size=46 color=#505050"); std::string level_title = GetModel()->GetLevelTitle(); if (level_title.size() > 24) { // in that case we break up the level title in two lines size_t first_line_end = level_title.find_last_of (" ", 24); std::string first_line = level_title.substr (0, first_line_end); std::string second_line = level_title.substr (first_line_end + 1, level_title.size()); Engine::GUI::LabelCentered (21, first_line.c_str(), level_title_dest_x - Engine::GetTimer("LevelIntroLevelTitle") * level_title_delta_x - 2, level_title_dest_y - Engine::GetTimer("LevelIntroLevelTitle") * level_title_delta_y + 2 ); Engine::GUI::LabelCentered (21, second_line.c_str(), level_title_dest_x - Engine::GetTimer("LevelIntroLevelTitle") * level_title_delta_x - 2, level_title_dest_y - Engine::GetTimer("LevelIntroLevelTitle") * level_title_delta_y + 2 + 40 ); } else { Engine::GUI::LabelCentered (21, level_title.c_str(), level_title_dest_x - Engine::GetTimer("LevelIntroLevelTitle") * level_title_delta_x - 2, level_title_dest_y - Engine::GetTimer("LevelIntroLevelTitle") * level_title_delta_y + 2 ); } SelectFont ("console.ttf size=23"); level_info_stream.str(""); level_info_stream << "by " << GetModel()->GetLevelAuthor(); int level_author_dest_x = (screen_right - screen_left) * 0.5 + 80; int level_author_dest_y = (screen_bottom - screen_top) * 0.5 + 20; if (level_title.size() > 24) { level_author_dest_y += 40; } // draw a greyish backround behind the title which can improve // readability glColor4f( 1., 1., 1., 0.1); DrawRect2D (screen_left, level_title_dest_y - 24, screen_right - screen_left, level_author_dest_y - level_title_dest_y - 4); int level_author_start_x = screen_right; int level_author_start_y = level_author_dest_y; int level_author_delta_x = level_author_dest_x - level_author_start_x; int level_author_delta_y = level_author_dest_y - level_author_start_y; Engine::GUI::Label (22, level_info_stream.str().c_str(), level_author_dest_x - Engine::GetTimer("LevelIntroLevelAuthor") * level_author_delta_x, level_author_dest_y - Engine::GetTimer("LevelIntroLevelAuthor") * level_author_delta_y ); if (Engine::CheckTimer("LevelIntroLevelStart")) { if(Engine::GUI::Button (1, "Start", (screen_right - button_width) * 0.5, screen_bottom * 0.5 + 180, button_width, button_height)) { PopViewState(); GetModel()->SetGameState(GameStateRunning); } } if (Engine::GUI::CheckKeyPressed(SDLK_ESCAPE) ) { PushViewState(ViewStatePaused); } } void split_time_seconds (float time_seconds, int *minutes, int *seconds) { float current_time = roundf(time_seconds); *minutes = static_cast (floor (current_time / 60.f)); *seconds = static_cast (current_time - *minutes * 60); } std::string time_seconds_to_string (float time_seconds) { stringstream time_stream; int minutes, seconds; split_time_seconds (time_seconds, &minutes, &seconds); time_stream << minutes << ":"; if (seconds < 10) time_stream << "0"; time_stream << seconds; return time_stream.str(); } void View::DrawUiLevelComplete() { DrawPageTitle ("Level Complete!"); if (GetModel()->GetGameModified()) { SelectFont("console.ttf size=23 color=#cc0000"); float width, height; std::string message ("* UNOFFICIAL GAME * UNOFFICIAL GAME * UNOFFICIAL GAME *"); float xpos = (screen_left) + 5; float ypos = 20; DrawGLString (xpos, ypos, message.c_str()); ypos = screen_bottom - 4; DrawGLString (xpos, ypos, message.c_str()); } SelectFont ("console.ttf size=23 color=#ffffff"); stringstream temp_stream; int minutes, seconds; split_time_seconds (GetModel()->GetLevelTimeSeconds(), &minutes, &seconds); int level_time_xpos, level_time_ypos; float level_time = roundf(GetModel()->GetLevelTimeSeconds()); float level_par_time = roundf(GetModel()->GetLevelParTimeSeconds()); 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: " << setw(value_width) << time_seconds_to_string (level_par_time); level_time_ypos += 32; Engine::GUI::Label (1, temp_stream.str().c_str(), level_time_xpos, level_time_ypos + 3 ); // ----- Level Points ----- unsigned int level_points = GetModel()->GetLevelPoints() - GetModel()->GetLevelTimeBonusPoints(); temp_stream.str(""); temp_stream << "Level Points: " << setw(value_width) << level_points; 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, 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... if (GetViewState() == ViewStateEditor) { GetModel()->SetGameState(GameStatePaused); if (mEditorState == EditorStateTest) { GetModel()->DoLoadLevel("level_edit_temp.map"); mEditorState = EditorStateUnknown; } } else { PushViewState(ViewStateLevelIntro); Engine::StartTimer ("LevelIntroLevelNumber", 0.4); Engine::StartTimer ("LevelIntroLevelTitle", 0.6); Engine::StartTimer ("LevelIntroLevelAuthor", 0.8); Engine::StartTimer ("LevelIntroLevelStart", 1.0); GetModel()->ProceedToNextLevel(); GetModel()->SetGameState(GameStatePaused); } } } void View::DrawUiGamePaused() { DrawPageTitle ("Game Paused"); SelectFont ("console.ttf size=23"); if (Engine::GUI::Button (1, "Resume Game", screen_right * 0.5 - 100, 200, button_width, button_height)) { PopViewState(); if (GetViewState() == ViewStateGameRunning) GetModel()->SetGameState(GameStateRunning); } if (Engine::GUI::Button (2, "Options", screen_right * 0.5 - 100, 250, button_width, button_height)) { PushViewState (ViewStateOptions); } if (Engine::GUI::Button (3, "Abort Game", screen_right * 0.5 - 100, 300, button_width, button_height)) { ResetViewState(); PushViewState(ViewStateMainMenu); GetModel()->SetGameState(GameStatePaused); } if (Engine::GUI::Button (4, "Quit", screen_right * 0.5 - 100, 380, button_width, button_height)) { Engine::RunCommand("quit"); } } void View::DrawUiPlayerDied() { DrawPageTitle ("You died!"); SelectFont ("console.ttf size=23"); if (mFadeTimerSecValue > 0.) return; if (Engine::GUI::Button (1, "Continue", screen_right * 0.5 - 100, 380, button_width, button_height)) { PopViewState(); // we have to take care when we are testing the level to not proceed to // the next level... if (GetViewState() == ViewStateEditor) { GetModel()->SetGameState(GameStatePaused); if (mEditorState == EditorStateTest) { GetModel()->DoLoadLevel("level_edit_temp.map"); mEditorState = EditorStateUnknown; } } else { GetModel()->ReloadLevel(); GetModel()->SetGameState(GameStatePaused); PushViewState(ViewStateLevelIntro); Engine::StartTimer ("LevelIntroLevelNumber", 0.4); Engine::StartTimer ("LevelIntroLevelTitle", 0.6); Engine::StartTimer ("LevelIntroLevelAuthor", 0.8); Engine::StartTimer ("LevelIntroLevelStart", 1.0); } } } /** \brief Draws an entry in the form .... * * The amount of dots is also computed within this function. Not necessarily * fast, however it works for now. */ void View::DrawHighscoreEntry (float x, float y, float entry_width, const std::string &name, unsigned int points) { const float width_buffer = 30.; float width, height; float name_width, points_value_width; // Measure and draw the name DrawGLStringMeasure (name.c_str(), &name_width, &height); name_width = fabsf(name_width); Engine::DrawGLString ( x, y, name.c_str()); // Compute the width of the points value when it is printed out std::ostringstream points_value_stream; points_value_stream << points; DrawGLStringMeasure (points_value_stream.str().c_str(), &points_value_width, &height); points_value_width = fabsf(points_value_width); // Compute the amount of dots. This is done by iteratively adding a dot '.' // to a stream and check whether it has the desired width. float dots_width = 0.; std::ostringstream dots_stream; while (ceil(name_width) + dots_width + points_value_width + width_buffer < entry_width) { dots_stream << "."; DrawGLStringMeasure (dots_stream.str().c_str(), &dots_width, &height); dots_width = fabsf(dots_width); } // Drawing of the dots and the points value Engine::DrawGLString ( x + entry_width - points_value_width - dots_width - 10, y, dots_stream.str().c_str()); Engine::DrawGLString ( x + entry_width - points_value_width, y, points_value_stream.str().c_str()); } void View::DrawUiHighscore() { // DrawPageTitle but centered: SelectFont("console.ttf size=46 color=#808080"); float width, height; DrawGLStringMeasure("Highscores", &width, &height); float xpos = (screen_right - width) * 0.5; float ypos = 180; DrawGLString (xpos, ypos, "Highscores"); SelectFont("console.ttf size=46 color=#ffffff"); DrawGLString (xpos, ypos, "Highscores"); if (GetModel()->GetHighscoreIsOnline()) { SelectFont("console.ttf size=23 color=#887500"); std::string title= "-online-"; float width, height; DrawGLStringMeasure(title.c_str(), &width, &height); float xpos = (screen_right - width) * 0.5; float ypos = 130; 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-"; float width, height; DrawGLStringMeasure(title.c_str(), &width, &height); float xpos = (screen_right - width) * 0.5; float ypos = 130; SelectFont("console.ttf size=23 color=#ffffff"); Engine::GUI::Label (4, title.c_str(), xpos, ypos); } SelectFont ("console.ttf size=23"); unsigned int entry_length = 32; float char_width; DrawGLStringMeasure ("M", &char_width, &height); height = fabsf(height); float entry_width = fabsf(char_width * entry_length); float x = screen_right * 0.5 - entry_width * 0.5; float y = screen_bottom * 0.5 - 8 - 128; // then we do the drawings y += 60; std::list::iterator highscore_iter = GetModel()->mHighscoreList.begin(); SetFontJustification(Engine::FontJustificationLeft); unsigned int i = 0; while (highscore_iter != GetModel()->mHighscoreList.end()) { // Check whether we have to highlight an entry (such as when entering // the name) if (GetModel()->GetPlayerName() == highscore_iter->name && GetModel()->GetPoints() == highscore_iter->points) { // we highlight the newest entry SelectFont("console.ttf color=#e8d500 size=23"); } else { SelectFont("console.ttf color=#ffffff size=23"); } DrawHighscoreEntry ( x, y, entry_width, highscore_iter->name, highscore_iter->points); // go down one line y += height * 1.3; i++; highscore_iter++; } if (Engine::GUI::Button (1, "Back to Menu", screen_right * 0.5 - 250 * 0.5, y + 16, button_width, button_height) || Engine::GUI::CheckKeyPressed(SDLK_ESCAPE) ) { // Remove the ViewStateGameRunning while (GetViewState() != ViewStateMainMenu) { PopViewState(); } } } void View::DrawUiOptions() { DrawPageTitle ("Options"); SelectFont ("console.ttf size=23"); Engine::GUI::Label (10, "Effects Volume: ", screen_right * 0.5 - 150, 240); float effects_volume = Engine::GetEffectsVolume(); if (Engine::GUI::VerticalSlider (1, screen_right * 0.5 - 100, 250, 250, 16, 0., 1., effects_volume)) { Engine::LogDebug ("Setting effects volume to: %f", effects_volume); Engine::SetEffectsVolume(effects_volume); } Engine::GUI::Label (11, "Music Volume: ", screen_right * 0.5 - 150, 300); float music_volume = Engine::GetMusicVolume(); if (Engine::GUI::VerticalSlider (2, screen_right * 0.5 - 100, 310, 250, 16, 0., 1., music_volume)) { Engine::LogDebug ("Setting music volume to: %f", music_volume); Engine::SetMusicVolume(music_volume); } bool use_online_mode = Model::UseServerHighscore.GetBoolValue(); std::string online_button_caption; if (use_online_mode) { online_button_caption = "Highscore: online"; } else { online_button_caption = "Highscore: offline"; } if (Engine::GUI::CheckButton (12, online_button_caption.c_str(), use_online_mode, screen_right*0.5 - 130, 360, 300, button_height)) { if (use_online_mode) Model::UseServerHighscore.Set("no"); else Model::UseServerHighscore.Set("yes"); } if (Engine::GUI::Button (5, "Back", screen_right * 0.5 - 100, 480, button_width, button_height) || Engine::GUI::CheckKeyPressed(SDLK_ESCAPE) ) { PopViewState(); } } void View::DrawUiCredits() { // DrawPageTitle ("Credits"); SelectFont ("console.ttf size=23"); static std::string credits_content ( "_Programming, Design,\r\ _ Sounds, and Graphics\r\ Martin Felis\r\ \r\ _Top Level Designer\r\ Sir Wolle\r\ \r\ \r\ _Additional Level Design\r\ Martin Felis\r\ michi\r\ Andi\r\ Sebastian Felis\r\ Khai-Long Ho Hoang\r\ \r\ _Music\r\ DJad - Space Exploration\r\ \r\ _Libraries\r\ libSDL\r\ SDL_mixer\r\ OGLFT\r\ freetype2\r\ boost\r\ libpng\r\ \r\ Aaron D. Gifford's sha2 code\r\ \r\ _Tools\r\ GIMP\r\ Blender\r\ CMake\r\ sfxr-sdl\r\ Audacity\r\ \r\ _Special Thanks\r\ to my wonderful wife Katrina\r\ \r\ \r\ \r\ \r\ \r\ _http://www.fysx.org\r\ \r\ \r\ \r\ \r\ \r\ \r\ \r\ \r\ :created with vim.\r\ ::wq\r\ \r\ EOF\r\ "); static float page_duration = 5.; static float page_draw_duration = page_duration; stringstream credits_stream (credits_content); std::string line; float xpos = 270, ypos = 200.f; float dy = 20.f; unsigned int index = 0; bool first_content_line = false; while (getline (credits_stream, line, '\r')) { if (line.size() == 0) { index ++; continue; } if (index == mCreditsPageIndex) { if (line[0] == '_') { SelectFont ("console.ttf size=23 color=#e8d500"); line = line.substr (1, line.size()); first_content_line = true; } else if (line[0] == ':') { SelectFont ("console.ttf size=23 color=#ffffff"); line = line.substr (1, line.size()); } else { if (first_content_line) { ypos += 20; first_content_line = false; } SelectFont ("console.ttf size=23 color=#ffffff"); } DrawGLString (xpos, ypos, line.c_str()); ypos += dy; } else { continue; } if (index == mCreditsPageIndex && line == std::string("EOF")) { PopViewState(); } } if (page_draw_duration < 0.) { mCreditsPageIndex ++; page_draw_duration = page_duration; // Level contributors are shown a bit longer if (mCreditsPageIndex == 1) { page_draw_duration *= 1.5; } } page_draw_duration -= Engine::GetFrameDuration(); if (Engine::GUI::CheckKeyPressed(SDLK_ESCAPE) || Engine::GUI::CheckKeyPressed(SDLK_SPACE) ) { PopViewState(); } } void View::DrawUiEnterPlayername() { DrawPageTitle ("Asteroids"); SelectFont ("console.ttf size=23"); // Enter your name std::string player_name = GetModel()->GetPlayerName(); SelectFont("console.ttf size=23"); Engine::GUI::Label (1, "Enter your name: ", screen_right * 0.5 - 220, 250); std::string valid_chars ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-_!. "); if (Engine::GUI::LineEditMasked (2, screen_right * 0.5 + 20, 238, player_name, 16, valid_chars)) { GetModel()->SetPlayerName(player_name); } if (Engine::GUI::Button (3, "Start Game", screen_right - 180 - 20, 500, 180, 40)) { PopViewState(); GetModel()->OnNewGame(); PushViewState(ViewStateGameRunning); PushViewState(ViewStateLevelIntro); Engine::StartTimer ("LevelIntroLevelNumber", 0.4); Engine::StartTimer ("LevelIntroLevelTitle", 0.6); Engine::StartTimer ("LevelIntroLevelAuthor", 0.8); Engine::StartTimer ("LevelIntroLevelStart", 1.0); GetModel()->SetGameState(GameStatePaused); } if (Engine::GUI::Button (5, "Back", 20, 500, 180, 40) || Engine::GUI::CheckKeyPressed(SDLK_ESCAPE) ) { PopViewState(); } } void View::DrawUiEditor() { // DrawPageTitle ("Editor"); SelectFont ("console.ttf size=23"); // The close button if (Engine::GUI::Button (1, "X", screen_right - 48, 20, 32, button_height) || Engine::GUI::CheckKeyPressed(SDLK_ESCAPE)) { if (mEditorState == EditorStateTest) { mEditorState = EditorStateUnknown; GetModel()->DoLoadLevel("level_edit_temp.map"); GetModel()->SetGameState(GameStatePaused); return; } else if (!Engine::GUI::CheckKeyPressed(SDLK_ESCAPE)){ PopViewState(); } } if (mEditorState != EditorStateTest) { if (Engine::GUI::CheckButton (2, "Add", mEditorState == EditorStateAddEntity, 30, 20, 50, button_height)) { mEditorState = EditorStateAddEntity; Engine::LogDebug ("Editor state now Add"); return; } if (Engine::GUI::CheckButton (3, "Del", mEditorState == EditorStateDelEntity, 85, 20, 50, button_height)) { mEditorState = EditorStateDelEntity; Engine::LogDebug ("Editor state now Del"); return; } if (Engine::GUI::CheckButton (4, "Move", mEditorState == EditorStateMoveEntity, 140, 20, 65, button_height)) { mEditorState = EditorStateMoveEntity; Engine::LogDebug ("Editor state now Move"); return; } if (Engine::GUI::CheckButton (5, "Rot", mEditorState == EditorStateRotateEntity, 210, 20, 50, button_height)) { mEditorState = EditorStateRotateEntity; Engine::LogDebug ("Editor state now Move"); return; } if (Engine::GUI::CheckButton (6, "Spd", mEditorState == EditorStateEntityVelocity, 265, 20, 50, button_height)) { mEditorState = EditorStateEntityVelocity; Engine::LogDebug ("Editor state now Add"); return; } if (Engine::GUI::Button (7, "Save", 325, 20, 65, button_height)) { mEditorState = EditorStateSave; Engine::LogDebug ("Editor state now Save"); return; } if (Engine::GUI::Button (8, "Load", 400, 20, 65, button_height)) { mEditorState = EditorStateLoad; Engine::LogDebug ("Editor state now Load"); return; } // we only show the Test button when there is actually something to play // (i.e. a player entity and at least one asteroid) if (GetModel()->GetPlayerEntityId() != 0 && GetModel()->mAsteroids.size() > 0) { if (Engine::GUI::Button (9, "Test", 475, 20, 64, button_height)) { mEditorState = EditorStateTest; GetModel()->DoSaveLevel("level_edit_temp.map"); GetModel()->SetGameState(GameStateRunning); } } } std::ostringstream mouse_pos_str; vector3d mouse_world_pos; Controller* controller = GetController(); controller->GetMouseWorldPosition(mouse_world_pos); mouse_pos_str << mouse_world_pos[0] << "," << mouse_world_pos[2]; if (mEditorState == EditorStateAddEntity) { SelectFont ("console.ttf size=12"); // Engine::GUI::Label (9999, "Adding", 128, 16); if (Engine::GUI::CheckKeyPressed(MouseButtonLeft)) { // if there is no entity so far we create a player, otherwise we create // an asteroid Engine::EntityBase* entity = NULL; if (GetModel()->GetPlayerEntityId() != Engine::NullEntityId) { entity = Engine::CreateEntity(GameEntityTypeAsteroid); entity->mPhysicState->SetVelocity (vector3d (0., 0., -1.)); entity->mPhysicState->SetAngleVelocity ( (rand()/float(RAND_MAX) - 0.5) * 120); } else { entity = Engine::CreateEntity(GameEntityTypeShip); GetModel()->SetPlayerEntityId(entity->mId); entity->mPhysicState->SetOrientation (vector3d (0., 90., 0.)); } // Now we want to insert an Asteroid at the given position entity->mPhysicState->SetPosition (vector3d (mouse_world_pos[0], 0., mouse_world_pos[2])); } } if (mEditorState == EditorStateDelEntity) { SelectFont ("console.ttf size=12"); // Engine::GUI::Label (9999, "Deleting", 128, 16); if (Engine::GUI::CheckKeyPressed(MouseButtonLeft)) { // Check if there is an entity near the given position Engine::EntityBase* entity = Engine::GetEntityAt (mouse_world_pos); if (entity && entity->mType == GameEntityTypeAsteroid) { Engine::LogMessage ("Killing entity with id %u", entity->mId); GetModel()->UnregisterEntity (entity->mId); } } } if (mEditorState == EditorStateMoveEntity) { SelectFont ("console.ttf size=12"); // Engine::GUI::Label (9999, "Moving", 128, 16); if (Engine::GUI::CheckKeyPress(MouseButtonLeft)) { // Check if there is an entity near the given position Engine::EntityBase* asteroid = Engine::GetEntityAt (mouse_world_pos); if (asteroid) { mEditorEntityId = asteroid->mId; } } if (mEditorEntityId != 0) { Engine::EntityBase* asteroid = Engine::GetEntity (mEditorEntityId); asteroid->mPhysicState->SetPosition (mouse_world_pos); } if (!Engine::GUI::CheckKeyPress(MouseButtonLeft)) { if (mEditorEntityId != 0) { mEditorEntityId = 0; } } } if (mEditorState == EditorStateRotateEntity) { SelectFont ("console.ttf size=12"); // static vector3d mouse_start_rotate (0., 0., 0.); static float start_angle = 0.; if (mEditorEntityId == 0) { if (Engine::GUI::CheckKeyPress(MouseButtonLeft)) { // Check if there is an entity near the given position Engine::EntityBase* entity = Engine::GetEntityAt (mouse_world_pos); if (entity) { mEditorEntityId = entity->mId; vector3d mouse_start_rotate = mouse_world_pos - entity->mPhysicState->GetPosition(); start_angle = atan2 (mouse_start_rotate[0], mouse_start_rotate[2]) * 180 / M_PI - entity->mPhysicState->mOrientation[1]; } else { mEditorEntityId = 0; } } } if (mEditorEntityId != 0) { Engine::EntityBase* entity = Engine::GetEntity (mEditorEntityId); vector3d new_velocity = mouse_world_pos - entity->mPhysicState->GetPosition(); new_velocity[1] = 0.; float angle = atan2 (new_velocity[0], new_velocity[2]) * 180. / M_PI; entity->mPhysicState->SetOrientation (vector3d (0., angle - start_angle, 0.)); if (!Engine::GUI::CheckKeyPress(MouseButtonLeft)) { mEditorEntityId = 0; } } } if (mEditorState == EditorStateEntityVelocity) { SelectFont ("console.ttf size=12"); // Engine::GUI::Label (9999, "Velocity", 128, 16); if (mEditorEntityId == 0) { if (Engine::GUI::CheckKeyPress(MouseButtonLeft)) { // Check if there is an entity near the given position Engine::EntityBase* asteroid = Engine::GetEntityAt (mouse_world_pos); if (asteroid) { mEditorEntityId = asteroid->mId; } } } if (mEditorEntityId != 0) { Engine::EntityBase* asteroid = Engine::GetEntity (mEditorEntityId); vector3d new_velocity = mouse_world_pos - asteroid->mPhysicState->GetPosition(); new_velocity[1] = 0.; asteroid->mPhysicState->SetVelocity (new_velocity); if (!Engine::GUI::CheckKeyPress(MouseButtonLeft)) { if (mEditorEntityId != 0) { mEditorEntityId = 0; } } } } if (mEditorState == EditorStateSave) { glColor3f (0.2, 0.2, 0.2); Engine::GUI::DrawRoundedBlock (140, 150, screen_right - 280, 280); // Engine::GUI::Label (9999, "Saving", 128, 16); SelectFont ("console.ttf size=23"); Engine::GUI::Label(51, "Filename: ", 145, 180); std::string level_name = GetModel()->GetLevelName(); glColor3f (1., 1., 1.); if (Engine::GUI::LineEdit(52, 150, 200, level_name, 31)) GetModel()->SetLevelName(level_name); Engine::GUI::Label(53, "Author: ", 145, 250); std::string level_author = GetModel()->GetLevelAuthor(); if (Engine::GUI::LineEdit(531, 150, 270, level_author, 31)) GetModel()->SetLevelAuthor(level_author); Engine::GUI::Label(54, "Level Title: ", 145, 320); std::string level_title = GetModel()->GetLevelTitle(); if (Engine::GUI::LineEdit(541, 150, 340, level_title, 31)) GetModel()->SetLevelTitle(level_title); if (Engine::GUI::Button (55, "Save", 145, 380, button_width, button_height)) { GetModel()->DoSaveLevel((level_name + std::string(".map")).c_str()); Engine::LogMessage ("Save"); mEditorState = EditorStateUnknown; } if (Engine::GUI::Button (56, "Cancel", screen_right - 140 - 5 - button_width, 380, button_width, button_height)) mEditorState = EditorStateUnknown; } if (mEditorState == EditorStateLoad) { glColor3f (0.2, 0.2, 0.2); Engine::GUI::DrawRoundedBlock (140, 150, screen_right - 280, 200); // Engine::GUI::Label (9999, "Loading", 128, 16); SelectFont ("console.ttf size=23"); Engine::GUI::Label(51, "Filename: ", 145, 180); std::string level_name = GetModel()->GetLevelName(); glColor3f (1., 1., 1.); if (Engine::GUI::LineEdit(52, 145, 210, level_name, 32)) GetModel()->SetLevelName(level_name); if (Engine::FileExists (level_name + std::string(".map"))) { if (Engine::GUI::Button (54, "Load", 145, 300, button_width, button_height)) { GetModel()->DoLoadLevel((level_name + std::string(".map")).c_str()); Engine::LogMessage ("Load"); mEditorState = EditorStateUnknown; } } if (Engine::GUI::Button (55, "Cancel", screen_right - 140 - 5 - button_width, 300, button_width, button_height)) mEditorState = EditorStateUnknown; } if (Engine::GUI::CheckKeyPressed(SDLK_ESCAPE)) { if (mEditorState != EditorStateUnknown) mEditorState = EditorStateUnknown; } if (Engine::GUI::CheckKeyPressed(MouseButtonRight) || Engine::GUI::CheckKeyPressed(SDLK_ESCAPE) ) { mEditorState = EditorStateUnknown; } } /* * Entities */ void View::DrawEntity (Engine::EntityBase *entity) { if (entity->mType == GameEntityTypeAsteroid) DrawAsteroid ((AsteroidEntity*) entity); else if (entity->mType == GameEntityTypeShip) DrawShip ((ShipEntity*) entity); else if (entity->mType == GameEntityTypeRocket) DrawRocket ((RocketEntity*) entity); else if (entity->mType == GameEntityTypeShipPart) DrawShipPart (entity); else { Engine::LogError ("Cannot draw entity: unknown type '%d'", entity->mType); } } /// \todo: Update of the animation ?? void View::DrawShip (ShipEntity *ship) { if (!ship->mAlive) return; mShipSprite.SetScale (2. * ship->mPhysicState->mRadius / mShipSprite.GetHeight()); mShipThrustSprite.SetScale (2. * ship->mPhysicState->mRadius / mShipSprite.GetHeight()); if (ship->mState == ShipEntity::Accelerating) { mShipThrustSprite.UpdateAnimation (Engine::GetFrameDuration()); mShipThrustSprite.DrawAt(-0.5, 0., 0.); } mShipSprite.DrawAt(0., 0., 0.); #ifdef DRAW_BOUNDARIES glColor3f (1., 1., 1.); DrawCircle (ship->mPhysicState->mRadius, 20); #endif } void View::DrawAsteroid (AsteroidEntity *asteroid) { mAsteroidSprite.SetScale (2. * asteroid->mPhysicState->mRadius / mAsteroidSprite.GetWidth()); mAsteroidSprite.DrawAt(0., 0., 0.); #ifdef DRAW_BOUNDARIES glColor3f (1., 1., 1.); DrawCircle (asteroid->mPhysicState->mRadius, 20); #endif } void View::DrawRocket (RocketEntity *rocket) { glColor3f (1., 1., 1.); glBegin (GL_QUADS); glVertex3f (-0.25, 0., 0.05); glVertex3f (0.05, 0., 0.05); glVertex3f (0.05, 0., -0.05); glVertex3f (-0.25, 0., -0.05); glEnd (); } void View::DrawShipPart (Engine::EntityBase *entity) { unsigned int i; mShipPartsSprite.SetScale (1. / mShipSprite.GetHeight()); for (i = 0; i < mShipPartsEntityIds.size(); i++) { if (mShipPartsEntityIds.at(i) == entity->mId) { mShipPartsSprite.DrawSubAt (i, 0., 0., 0.); } } #ifdef DRAW_BOUNDARIES glColor3f (1., 1., 1.); DrawCircle (entity->mPhysicState->mRadius, 20); #endif } }