src/badguy/snail.cpp

Go to the documentation of this file.
00001 //  SuperTux - Badguy "Snail"
00002 //  Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.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/snail.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 SNAIL_KICK_SPEED = 500;
00028 const int MAX_SNAIL_SQUISHES = 10;
00029 const float SNAIL_KICK_SPEED_Y = -500; 
00030 }
00031 
00032 Snail::Snail(const Reader& reader) :
00033   WalkingBadguy(reader, "images/creatures/snail/snail.sprite", "left", "right"), 
00034   state(STATE_NORMAL), 
00035   kicked_delay_timer(),
00036   squishcount(0)
00037 {
00038   walk_speed = 80;
00039   max_drop_height = 600;
00040   sound_manager->preload("sounds/iceblock_bump.wav");
00041   sound_manager->preload("sounds/stomp.wav");
00042   sound_manager->preload("sounds/kick.wav");
00043 }
00044 
00045 Snail::Snail(const Vector& pos, Direction d) :
00046   WalkingBadguy(pos, d, "images/creatures/snail/snail.sprite", "left", "right"), 
00047   state(STATE_NORMAL), 
00048   kicked_delay_timer(),
00049   squishcount(0)
00050 {
00051   walk_speed = 80;
00052   max_drop_height = 600;
00053   sound_manager->preload("sounds/iceblock_bump.wav");
00054   sound_manager->preload("sounds/stomp.wav");
00055   sound_manager->preload("sounds/kick.wav");
00056 }
00057 
00058 void
00059 Snail::initialize()
00060 {
00061   WalkingBadguy::initialize();
00062   be_normal();
00063 }
00064 
00065 void
00066 Snail::be_normal()
00067 {
00068   if (state == STATE_NORMAL) return;
00069 
00070   state = STATE_NORMAL;
00071   WalkingBadguy::initialize();
00072 }
00073 
00074 void
00075 Snail::be_flat()
00076 {
00077   state = STATE_FLAT;
00078   sprite->set_action(dir == LEFT ? "flat-left" : "flat-right", 1);
00079 
00080   physic.set_velocity_x(0);
00081   physic.set_velocity_y(0);
00082 }
00083 
00084 void
00085 Snail::be_kicked()
00086 {
00087   state = STATE_KICKED_DELAY;
00088   sprite->set_action(dir == LEFT ? "flat-left" : "flat-right", 1);
00089 
00090   physic.set_velocity_x(dir == LEFT ? -SNAIL_KICK_SPEED : SNAIL_KICK_SPEED);
00091   physic.set_velocity_y(0);
00092 
00093   // start a timer to delay addition of upward movement until we are (hopefully) out from under the player
00094   kicked_delay_timer.start(0.05f);
00095 }
00096 
00097 bool
00098 Snail::can_break(){
00099   return state == STATE_KICKED;
00100 }
00101 
00102 void
00103 Snail::active_update(float elapsed_time)
00104 {
00105   switch (state) {
00106 
00107     case STATE_NORMAL:
00108       WalkingBadguy::active_update(elapsed_time);
00109       return;
00110 
00111     case STATE_FLAT:
00112       if (sprite->animation_done()) {
00113         be_normal();
00114       }
00115       break;
00116 
00117     case STATE_KICKED_DELAY:
00118       if (kicked_delay_timer.check()) {
00119         physic.set_velocity_x(dir == LEFT ? -SNAIL_KICK_SPEED : SNAIL_KICK_SPEED);
00120         physic.set_velocity_y(SNAIL_KICK_SPEED_Y);
00121         state = STATE_KICKED;
00122       }
00123       break;
00124 
00125     case STATE_KICKED:
00126       physic.set_velocity_x(physic.get_velocity_x() * pow(0.99, elapsed_time/0.02));
00127       if (sprite->animation_done() || (fabsf(physic.get_velocity_x()) < walk_speed)) be_normal();
00128       break;
00129 
00130   }
00131 
00132   BadGuy::active_update(elapsed_time);
00133 }
00134 
00135 void
00136 Snail::collision_solid(const CollisionHit& hit)
00137 {
00138   switch (state) {
00139     case STATE_NORMAL:
00140       WalkingBadguy::collision_solid(hit);
00141       return;
00142     case STATE_KICKED:
00143       if(hit.left || hit.right) {
00144         sound_manager->play("sounds/iceblock_bump.wav", get_pos());
00145 
00146         if( ( dir == LEFT && hit.left ) || ( dir == RIGHT && hit.right) ){
00147           dir = (dir == LEFT) ? RIGHT : LEFT;
00148           sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
00149 
00150           physic.set_velocity_x(-physic.get_velocity_x());
00151         }
00152       }
00153       /* fall-through */
00154     case STATE_FLAT:
00155     case STATE_KICKED_DELAY:
00156       if(hit.top || hit.bottom) {
00157         physic.set_velocity_y(0);
00158       }
00159       break;
00160   }
00161 
00162   update_on_ground_flag(hit);
00163 
00164 }
00165 
00166 HitResponse
00167 Snail::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
00168 {
00169   switch(state) {
00170     case STATE_NORMAL:
00171       return WalkingBadguy::collision_badguy(badguy, hit);
00172     case STATE_FLAT:
00173     case STATE_KICKED_DELAY:
00174       return FORCE_MOVE;
00175     case STATE_KICKED:
00176       badguy.kill_fall();
00177       return FORCE_MOVE;
00178     default:
00179       assert(false);
00180   }
00181 
00182   return ABORT_MOVE;
00183 }
00184 
00185 HitResponse
00186 Snail::collision_player(Player& player, const CollisionHit& hit)
00187 {
00188   // handle kicks from left or right side
00189   if(state == STATE_FLAT && (hit.left || hit.right)) {
00190     if(hit.left) {
00191       dir = RIGHT;
00192     } else if(hit.right) {
00193       dir = LEFT;
00194     }
00195     player.kick();
00196     be_kicked();
00197     return FORCE_MOVE;
00198   }
00199 
00200   return BadGuy::collision_player(player, hit);
00201 }
00202 
00203 bool
00204 Snail::collision_squished(GameObject& object)
00205 {
00206   Player* player = dynamic_cast<Player*>(&object);
00207   if(player && (player->does_buttjump || player->is_invincible())) {
00208     kill_fall();
00209     player->bounce(*this);
00210     return true;
00211   }
00212 
00213   switch(state) {
00214 
00215     case STATE_KICKED:
00216     case STATE_NORMAL:
00217 
00218       // Can't stomp in midair
00219       if(!on_ground())
00220         break;
00221 
00222       squishcount++;
00223       if (squishcount >= MAX_SNAIL_SQUISHES) {
00224         kill_fall();
00225         return true;
00226       }
00227       sound_manager->play("sounds/stomp.wav", get_pos());
00228       be_flat();
00229       break;
00230 
00231     case STATE_FLAT:
00232       sound_manager->play("sounds/kick.wav", get_pos());
00233       {
00234         MovingObject* movingobject = dynamic_cast<MovingObject*>(&object);
00235         if (movingobject && (movingobject->get_pos().x < get_pos().x)) {
00236           dir = RIGHT;
00237         } else {
00238           dir = LEFT;
00239         }
00240       }
00241       be_kicked();
00242       break;
00243 
00244     case STATE_KICKED_DELAY:
00245       break;
00246 
00247   }
00248 
00249   if (player) player->bounce(*this);
00250   return true;
00251 }
00252 
00253 /* EOF */

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