00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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) {
00097 physic.set_velocity_y(0);
00098 }
00099
00100
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", -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
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
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", -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", -1);
00251
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", -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