#include "View.h" #include "CameraBase.h" #include "UserInterface.h" #include "SimpleConsoleOverlay.h" #include "Engine.h" #include "Physics.h" #include "Model.h" #include "EventsBase.h" #include "ShipEntity.h" #include "AsteroidEntity.h" #include "AsteroidsEvents.h" #include "RocketEntity.h" #include // #define DRAW_BOUNDARIES #ifdef DRAW_BOUNDARIES #include "coll2d.h" #include "DrawingsGL.h" #endif using namespace std; namespace asteroids { int View::OnInit (int argc, char* argv[]) { ViewBase::OnInit (argc, argv); // We want menu Engine::OverlayBasePtr menu_overlay (new MainMenuOverlay); Engine::OverlayBasePtr game_running_overlay (new GameRunningOverlay); Engine::OverlayBasePtr game_over_overlay (new GameOverOverlay); Engine::OverlayBasePtr level_complete_overlay (new LevelCompleteOverlay); Engine::OverlayBasePtr game_paused_overlay (new GamePausedOverlay); Engine::OverlayBasePtr player_died_overlay (new PlayerDiedOverlay); Engine::OverlayBasePtr highscore_overlay (new HighscoreOverlay); mOverlayManager.Register (menu_overlay, GameStateMainMenu); mOverlayManager.Register (game_running_overlay, GameStateRunning); mOverlayManager.Register (level_complete_overlay, GameStateLevelComplete); mOverlayManager.Register (game_over_overlay, GameStateGameOver); mOverlayManager.Register (player_died_overlay, GameStatePlayerDied); mOverlayManager.Register (game_paused_overlay, GameStatePaused); mOverlayManager.Register (highscore_overlay, GameStateShowHighscore); mOverlayManager.InitOverlays(); /* // 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); */ // 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); star.position[1] = rand() / float(RAND_MAX); star.position[2] = rand() / float(RAND_MAX); mBackgroundStars.push_back (star); } mAsteroidSprite.LoadFromPNG ("./data/textures/asteroid.png"); mShipSprite.LoadFromPNG ("./data/textures/ship.png"); mShipThrustSprite.LoadFromPNG ("./data/textures/ship_thrust.png"); mShipThrustSprite.SetAnimation (4, 8); mShipPartsSprite.LoadFromPNG ("./data/textures/ship_parts.png"); mShipPartsSprite.SetSubSpriteCount (10); mAccelerateEventHandler = new AccelerateEventHandler (this); Engine::RegisterListener (mAccelerateEventHandler, EventAccelerateStart); Engine::RegisterListener (mAccelerateEventHandler, EventAccelerateStop); mShipExplodeEventHandler = new ShipExplodeEventHandler (this); Engine::RegisterListener (mShipExplodeEventHandler, EventShipExplode); return 0; } void View::OnDestroy() { delete mAccelerateEventHandler; delete mShipExplodeEventHandler; mBackgroundStars.clear(); mShipPartsEntityIds.clear(); Engine::ViewBase::OnDestroy(); } /* * Event Handlers */ bool View::AccelerateEventHandler::HandleEvent (const Engine::EventBasePtr &event) const { if (event->mEventType == EventAccelerateStart) mView->mShipThrustSprite.ResetAnimation(); Engine::LogDebug ("Received Acceleration Event: %d", event->mEventType); return true; } bool View::ShipExplodeEventHandler::HandleEvent (const Engine::EventBasePtr &event) const { if (event->mEventType == EventShipExplode) { 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; unsigned int i; mView->mShipPartsEntityIds.clear(); for (i = 0; i < mView->mShipPartsSprite.GetSubSpriteCount(); i++) { Engine::EntityBase* part_sprite_particle = Engine::CreateEntity (GameEntityTypeShipPart); part_sprite_particle->mPhysicState->mPosition = position; part_sprite_particle->mPhysicState->mOrientation = orientation; part_sprite_particle->mPhysicState->mVelocity = velocity; part_sprite_particle->mPhysicState->mVelocity = vector3d (velocity[0] * (rand()/float(RAND_MAX)) * 1.7, 0., velocity[2] * (rand()/float(RAND_MAX)) * 1.5); part_sprite_particle->mPhysicState->mAngleVelocity = (rand()/float(RAND_MAX) - 0.5 ) * 100.; mView->mShipPartsEntityIds.push_back(part_sprite_particle->mId); } } Engine::LogDebug ("Received Ship Explode Event: %d", event->mEventType); return true; } /* * 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.); if (mBackgroundStars.at(i).position[0] < 0.) mBackgroundStars.at(i).position[0] += 1.; if (mBackgroundStars.at(i).position[0] >= 1.) mBackgroundStars.at(i).position[0] -= 1.; } glEnd(); glPopMatrix(); } void View::DrawWorld() { std::map::iterator entity_iterator; Model *game_model = static_cast (mModel); DrawStars (); if ( game_model->GetGameState() != GameStateRunning) { return; } 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(); // 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 (); } } } 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 } }