Fade out and pause music on death and resume on restart of level, fixes #1064
[supertux.git] / src / object / player.cpp
index ef5b489..93c1094 100644 (file)
@@ -185,7 +185,7 @@ Player::Player(PlayerStatus* _player_status, const std::string& name_) :
   SoundManager::current()->preload("sounds/skid.wav");
   SoundManager::current()->preload("sounds/flip.wav");
   SoundManager::current()->preload("sounds/invincible_start.ogg");
-  SoundManager::current()->preload("sounds/splash.ogg");
+  SoundManager::current()->preload("sounds/splash.wav");
 
   init();
 }
@@ -224,6 +224,8 @@ Player::init()
   backflipping = false;
   backflip_direction = 0;
   sprite->set_angle(0.0f);
+  powersprite->set_angle(0.0f);
+  lightsprite->set_angle(0.0f);
   visible = true;
   ability_time = 0;
   stone = false;
@@ -338,6 +340,8 @@ Player::trigger_sequence(std::string sequence_name)
   backflipping = false;
   backflip_direction = 0;
   sprite->set_angle(0.0f);
+  powersprite->set_angle(0.0f);
+  lightsprite->set_angle(0.0f);
   GameSession::current()->start_sequence(sequence_name);
 }
 
@@ -388,6 +392,11 @@ Player::update(float elapsed_time)
     if (backflip_timer.started()) physic.set_velocity_x(100 * backflip_direction);
     //rotate sprite during flip
     sprite->set_angle(sprite->get_angle() + (dir==LEFT?1:-1) * elapsed_time * (360.0f / 0.5f));
+    if (player_status->bonus == EARTH_BONUS || player_status->bonus == AIR_BONUS) {
+      powersprite->set_angle(sprite->get_angle());
+      if (player_status->bonus == EARTH_BONUS)
+        lightsprite->set_angle(sprite->get_angle());
+    }
   }
 
   // set fall mode...
@@ -407,7 +416,12 @@ Player::update(float elapsed_time)
     if (backflipping && (backflip_timer.get_timegone() > 0.15f)) {
       backflipping = false;
       backflip_direction = 0;
-      sprite->set_angle(0.0f);
+      physic.set_velocity_x(0);
+      if (!stone) {
+        sprite->set_angle(0.0f);
+        powersprite->set_angle(0.0f);
+        lightsprite->set_angle(0.0f);
+      }
 
       // if controls are currently deactivated, we take care of standing up ourselves
       if (deactivated)
@@ -570,10 +584,9 @@ Player::handle_horizontal_input()
       // dust some particles
       Sector::current()->add_object(
         std::make_shared<Particles>(
-          Vector(dir == RIGHT ? get_bbox().p2.x : get_bbox().p1.x, get_bbox().p2.y),
-          dir == RIGHT ? 270+20 : 90-40, dir == RIGHT ? 270+40 : 90-20,
-          Vector(280, -260), Vector(0, 300), 3, Color(.4f, .4f, .4f), 3, .8f,
-          LAYER_OBJECTS+1));
+          Vector(dir == LEFT ? get_bbox().p2.x : get_bbox().p1.x, get_bbox().p2.y),
+          dir == LEFT ? 50 : -70, dir == LEFT ? 70 : -50, 260, 280,
+          Vector(0, 300), 3, Color(.4f, .4f, .4f), 3, .8f, LAYER_OBJECTS+1));
 
       ax *= 2.5;
     } else {
@@ -634,6 +647,8 @@ Player::do_standup() {
     return;
   if (backflipping)
     return;
+  if (stone)
+    return;
 
   if (adjust_height(BIG_TUX_HEIGHT)) {
     duck = false;
@@ -850,6 +865,7 @@ Player::handle_input()
   if (controller->pressed(Controller::DOWN) && player_status->bonus == EARTH_BONUS && !cooldown_timer.started()) {
     if (controller->hold(Controller::ACTION) && !ability_timer.started()) {
       ability_timer.start(player_status->max_earth_time * STONE_TIME_PER_FLOWER);
+      powersprite->stop_animation();
       stone = true;
       physic.set_gravity_modifier(1.0f); // Undo jump_early_apex
     }
@@ -862,6 +878,9 @@ Player::handle_input()
   if (stone && (!controller->hold(Controller::ACTION) || ability_timer.get_timeleft() <= 0.5f)) {
     cooldown_timer.start(ability_timer.get_timegone()/2.0f); //The longer stone form is used, the longer until it can be used again
     ability_timer.stop();
+    sprite->set_angle(0.0f);
+    powersprite->set_angle(0.0f);
+    lightsprite->set_angle(0.0f);
     stone = false;
     for (int i = 0; i < 8; i++)
     {
@@ -918,6 +937,8 @@ Player::handle_input()
     backflipping = false;
     backflip_direction = 0;
     sprite->set_angle(0.0f);
+    powersprite->set_angle(0.0f);
+    lightsprite->set_angle(0.0f);
   }
 }
 
@@ -961,8 +982,6 @@ Player::try_grab()
       // make sure the Portable is a MovingObject
       MovingObject* moving_object = dynamic_cast<MovingObject*> (portable);
       assert(moving_object);
-      if(moving_object == NULL)
-        continue;
 
       // make sure the Portable isn't currently non-solid
       if(moving_object->get_group() == COLGROUP_DISABLED) continue;
@@ -1052,7 +1071,7 @@ Player::add_bonus(BonusType type, bool animate)
 
   // ignore GROWUP_BONUS if we're already big
   if (type == GROWUP_BONUS) {
-    if (!player_status->bonus == NO_BONUS)
+    if (player_status->bonus != NO_BONUS)
       return true;
   }
 
@@ -1175,7 +1194,7 @@ Player::draw(DrawingContext& context)
   else if (player_status->bonus == ICE_BONUS)
     sa_prefix = "ice";
   else if (player_status->bonus == AIR_BONUS)
-    sa_prefix = "ice";
+    sa_prefix = "air";
   else if (player_status->bonus == EARTH_BONUS)
     sa_prefix = "earth";
   else
@@ -1256,7 +1275,8 @@ Player::draw(DrawingContext& context)
   if (player_status->bonus == EARTH_BONUS) {
     powersprite->set_action(sprite->get_action());
     lightsprite->set_action(sprite->get_action());
-  }
+  } else if (player_status->bonus == AIR_BONUS)
+    powersprite->set_action(sprite->get_action());
 
   /*
   // Tux is holding something
@@ -1276,11 +1296,11 @@ Player::draw(DrawingContext& context)
     Vector shake_delta = (stone && ability_timer.get_timeleft() < 1.0f) ? Vector(graphicsRandom.rand(-3,3), 0) : Vector(0,0);
     sprite->draw(context, get_pos() + shake_delta, LAYER_OBJECTS + 1);
     // draw hardhat
-    powersprite->draw(context, get_pos(), LAYER_OBJECTS + 1);
+    powersprite->draw(context, get_pos() + shake_delta, LAYER_OBJECTS + 1);
     // light
     context.push_target();
     context.set_target(DrawingContext::LIGHTMAP);
-    lightsprite->draw(context, get_pos()/* + Vector(dir==LEFT ? 0 : 32, 0)*/, 0);
+    lightsprite->draw(context, get_pos(), 0);
     context.pop_target();
     // give an indicator that stone form cannot be used for a while
     if (cooldown_timer.started() && graphicsRandom.rand(0, 4) == 0) {
@@ -1292,8 +1312,15 @@ Player::draw(DrawingContext& context)
         ppos, ANCHOR_MIDDLE, Vector(0, 0), Vector(0, 0), LAYER_OBJECTS+1+5));
     }
   }
