Advertisement
kurozael

Spaceship Class

Feb 15th, 2012
270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.44 KB | None | 0 0
  1. /*
  2.     Written by kurozael (kurozael@gmail.com), do with it
  3.     as you please :)
  4. */
  5.  
  6. #include <Engine/States/PlayState.h>
  7. #include <Engine/Entities/Spaceship.h>
  8. #include <Engine/System/Timer.h>
  9. #include <Engine/System/Entities.h>
  10. #include <Engine/System/Events.h>
  11. #include <Engine/System/Asset.h>
  12. #include <Engine/System/Utility.h>
  13. #include <Engine/Graphics/Render.h>
  14. #include <Engine/Game.h>
  15.  
  16. namespace en
  17. {
  18.     float Spaceship::EnterAtmosphere(Planet* planet)
  19.     {
  20.         Vector3f& planetPos = planet->GetPos();
  21.         float distance = planetPos.Distance(m_position);
  22.         float pullSize = planet->GetSize() + (1.0f + planet->GetGravPull());
  23.  
  24.         if (distance <= pullSize * 2.0f)
  25.         {
  26.             if (m_atmosphere == NULL || (distance < planetPos.Distance(m_atmosphere->GetPos())))
  27.                 m_atmosphere = planet;
  28.         }
  29.  
  30.         return distance;
  31.     }
  32.  
  33.     void Spaceship::SetDashTime(float dashTime)
  34.     {
  35.         m_dashTime = Timer::CurTime() + dashTime;
  36.     }
  37.  
  38.     void Spaceship::SetMessage(const std::string& message)
  39.     {
  40.         m_fadeMessageTime = Timer::CurTime() + 3.0f;
  41.         m_message = message;
  42.     }
  43.  
  44.     void Spaceship::OnCollide(Planet* planet)
  45.     {
  46.         if (m_fuel < 20.0f)
  47.             g_Awards->Earn("Close One");
  48.  
  49.         SetPlanet(planet);
  50.         SetVelocity(Vector3f(0, 0, 0));
  51.  
  52.         g_PlayState->AddScore(
  53.             std::ceil((4.0f - planet->GetSize()) * 100.0f));
  54.  
  55.         m_landCount++;
  56.  
  57.         if (m_landCount == 1)
  58.         {
  59.             g_PlayState->SetNewPlanet();
  60.             m_landCount = 0;
  61.         }
  62.     }
  63.  
  64.     void Spaceship::CheckSkip(Planet* planet)
  65.     {
  66.         Entity* nextPlanet = (Planet*)g_Entities->GetNext(m_planet, "Planet");
  67.         float skipBonus = g_Config->GetFloat("SkipPlanetBonus", 300.0f);
  68.  
  69.         if (nextPlanet != NULL && planet != nextPlanet)
  70.         {
  71.             g_PlayState->AddScore(skipBonus, true);
  72.             g_Awards->Earn("Skip Planet");
  73.             SetMessage("Skip! +" + Math::ToString(skipBonus));
  74.         }
  75.     }
  76.  
  77.     void Spaceship::SetPlanet(Planet* planet)
  78.     {
  79.         if (m_fuel < 1.0f)
  80.             return;
  81.  
  82.         Vector3f& position = planet->GetPos();
  83.         Vector3f direction = position - m_position;
  84.         float angle = std::atan2(direction.z, -direction.x);
  85.  
  86.         // Only play the impact sound if we hopped onto it! Durr.
  87.         if (m_planet != NULL && m_planet != planet)
  88.         {
  89.             g_Audio->PlaySound("impact.wav");
  90.             CheckSkip(planet);
  91.         }
  92.  
  93.         m_gravity.Reset();
  94.         m_gasSound->Stop();
  95.         m_orbit = angle;
  96.         m_planet = planet;
  97.         m_fuel = 100.0f;
  98.     }
  99.  
  100.     Planet* Spaceship::GetPlanet()
  101.     {
  102.         return m_planet;
  103.     }
  104.  
  105.     void Spaceship::OnEvent(sf::Event& event)
  106.     {
  107.         if (event.Type == sf::Event::KeyReleased && event.Key.Code == sf::Keyboard::Space
  108.             && !IsMoving() && !m_exploded)
  109.             Jump();
  110.     }
  111.  
  112.     void Spaceship::OnUpdate()
  113.     {
  114.         if (m_planet != NULL && !IsMoving() && !m_exploded)
  115.         {
  116.             Vector3f& position = m_planet->GetPos();
  117.             Vector3f direction = position - m_position;
  118.             float orbitSpeed = m_planet->GetSpinSpeed() * 0.04;
  119.             float angle = std::atan2(direction.z, -direction.x);
  120.             float size = m_planet->GetSize() + 1.0f;
  121.             angle = (angle * 180.f) / M_PI;
  122.  
  123.             m_position.x = position.x + std::cos(m_orbit) * size;
  124.             m_position.z = position.z - std::sin(m_orbit) * size;
  125.             m_position.y = 0.2f;
  126.             m_angle.y = angle;
  127.  
  128.             bool bIsClockwise = m_planet->IsClockwise();
  129.  
  130.             if (sf::Keyboard::IsKeyPressed(sf::Keyboard::LShift)
  131.                 || sf::Keyboard::IsKeyPressed(sf::Keyboard::RShift))
  132.             {
  133.                 bIsClockwise = !bIsClockwise;
  134.                 orbitSpeed *= 0.5f;
  135.             }
  136.            
  137.             if (bIsClockwise)
  138.                 m_orbit -= (Timer::GetDT() * orbitSpeed);
  139.             else
  140.                 m_orbit += (Timer::GetDT() * orbitSpeed);
  141.         }
  142.         else if (!m_exploded)
  143.         {
  144.             // Are we currently within a planet's atmosphere?
  145.             if (m_atmosphere != NULL)
  146.             {
  147.                 Vector3f planetPos = m_atmosphere->GetPos();
  148.                 Vector3f direction = planetPos - m_position;
  149.                 float distance = planetPos.Distance(m_position);
  150.                 float pullSize = m_atmosphere->GetSize() + (1.0f + m_atmosphere->GetGravPull());
  151.  
  152.                 float angle = std::atan2(direction.z, -direction.x);
  153.                 angle = angle * (180.f / M_PI);
  154.  
  155.                 if (distance <= pullSize)
  156.                     m_gravity = direction * 0.6f;
  157.                 else
  158.                     m_gravity = direction * 0.2f;
  159.            
  160.                 m_angle.y = Math::DegApproach(
  161.                     m_angle.y, angle, Timer::GetDT() * 360.0f
  162.                 );
  163.  
  164.                 m_atmosphere = NULL;
  165.             };
  166.  
  167.             /*
  168.                 Here we give the ability for the player to do a short 'halt'
  169.                 in space. This is useful to dodge asteroids, but limits their
  170.                 speed and still reduces their fuel!
  171.             */
  172.  
  173.             if (sf::Keyboard::IsKeyPressed(sf::Keyboard::LShift)
  174.                 || sf::Keyboard::IsKeyPressed(sf::Keyboard::RShift))
  175.             {
  176.                 SetVelocity(m_velocity.NormalCopy() * 4.0f);
  177.             }
  178.             else
  179.             {
  180.                 SetVelocity(m_velocity.NormalCopy() * GetSpeed());
  181.             }
  182.  
  183.             /*
  184.                 Change the volume based on our fuel,
  185.                 but not too frequently because SFML doesn't
  186.                 like it! Silly SFML!
  187.             */
  188.             if (Timer::CurTime() >= m_nextVolumeTime)
  189.             {
  190.                 m_nextVolumeTime = Timer::CurTime() + 0.5f;
  191.                 m_gasSound->SetVolume(
  192.                     Math::Clamp(m_fuel, 0.0f, 100.0f)
  193.                 );
  194.             }
  195.  
  196.             m_position = m_position + (m_gravity * Timer::GetDT());
  197.             m_gravity *= 0.6f;
  198.  
  199.             float fuelLossAmount = g_Config->GetFloat("FuelLossAmount") * Timer::GetDT();
  200.             PropPhysics::OnUpdate();
  201.  
  202.             if (m_position.z > 30.0f || m_position.z < -30.0f)
  203.                 Kill();
  204.  
  205.             if (m_fuel > 0.0f)
  206.                 m_fuel = std::max<float>(m_fuel - fuelLossAmount, 0);
  207.             else
  208.                 Kill();
  209.  
  210.             FireTrail();
  211.         }
  212.  
  213.         if (m_nextRespawn > 0.0f && Timer::CurTime() >= m_nextRespawn)
  214.             Respawn();
  215.  
  216.         m_emitter->Update();
  217.     }
  218.  
  219.     float Spaceship::GetSpeed()
  220.     {
  221.         if (m_dashTime > 0.0f && Timer::CurTime() < m_dashTime)
  222.             return 12.0f;
  223.         else
  224.             return 9.0f;
  225.     }
  226.  
  227.     void Spaceship::Kill()
  228.     {
  229.         if (!m_exploded)
  230.             Explode();
  231.     }
  232.  
  233.     void Spaceship::Respawn()
  234.     {
  235.         g_PlayState->GetCamera()->SetTarget(
  236.             m_planet->GetPos(), true
  237.         );
  238.  
  239.         Vector3f& sunPos = g_PlayState->GetTheSun()->GetPos();
  240.         sunPos.x = m_planet->GetPos().x - 28.0f;
  241.  
  242.         g_Audio->PlaySound("impact.wav");
  243.         m_nextRespawn = 0.0f;
  244.         m_gasSound->Stop();
  245.         m_velocity.Reset();
  246.         m_exploded = false;
  247.         m_fuel = 100.0f;
  248.         m_lives--;
  249.  
  250.         if (m_lives == 0)
  251.             g_PlayState->Lose();
  252.  
  253.         g_Game->DoFlash(0.2f, "hazard.wav");
  254.     }
  255.  
  256.     void Spaceship::Explode()
  257.     {
  258.  
  259.         m_emitter->ExplodeFX(m_position, 18, 60);
  260.         m_emitter->ShockwaveFX(m_position, 10, 60);
  261.  
  262.         /*
  263.             Ground control to major Tom, your circuits dead, there's something wrong
  264.             Can you hear me, major Tom?
  265.             Can you hear me, major Tom?
  266.             Can you hear me, major Tom?
  267.             Can you...
  268.             Uh... Houston, we have a problem...
  269.         */
  270.         m_nextRespawn = Timer::CurTime() + 1.0f;
  271.         m_gasSound->Stop();
  272.         m_exploded = true;
  273.  
  274.         // Lose points for the failure!
  275.         float loseLifePenalty = g_Config->GetInt("LoseLifePenalty", 100);
  276.             SetMessage("Boom! -" + Math::ToString(loseLifePenalty));
  277.         g_PlayState->TakeScore(loseLifePenalty);
  278.  
  279.         // BOOOOOOOOOOOOOOOOOOOOOOOOOOOM!
  280.         m_explosion->Play();
  281.     }
  282.  
  283.     void Spaceship::FireTrail()
  284.     {
  285.         Vector3f shipDir = m_angle.Direction();
  286.         float velLength = m_velocity.Length();
  287.         int particles = velLength * 0.3f;
  288.  
  289.         // Don't bother if we aren't moving much!
  290.         if (velLength <= 1.5f) return;
  291.  
  292.         for (int i = 0; i < particles; i++)
  293.         {
  294.             std::string texture = "textures/particles/dust1.png";
  295.             Vector3f velocity = shipDir * -velLength;
  296.             float startSize = Math::Random(0.4f, 1.2f);
  297.             float endSize = Math::Random(0.0f, 0.4f);
  298.             float randAlpha = Math::Random(0.4f, 1.0f);
  299.             float randGrey = Math::Random(0.2f, 0.8f);
  300.             float dieTime = Math::Random(0.8, 1.6f);
  301.             Color color = Color(randGrey, randGrey, randGrey, randAlpha);
  302.  
  303.             if (i >= particles * 0.5f)
  304.             {
  305.                 texture = "textures/particles/dust2.png";
  306.                 startSize = Math::Random(0.8f, 1.8f);
  307.                 endSize = Math::Random(0.3f, 0.6f);
  308.                 dieTime = Math::Random(0.4f, 1.2f);
  309.                 color = Color(Math::Random(0.2f, 1.0f), Math::Random(0.0f, 0.2f), 0.0f, randAlpha);
  310.             }
  311.  
  312.             pParticle particle = m_emitter->New();
  313.                 particle->SetPos(m_position - (shipDir * 0.9f));
  314.                 particle->SetColor(color);
  315.                 particle->SetDieTime(dieTime);
  316.                 particle->SetStartSize(startSize);
  317.                 particle->SetTexture(texture);
  318.                 particle->SetEndSize(endSize);
  319.                 particle->SetVelocity(velocity);
  320.                 particle->SetAirResistance(0.1f);
  321.             m_emitter->Add(particle);
  322.         }
  323.     }
  324.  
  325.     bool Spaceship::IsMoving()
  326.     {
  327.         return m_velocity.SquaredLength() > 0.0f;
  328.     }
  329.  
  330.     int Spaceship::GetLives()
  331.     {
  332.         return m_lives;
  333.     }
  334.    
  335.     void Spaceship::OnDraw()
  336.     {
  337.         // See if we're not respawning!
  338.         if (m_nextRespawn == 0.0f)
  339.         {
  340.             Color& color = m_planet->GetColor();
  341.  
  342.             m_color.r = Math::Approach(m_color.r, color.r + 0.25f, Timer::GetDT() * 0.1f);
  343.             m_color.g = Math::Approach(m_color.g, color.g + 0.25f, Timer::GetDT() * 0.1f);
  344.             m_color.b = Math::Approach(m_color.b, color.b + 0.25f, Timer::GetDT() * 0.1f);
  345.  
  346.             glPushMatrix();
  347.                 glTranslatef(m_position.x, m_position.y, m_position.z);
  348.                 glColor4f(m_color.r, m_color.g, m_color.b, 0.4f);
  349.                 m_billboard.Draw(Vector3f(0.0f, 0.0f, 0.0f), 10.0f);
  350.                 m_angle.Set();
  351.                 glColor4f(1, 1, 1, 1);
  352.                 glRotatef(180, 0, 1, 0);
  353.                 glScalef(0.07, 0.07, 0.07);
  354.                 m_model->Draw();
  355.             glPopMatrix();
  356.         }
  357.  
  358.         Pointf screenPos = Render::ToScreen(m_position);
  359.  
  360.         if (m_fadeMessageTime != 0.0f)
  361.         {
  362.             float timeLeft = Math::Clamp(m_fadeMessageTime - Timer::CurTime(), 0.0f, 3.0f);
  363.             Color color = Color(1.0f, 1.0f, 1.0f, (1.0f / 3.0f) * timeLeft);
  364.  
  365.             Render::Start2D();
  366.                 Render::Text::SetFont(g_Config->GetString("GameFont"));
  367.                 Render::Text::SetHeight(20.0f);
  368.                 Render::Text::Draw2D(
  369.                     screenPos.x, screenPos.y + 32.0f + (48.0f - ((48.0f / 3.0f) * timeLeft)), m_message, color, true
  370.                     );
  371.             Render::End2D();
  372.  
  373.             if (timeLeft == 0.0f)
  374.             {
  375.                 m_fadeMessageTime = 0.0f;
  376.                 m_message.clear();
  377.             }
  378.         }
  379.  
  380.         if (m_nextRespawn == 0.0f)
  381.         {
  382.             // Don't display the fuel bar if we're orbiting!
  383.             if (!IsMoving())
  384.                 return;
  385.  
  386.             // Position the fuel bar above the spaceship.
  387.             screenPos.y -= 64.0f;
  388.  
  389.             Render::Start2D();
  390.                 Render::Screen::Quad(screenPos.x, screenPos.y, 64, 6, Color(1, 0.2, 0.2, 1));
  391.                 Render::Screen::Quad(screenPos.x, screenPos.y, (64.0f / 100.0f) * m_fuel, 6, Color(0, 1, 0, 1));
  392.                
  393.                 Render::Text::SetFont(g_Config->GetString("GameFont"));
  394.                 Render::Text::SetHeight(20.0f);
  395.                 Render::Text::Draw2D(screenPos.x, screenPos.y + 8, "FUEL: " + Math::ToString(std::ceil(m_fuel)));
  396.             Render::End2D();
  397.         }
  398.  
  399.         m_emitter->Draw();
  400.     }
  401.  
  402.     float Spaceship::GetFuel()
  403.     {
  404.         return m_fuel;
  405.     }
  406.  
  407.     void Spaceship::Remove()
  408.     {
  409.         g_Entities->Remove(this);
  410.     }
  411.  
  412.     void Spaceship::Jump()
  413.     {
  414.         if (m_angle.y <= 90 && m_angle.y >= -90)
  415.         {
  416.             if (Math::Random(0.0f, 1.0f) < 0.1f)
  417.                 g_PlayState->MakeAsteroid();
  418.  
  419.             SetVelocity(m_angle.Direction() * GetSpeed());
  420.             m_gasSound->Play();
  421.             m_planet->Impact();
  422.         }
  423.     }
  424.  
  425.     Spaceship::Spaceship()
  426.     {
  427.         m_billboard.SetTexture("textures/particle.png");
  428.         m_billboard.DisableLighting();
  429.         m_emitter.reset(new Emitter);
  430.         m_emitter->Clear();
  431.  
  432.         g_Entities->Add(this);
  433.         g_Events->Add(this);
  434.        
  435.         m_explosion = g_Audio->GetSound("explosion.ogg");
  436.         m_gasSound = g_Audio->GetSound("cannister_loop.wav");
  437.         m_gasSound->SetLoop(true);
  438.         g_Audio->LoadSound("impact.wav");
  439.  
  440.         m_nextVolumeTime = 0.0f;
  441.         m_nextRespawn = 0.0f;
  442.         m_exploded = false;
  443.         m_atmosphere = NULL;
  444.         m_landCount = 0;
  445.         m_dashTime = 0.0f;
  446.         m_planet = NULL;
  447.         m_lives = g_Config->GetInt("StartLives", 2);
  448.         m_model = new StaticModel;
  449.         m_model->Load("meshes/SpaceFrigate/SpaceFrigate.3ds");
  450.         m_fuel = 100.0f;
  451.     }
  452.  
  453.     Spaceship::~Spaceship()
  454.     {
  455.         g_Events->Remove(this);
  456.         delete m_model;
  457.     }
  458. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement