src/badguy/yeti.cpp

Go to the documentation of this file.
00001 //  SuperTux - Boss "Yeti"
00002 //  Copyright (C) 2005 Matthias Braun <matze@braunis.de>
00003 //  Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
00004 //
00005 //  This program is free software: you can redistribute it and/or modify
00006 //  it under the terms of the GNU General Public License as published by
00007 //  the Free Software Foundation, either version 3 of the License, or
00008 //  (at your option) any later version.
00009 //
00010 //  This program is distributed in the hope that it will be useful,
00011 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 //  GNU General Public License for more details.
00014 //
00015 //  You should have received a copy of the GNU General Public License
00016 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 
00018 #include "badguy/yeti.hpp"
00019 
00020 #include "audio/sound_manager.hpp"
00021 #include "badguy/bouncing_snowball.hpp"
00022 #include "badguy/yeti_stalactite.hpp"
00023 #include "object/camera.hpp"
00024 #include "object/player.hpp"
00025 #include "sprite/sprite.hpp"
00026 #include "supertux/object_factory.hpp"
00027 #include "supertux/sector.hpp"
00028 
00029 #include <float.h>
00030 #include <math.h>
00031 
00032 namespace {
00033 const float JUMP_DOWN_VX = 250; 
00034 const float JUMP_DOWN_VY = -250; 
00036 const float RUN_VX = 350; 
00038 const float JUMP_UP_VX = 350; 
00039 const float JUMP_UP_VY = -700; 
00041 const float STOMP_VY = -300; 
00043 const float LEFT_STAND_X = 80; 
00044 const float RIGHT_STAND_X = 1280-LEFT_STAND_X-60; 
00045 const float LEFT_JUMP_X = LEFT_STAND_X+448; 
00046 const float RIGHT_JUMP_X = RIGHT_STAND_X-448; 
00047 const float STOMP_WAIT = .5; 
00048 const float SAFE_TIME = .5; 
00049 const int INITIAL_HITPOINTS = 5; 
00051 const float YETI_SQUISH_TIME = 5;
00052 }
00053 
00054 Yeti::Yeti(const Reader& reader) :
00055   BadGuy(reader, "images/creatures/yeti/yeti.sprite"),
00056   state(),
00057   state_timer(),
00058   safe_timer(),
00059   stomp_count(),
00060   hit_points(),
00061   hud_head()
00062 {
00063   hit_points = INITIAL_HITPOINTS;
00064   countMe = false;
00065   sound_manager->preload("sounds/yeti_gna.wav");
00066   sound_manager->preload("sounds/yeti_roar.wav");
00067   hud_head = Surface::create("images/creatures/yeti/hudlife.png");
00068 }
00069 
00070 Yeti::~Yeti()
00071 {
00072 }
00073 
00074 void
00075 Yeti::initialize()
00076 {
00077   dir = RIGHT;
00078   jump_down();
00079 }
00080 
00081 void
00082 Yeti::draw(DrawingContext& context)
00083 {
00084   // we blink when we are safe
00085   if(safe_timer.started() && size_t(game_time*40)%2)
00086     return;
00087 
00088   draw_hit_points(context);
00089 
00090   BadGuy::draw(context);
00091 }
00092 
00093 void
00094 Yeti::draw_hit_points(DrawingContext& context)
00095 {
00096   int i;
00097 
00098   if (hud_head)
00099   {
00100     context.push_transform();
00101     context.set_translation(Vector(0, 0));
00102 
00103     for (i = 0; i < hit_points; ++i)
00104     {
00105       context.draw_surface(hud_head, Vector(BORDER_X + (i * hud_head->get_width()), BORDER_Y + 1), LAYER_FOREGROUND1);
00106     }
00107 
00108     context.pop_transform();
00109   }
00110 }
00111 
00112 void
00113 Yeti::active_update(float elapsed_time)
00114 {
00115   switch(state) {
00116     case JUMP_DOWN:
00117       physic.set_velocity_x((dir==RIGHT)?+JUMP_DOWN_VX:-JUMP_DOWN_VX);
00118       break;
00119     case RUN:
00120       physic.set_velocity_x((dir==RIGHT)?+RUN_VX:-RUN_VX);
00121       if (((dir == RIGHT) && (get_pos().x >= RIGHT_JUMP_X)) || ((dir == LEFT) && (get_pos().x <= LEFT_JUMP_X))) jump_up();
00122       break;
00123     case JUMP_UP:
00124       physic.set_velocity_x((dir==RIGHT)?+JUMP_UP_VX:-JUMP_UP_VX);
00125       if (((dir == RIGHT) && (get_pos().x >= RIGHT_STAND_X)) || ((dir == LEFT) && (get_pos().x <= LEFT_STAND_X))) be_angry();
00126       break;
00127     case BE_ANGRY:
00128       if(state_timer.check()) {
00129         sound_manager->play("sounds/yeti_gna.wav");
00130         physic.set_velocity_y(STOMP_VY);
00131         sprite->set_action((dir==RIGHT)?"stomp-right":"stomp-left");
00132       }
00133       break;
00134     case SQUISHED:
00135       if (state_timer.check()) {
00136         remove_me();
00137       }
00138       break;
00139   }
00140 
00141   movement = physic.get_movement(elapsed_time);
00142 }
00143 
00144 void
00145 Yeti::jump_down()
00146 {
00147   sprite->set_action((dir==RIGHT)?"jump-right":"jump-left");
00148   physic.set_velocity_x((dir==RIGHT)?(+JUMP_DOWN_VX):(-JUMP_DOWN_VX));
00149   physic.set_velocity_y(JUMP_DOWN_VY);
00150   state = JUMP_DOWN;
00151 }
00152 
00153 void
00154 Yeti::run()
00155 {
00156   sprite->set_action((dir==RIGHT)?"run-right":"run-left");
00157   physic.set_velocity_x((dir==RIGHT)?(+RUN_VX):(-RUN_VX));
00158   physic.set_velocity_y(0);
00159   state = RUN;
00160 }
00161 
00162 void
00163 Yeti::jump_up()
00164 {
00165   sprite->set_action((dir==RIGHT)?"jump-right":"jump-left");
00166   physic.set_velocity_x((dir==RIGHT)?(+JUMP_UP_VX):(-JUMP_UP_VX));
00167   physic.set_velocity_y(JUMP_UP_VY);
00168   state = JUMP_UP;
00169 }
00170 
00171 void
00172 Yeti::be_angry()
00173 {
00174   //turn around
00175   dir = (dir==RIGHT) ? LEFT : RIGHT;
00176 
00177   sprite->set_action((dir==RIGHT) ? "stand-right" : "stand-left");
00178   physic.set_velocity_x(0);
00179   physic.set_velocity_y(0);
00180   stomp_count = 0;
00181   state = BE_ANGRY;
00182   state_timer.start(STOMP_WAIT);
00183 }
00184 
00185 bool
00186 Yeti::collision_squished(GameObject& object)
00187 {
00188   kill_squished(object);
00189 
00190   return true;
00191 }
00192 
00193 void
00194 Yeti::kill_squished(GameObject& object)
00195 {
00196   Player* player = dynamic_cast<Player*>(&object);
00197   if (player) {
00198     player->bounce(*this);
00199     take_hit(*player);
00200   }
00201 }
00202 
00203 void Yeti::take_hit(Player& )
00204 {
00205   if(safe_timer.started())
00206     return;
00207 
00208   sound_manager->play("sounds/yeti_roar.wav");
00209   hit_points--;
00210 
00211   if(hit_points <= 0) {
00212     // We're dead
00213     physic.enable_gravity(true);
00214     physic.set_velocity_x(0);
00215     physic.set_velocity_y(0);
00216 
00217     state = SQUISHED;
00218     state_timer.start(YETI_SQUISH_TIME);
00219     set_colgroup_active(COLGROUP_MOVING_ONLY_STATIC);
00220     sprite->set_action("dead");
00221 
00222     run_dead_script();
00223   }
00224   else {
00225     safe_timer.start(SAFE_TIME);
00226   }
00227 }
00228 
00229 void
00230 Yeti::kill_fall()
00231 {
00232   // shooting bullets or being invincible won't work :)
00233 }
00234 
00235 void
00236 Yeti::drop_stalactite()
00237 {
00238   // make a stalactite falling down and shake camera a bit
00239   Sector::current()->camera->shake(.1f, 0, 10);
00240 
00241   Player* player = this->get_nearest_player();
00242   if (!player) return;
00243 
00244   Sector* sector = Sector::current();
00245   for(Sector::GameObjects::iterator i = sector->gameobjects.begin();
00246       i != sector->gameobjects.end(); ++i) {
00247     YetiStalactite* stalactite = dynamic_cast<YetiStalactite*> (*i);
00248     if(stalactite && stalactite->is_hanging()) {
00249       float distancex;
00250       if (hit_points >= 3) {
00251         // drop stalactites within 3 of player, going out with each jump
00252         distancex = fabsf(stalactite->get_bbox().get_middle().x - player->get_bbox().get_middle().x);
00253         if(distancex < stomp_count*32) {
00254           stalactite->start_shaking();
00255         }
00256       }
00257       else { /* if (hitpoints < 3) */
00258         // drop every 3rd pair of stalactites
00259         if(((((int)stalactite->get_pos().x + 16) / 64) % 3) == (stomp_count % 3)) {
00260           stalactite->start_shaking();
00261         }
00262       }
00263     } /* if(stalactite && stalactite->is_hanging()) */
00264   }
00265 }
00266 
00267 void
00268 Yeti::collision_solid(const CollisionHit& hit)
00269 {
00270   if(hit.top || hit.bottom) {
00271     // hit floor or roof
00272     physic.set_velocity_y(0);
00273     switch (state) {
00274       case JUMP_DOWN:
00275         run();
00276         break;
00277       case RUN:
00278         break;
00279       case JUMP_UP:
00280         break;
00281       case BE_ANGRY:
00282         // we just landed
00283         if(!state_timer.started()) {
00284           sprite->set_action((dir==RIGHT)?"stand-right":"stand-left");
00285           stomp_count++;
00286           drop_stalactite();
00287 
00288           // go to other side after 3 jumps
00289           if(stomp_count == 3) {
00290             jump_down();
00291           } else {
00292             // jump again
00293             state_timer.start(STOMP_WAIT);
00294           }
00295         }
00296         break;
00297       case SQUISHED:
00298         break;
00299     }
00300   } else if(hit.left || hit.right) {
00301     // hit wall
00302     jump_up();
00303   }
00304 }
00305 
00306 /* EOF */

Generated on Mon Jun 9 03:38:18 2014 for SuperTux by  doxygen 1.5.1