src/badguy/totem.cpp

Go to the documentation of this file.
00001 //  SuperTux - "Totem" Badguy
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/totem.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 #include "supertux/sector.hpp"
00024 
00025 #include <math.h>
00026 
00027 static const float JUMP_ON_SPEED_Y = -400;
00028 static const float JUMP_OFF_SPEED_Y = -500;
00029 static const std::string LAND_ON_TOTEM_SOUND = "sounds/totem.ogg";
00030 
00031 Totem::Totem(const Reader& reader) :
00032   BadGuy(reader, "images/creatures/totem/totem.sprite"),
00033   carrying(0),
00034   carried_by(0)
00035 {
00036   sound_manager->preload( LAND_ON_TOTEM_SOUND );
00037 }
00038 
00039 Totem::~Totem()
00040 {
00041   if (carrying) carrying->jump_off();
00042   if (carried_by) jump_off();
00043 }
00044 
00045 bool
00046 Totem::updatePointers(const GameObject* from_object, GameObject* to_object)
00047 {
00048   if (from_object == carrying) {
00049     carrying = dynamic_cast<Totem*>(to_object);
00050     return true;
00051   }
00052   if (from_object == carried_by) {
00053     carried_by = dynamic_cast<Totem*>(to_object);
00054     return true;
00055   }
00056   return false;
00057 }
00058 
00059 void
00060 Totem::initialize()
00061 {
00062   if (!carried_by) {
00063 static const float WALKSPEED = 100;
00064     physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
00065     sprite->set_action(dir == LEFT ? "walking-left" : "walking-right");
00066     return;
00067   } else {
00068     synchronize_with(carried_by);
00069     sprite->set_action(dir == LEFT ? "stacked-left" : "stacked-right");
00070     return;
00071   }
00072 }
00073 
00074 void
00075 Totem::active_update(float elapsed_time)
00076 {
00077   BadGuy::active_update(elapsed_time);
00078 
00079   if (!carried_by) {
00080     if (on_ground() && might_fall())
00081     {
00082       dir = (dir == LEFT ? RIGHT : LEFT);
00083       initialize();
00084     }
00085 
00086     Sector* s = Sector::current();
00087     if (s) {
00088       // jump a bit if we find a suitable totem
00089       for (std::vector<MovingObject*>::iterator i = s->moving_objects.begin(); i != s->moving_objects.end(); i++) {
00090         Totem* t = dynamic_cast<Totem*>(*i);
00091         if (!t) continue;
00092 
00093         // skip if we are not approaching each other
00094         if (!((this->dir == LEFT) && (t->dir == RIGHT))) continue;
00095 
00096         Vector p1 = this->get_pos();
00097         Vector p2 = t->get_pos();
00098 
00099         // skip if not on same height
00100         float dy = (p1.y - p2.y);
00101         if (fabsf(dy - 0) > 2) continue;
00102 
00103         // skip if too far away
00104         float dx = (p1.x - p2.x);
00105         if (fabsf(dx - 128) > 2) continue;
00106 
00107         physic.set_velocity_y(JUMP_ON_SPEED_Y);
00108         p1.y -= 1;
00109         this->set_pos(p1);
00110         break;
00111       }
00112     }
00113   }
00114 
00115   if (carried_by) {
00116     this->synchronize_with(carried_by);
00117   }
00118 
00119   if (carrying) {
00120     carrying->synchronize_with(this);
00121   }
00122 
00123 }
00124 
00125 bool
00126 Totem::collision_squished(GameObject& object)
00127 {
00128   if (carrying) carrying->jump_off();
00129   if (carried_by) {
00130     Player* player = dynamic_cast<Player*>(&object);
00131     if (player) player->bounce(*this);
00132     jump_off();
00133   }
00134 
00135   sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
00136   bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height());
00137 
00138   kill_squished(object);
00139   return true;
00140 }
00141 
00142 void
00143 Totem::collision_solid(const CollisionHit& hit)
00144 {
00145   update_on_ground_flag(hit);
00146 
00147   // if we are being carried around, pass event to bottom of stack and ignore it
00148   if (carried_by) {
00149     carried_by->collision_solid(hit);
00150     return;
00151   }
00152 
00153   // If we hit something from above or below: stop moving in this direction
00154   if (hit.top || hit.bottom) {
00155     physic.set_velocity_y(0);
00156   }
00157 
00158   // If we are hit from the direction we are facing: turn around
00159   if (hit.left && (dir == LEFT)) {
00160     dir = RIGHT;
00161     initialize();
00162   }
00163   if (hit.right && (dir == RIGHT)) {
00164     dir = LEFT;
00165     initialize();
00166   }
00167 }
00168 
00169 HitResponse
00170 Totem::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
00171 {
00172   // if we are being carried around, pass event to bottom of stack and ignore it
00173   if (carried_by) {
00174     carried_by->collision_badguy(badguy, hit);
00175     return CONTINUE;
00176   }
00177 
00178   // if we hit a Totem that is not from our stack: have our base jump on its top
00179   Totem* totem = dynamic_cast<Totem*>(&badguy);
00180   if (totem) {
00181     Totem* thisBase = this; while (thisBase->carried_by) thisBase=thisBase->carried_by;
00182     Totem* srcBase = totem; while (srcBase->carried_by)  srcBase=srcBase->carried_by;
00183     Totem* thisTop = this;  while (thisTop->carrying)    thisTop=thisTop->carrying;
00184     if (srcBase != thisBase) {
00185       srcBase->jump_on(thisTop);
00186     }
00187   }
00188 
00189   // If we are hit from the direction we are facing: turn around
00190   if(hit.left && (dir == LEFT)) {
00191     dir = RIGHT;
00192     initialize();
00193   }
00194   if(hit.right && (dir == RIGHT)) {
00195     dir = LEFT;
00196     initialize();
00197   }
00198 
00199   return CONTINUE;
00200 }
00201 
00202 void
00203 Totem::kill_fall()
00204 {
00205   if (carrying) carrying->jump_off();
00206   if (carried_by) jump_off();
00207 
00208   BadGuy::kill_fall();
00209 }
00210 
00211 void
00212 Totem::jump_on(Totem* target)
00213 {
00214   if (target->carrying) {
00215     log_warning << "target is already carrying someone" << std::endl;
00216     return;
00217   }
00218 
00219   target->carrying = this;
00220 
00221   this->carried_by = target;
00222   this->initialize();
00223   bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height());
00224 
00225   sound_manager->play( LAND_ON_TOTEM_SOUND , get_pos());
00226 
00227   this->synchronize_with(target);
00228 }
00229 
00230 void
00231 Totem::jump_off() {
00232   if (!carried_by) {
00233     log_warning << "not carried by anyone" << std::endl;
00234     return;
00235   }
00236 
00237   carried_by->carrying = 0;
00238 
00239   this->carried_by = 0;
00240 
00241   this->initialize();
00242   bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height());
00243 
00244   physic.set_velocity_y(JUMP_OFF_SPEED_Y);
00245 }
00246 
00247 void
00248 Totem::synchronize_with(Totem* base)
00249 {
00250 
00251   if (dir != base->dir) {
00252     dir = base->dir;
00253     sprite->set_action(dir == LEFT ? "stacked-left" : "stacked-right");
00254   }
00255 
00256   Vector pos = base->get_pos();
00257   pos.y -= sprite->get_current_hitbox_height();
00258   set_pos(pos);
00259 
00260   physic.set_velocity_x(base->physic.get_velocity_x());
00261   physic.set_velocity_y(base->physic.get_velocity_y());
00262 }
00263 
00264 /* EOF */

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