00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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
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
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
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