00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
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
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
00233 }
00234
00235 void
00236 Yeti::drop_stalactite()
00237 {
00238
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
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 {
00258
00259 if(((((int)stalactite->get_pos().x + 16) / 64) % 3) == (stomp_count % 3)) {
00260 stalactite->start_shaking();
00261 }
00262 }
00263 }
00264 }
00265 }
00266
00267 void
00268 Yeti::collision_solid(const CollisionHit& hit)
00269 {
00270 if(hit.top || hit.bottom) {
00271
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
00283 if(!state_timer.started()) {
00284 sprite->set_action((dir==RIGHT)?"stand-right":"stand-left");
00285 stomp_count++;
00286 drop_stalactite();
00287
00288
00289 if(stomp_count == 3) {
00290 jump_down();
00291 } else {
00292
00293 state_timer.start(STOMP_WAIT);
00294 }
00295 }
00296 break;
00297 case SQUISHED:
00298 break;
00299 }
00300 } else if(hit.left || hit.right) {
00301
00302 jump_up();
00303 }
00304 }
00305
00306