src/badguy/mriceblock.cpp

Go to the documentation of this file.
00001 //  SuperTux
00002 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
00003 //
00004 //  This program is free software: you can redistribute it and/or modify
00005 //  it under the terms of the GNU General Public License as published by
00006 //  the Free Software Foundation, either version 3 of the License, or
00007 //  (at your option) any later version.
00008 //
00009 //  This program is distributed in the hope that it will be useful,
00010 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 //  GNU General Public License for more details.
00013 //
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017 #include "badguy/mriceblock.hpp"
00018 
00019 #include "audio/sound_manager.hpp"
00020 #include "object/player.hpp"
00021 #include "sprite/sprite.hpp"
00022 #include "supertux/object_factory.hpp"
00023 
00024 #include <math.h>
00025 
00026 namespace {
00027 const float KICKSPEED = 500;
00028 const int MAXSQUISHES = 10;
00029 const float NOKICK_TIME = 0.1f;
00030 }
00031 
00032 MrIceBlock::MrIceBlock(const Reader& reader) :
00033   WalkingBadguy(reader, "images/creatures/mr_iceblock/mr_iceblock.sprite", "left", "right"), 
00034   ice_state(ICESTATE_NORMAL), 
00035   nokick_timer(),
00036   flat_timer(),
00037   squishcount(0)
00038 {
00039   walk_speed = 80;
00040   max_drop_height = 600;
00041   sound_manager->preload("sounds/iceblock_bump.wav");
00042   sound_manager->preload("sounds/stomp.wav");
00043   sound_manager->preload("sounds/kick.wav");
00044 }
00045 
00046 MrIceBlock::MrIceBlock(const Vector& pos, Direction d) :
00047   WalkingBadguy(pos, d, "images/creatures/mr_iceblock/mr_iceblock.sprite", "left", "right"), 
00048   ice_state(ICESTATE_NORMAL), 
00049   nokick_timer(),
00050   flat_timer(),
00051   squishcount(0)
00052 {
00053   walk_speed = 80;
00054   max_drop_height = 600;
00055   sound_manager->preload("sounds/iceblock_bump.wav");
00056   sound_manager->preload("sounds/stomp.wav");
00057   sound_manager->preload("sounds/kick.wav");
00058 }
00059 
00060 void
00061 MrIceBlock::initialize()
00062 {
00063   WalkingBadguy::initialize();
00064   set_state(ICESTATE_NORMAL);
00065 }
00066 
00067 void
00068 MrIceBlock::active_update(float elapsed_time)
00069 {
00070   if(ice_state == ICESTATE_GRABBED)
00071     return;
00072 
00073   if(ice_state == ICESTATE_FLAT && flat_timer.check()) {
00074     set_state(ICESTATE_NORMAL);
00075   }
00076 
00077   if (ice_state == ICESTATE_NORMAL)
00078   {
00079     WalkingBadguy::active_update(elapsed_time);
00080     return;
00081   }
00082 
00083   BadGuy::active_update(elapsed_time);
00084 }
00085 
00086 bool
00087 MrIceBlock::can_break(){
00088   return ice_state == ICESTATE_KICKED;
00089 }
00090 
00091 void
00092 MrIceBlock::collision_solid(const CollisionHit& hit)
00093 {
00094   update_on_ground_flag(hit);
00095 
00096   if(hit.top || hit.bottom) { // floor or roof
00097     physic.set_velocity_y(0);
00098   }
00099 
00100   // hit left or right
00101   switch(ice_state) {
00102     case ICESTATE_NORMAL:
00103       WalkingBadguy::collision_solid(hit);
00104       break;
00105     case ICESTATE_KICKED: {
00106       if((hit.right && dir == RIGHT) || (hit.left && dir == LEFT)) {
00107         dir = (dir == LEFT) ? RIGHT : LEFT;
00108         sound_manager->play("sounds/iceblock_bump.wav", get_pos());
00109         physic.set_velocity_x(-physic.get_velocity_x()*.975);
00110       }
00111       this->set_action(dir == LEFT ? "flat-left" : "flat-right", /* loops = */ -1);
00112       if(fabsf(physic.get_velocity_x()) < walk_speed*1.5)
00113         set_state(ICESTATE_NORMAL);
00114       break;
00115     }
00116     case ICESTATE_FLAT:
00117       physic.set_velocity_x(0);
00118       break;
00119     case ICESTATE_GRABBED:
00120       break;
00121   }
00122 }
00123 
00124 HitResponse
00125 MrIceBlock::collision(GameObject& object, const CollisionHit& hit)
00126 {
00127   if(ice_state == ICESTATE_GRABBED)
00128     return FORCE_MOVE;
00129 
00130   return BadGuy::collision(object, hit);
00131 }
00132 
00133 HitResponse
00134 MrIceBlock::collision_player(Player& player, const CollisionHit& hit)
00135 {
00136   // handle kicks from left or right side
00137   if(ice_state == ICESTATE_FLAT && get_state() == STATE_ACTIVE) {
00138     if(hit.left) {
00139       dir = RIGHT;
00140       player.kick();
00141       set_state(ICESTATE_KICKED);
00142       return FORCE_MOVE;
00143     } else if(hit.right) {
00144       dir = LEFT;
00145       player.kick();
00146       set_state(ICESTATE_KICKED);
00147       return FORCE_MOVE;
00148     }
00149   }
00150 
00151   return BadGuy::collision_player(player, hit);
00152 }
00153 
00154 HitResponse
00155 MrIceBlock::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
00156 {
00157   switch(ice_state) {
00158     case ICESTATE_NORMAL:
00159       return WalkingBadguy::collision_badguy(badguy, hit);
00160     case ICESTATE_FLAT:
00161       return FORCE_MOVE;
00162     case ICESTATE_KICKED:
00163       badguy.kill_fall();
00164       return FORCE_MOVE;
00165     default:
00166       assert(false);
00167   }
00168 
00169   return ABORT_MOVE;
00170 }
00171 
00172 bool
00173 MrIceBlock::collision_squished(GameObject& object)
00174 {
00175   Player* player = dynamic_cast<Player*>(&object);
00176   if(player && (player->does_buttjump || player->is_invincible())) {
00177     player->bounce(*this);
00178     kill_fall();
00179     return true;
00180   }
00181 
00182   switch(ice_state) {
00183     case ICESTATE_KICKED:
00184     {
00185       BadGuy* badguy = dynamic_cast<BadGuy*>(&object);
00186       if (badguy) {
00187         badguy->kill_fall();
00188         break;
00189       }
00190     }
00191 
00192     // fall through
00193     case ICESTATE_NORMAL:
00194     {
00195       squishcount++;
00196       if (squishcount >= MAXSQUISHES) {
00197         kill_fall();
00198         return true;
00199       }
00200     }
00201 
00202     set_state(ICESTATE_FLAT);
00203     nokick_timer.start(NOKICK_TIME);
00204     break;
00205     case ICESTATE_FLAT:
00206     {
00207       MovingObject* movingobject = dynamic_cast<MovingObject*>(&object);
00208       if (movingobject && (movingobject->get_pos().x < get_pos().x)) {
00209         dir = RIGHT;
00210       } else {
00211         dir = LEFT;
00212       }
00213     }
00214     if (nokick_timer.check()) set_state(ICESTATE_KICKED);
00215     break;
00216     case ICESTATE_GRABBED:
00217       assert(false);
00218       break;
00219   }
00220 
00221   if (player) player->bounce(*this);
00222   return true;
00223 }
00224 
00225 void
00226 MrIceBlock::set_state(IceState state, bool up)
00227 {
00228   if(ice_state == state)
00229     return;
00230 
00231   switch(state) {
00232     case ICESTATE_NORMAL:
00233       WalkingBadguy::initialize();
00234       break;
00235     case ICESTATE_FLAT:
00236       if(up) {
00237         physic.set_velocity_y(-KICKSPEED);
00238       } else {
00239         sound_manager->play("sounds/stomp.wav", get_pos());
00240         physic.set_velocity_x(0);
00241         physic.set_velocity_y(0);
00242       }
00243       this->set_action(dir == LEFT ? "flat-left" : "flat-right", /* loops = */ -1);
00244       flat_timer.start(4);
00245       break;
00246     case ICESTATE_KICKED:
00247       sound_manager->play("sounds/kick.wav", get_pos());
00248 
00249       physic.set_velocity_x(dir == LEFT ? -KICKSPEED : KICKSPEED);
00250       this->set_action(dir == LEFT ? "flat-left" : "flat-right", /* loops = */ -1);
00251       // we should slide above 1 block holes now...
00252       bbox.set_size(34, 31.8f);
00253       break;
00254     case ICESTATE_GRABBED:
00255       flat_timer.stop();
00256       break;
00257     default:
00258       assert(false);
00259   }
00260   ice_state = state;
00261 }
00262 
00263 void
00264 MrIceBlock::grab(MovingObject&, const Vector& pos, Direction dir)
00265 {
00266   movement = pos - get_pos();
00267   this->dir = dir;
00268   this->set_action(dir == LEFT ? "flat-left" : "flat-right", /* loops = */ -1);
00269   set_state(ICESTATE_GRABBED);
00270   set_colgroup_active(COLGROUP_DISABLED);
00271 }
00272 
00273 void
00274 MrIceBlock::ungrab(MovingObject& , Direction dir)
00275 {
00276   if(dir == UP) {
00277     set_state(ICESTATE_FLAT, true);
00278   } else {
00279     this->dir = dir;
00280     set_state(ICESTATE_KICKED);
00281   }
00282   set_colgroup_active(COLGROUP_MOVING);
00283 }
00284 
00285 bool
00286 MrIceBlock::is_portable() const
00287 {
00288   return ice_state == ICESTATE_FLAT;
00289 }
00290 
00291 /* EOF */

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