-  else
-    sprite->draw(context, get_pos(), LAYER_OBJECTS + 1);
+  else {
+    if(dying)
+      sprite->draw(context, get_pos(), Sector::current()->get_foremost_layer() + 1);
+    else
+      sprite->draw(context, get_pos(), LAYER_OBJECTS + 1);
+
+    if (player_status->bonus == AIR_BONUS)
+      powersprite->draw(context, get_pos(), LAYER_OBJECTS + 1);
+  }
 
 }
 
@@ -1314,7 +1341,7 @@ Player::collision_tile(uint32_t tile_attributes)
     if( tile_attributes & Tile::WATER ){
       swimming = true;
       no_water = false;
-      SoundManager::current()->play( "sounds/splash.ogg" );
+      SoundManager::current()->play( "sounds/splash.wav" );
     }
   }
 #endif
@@ -1342,14 +1369,12 @@ Player::collision_solid(const CollisionHit& hit)
       on_ground_flag = false;
       Sector::current()->add_object(std::make_shared<Particles>(
                                       Vector(get_bbox().p2.x, get_bbox().p2.y),
-                                      270+20, 270+40,
-                                      Vector(280, -260), Vector(0, 300), 3, Color(.4f, .4f, .4f), 3, .8f,
-                                      LAYER_OBJECTS+1));
+                                      50, 70, 260, 280, Vector(0, 300), 3,
+                                      Color(.4f, .4f, .4f), 3, .8f, LAYER_OBJECTS+1));
       Sector::current()->add_object(std::make_shared<Particles>(
                                       Vector(get_bbox().p1.x, get_bbox().p2.y),
-                                      90-40, 90-20,
-                                      Vector(280, -260), Vector(0, 300), 3, Color(.4f, .4f, .4f), 3, .8f,
-                                      LAYER_OBJECTS+1));
+                                      -70, -50, 260, 280, Vector(0, 300), 3,
+                                      Color(.4f, .4f, .4f), 3, .8f, LAYER_OBJECTS+1));
       Sector::current()->camera->shake(.1f, 0, 5);
     }
 
@@ -1438,6 +1463,8 @@ Player::kill(bool completely)
   physic.set_velocity_x(0);
 
   sprite->set_angle(0.0f);
+  powersprite->set_angle(0.0f);
+  lightsprite->set_angle(0.0f);
 
   if(!completely && is_big()) {
     SoundManager::current()->play("sounds/hurt.wav");
@@ -1454,6 +1481,8 @@ Player::kill(bool completely)
       duck = false;
       backflipping = false;
       sprite->set_angle(0.0f);
+      powersprite->set_angle(0.0f);
+      lightsprite->set_angle(0.0f);
       set_bonus(NO_BONUS, true);
     } else if(player_status->bonus == NO_BONUS) {
       safe_timer.start(TUX_SAFE_TIME);
@@ -1497,7 +1526,7 @@ Player::kill(bool completely)
 
     // TODO: need nice way to handle players dying in co-op mode
     Sector::current()->effect->fade_out(3.0);
-    SoundManager::current()->stop_music(3.0);
+    SoundManager::current()->pause_music(3.0);
   }
 }
 
@@ -1514,6 +1543,8 @@ Player::move(const Vector& vector)
   duck = false;
   backflipping = false;
   sprite->set_angle(0.0f);
+  powersprite->set_angle(0.0f);
+  lightsprite->set_angle(0.0f);
   last_ground_y = vector.y;
   if (climbing) stop_climbing(*climbing);
 
@@ -1652,6 +1683,8 @@ Player::start_climbing(Climbable& climbable)
     backflipping = false;
     backflip_direction = 0;
     sprite->set_angle(0.0f);
+    powersprite->set_angle(0.0f);
+    lightsprite->set_angle(0.0f);
   }
 }