src/object/explosion.cpp

Go to the documentation of this file.
00001 //  SuperTux -- Explosion object
00002 //  Copyright (C) 2007 Christoph Sommer <christoph.sommer@2007.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 "object/explosion.hpp"
00018 
00019 #include "audio/sound_manager.hpp"
00020 #include "badguy/badguy.hpp"
00021 #include "badguy/walking_badguy.hpp"
00022 #include "math/random_generator.hpp"
00023 #include "object/player.hpp"
00024 #include "object/sprite_particle.hpp"
00025 #include "supertux/object_factory.hpp"
00026 #include "supertux/sector.hpp"
00027 
00028 #include <math.h>
00029 
00030 Explosion::Explosion(const Vector& pos) :
00031   MovingSprite(pos, "images/objects/explosion/explosion.sprite", LAYER_OBJECTS+40, COLGROUP_MOVING),
00032   hurt(true),
00033   push(false),
00034   state(STATE_WAITING)
00035 {
00036   sound_manager->preload("sounds/explosion.wav");
00037   set_pos(get_pos() - (get_bbox().get_middle() - get_pos()));
00038 }
00039 
00040 Explosion::Explosion(const Reader& reader) :
00041   MovingSprite(reader, "images/objects/explosion/explosion.sprite", LAYER_OBJECTS+40, COLGROUP_MOVING),
00042   hurt(true),
00043   push(false),
00044   state(STATE_WAITING)
00045 {
00046   sound_manager->preload("sounds/explosion.wav");
00047 }
00048 
00049 void
00050 Explosion::explode()
00051 {
00052   if (state != STATE_WAITING)
00053     return;
00054   state = STATE_EXPLODING;
00055 
00056   set_action("default", 1);
00057   sprite->set_animation_loops(1); //TODO: this is necessary because set_action will not set "loops" when "action" is the default action
00058   sound_manager->play("sounds/explosion.wav", get_pos());
00059 
00060 #if 0
00061   // spawn some particles
00062   // TODO: provide convenience function in MovingSprite or MovingObject?
00063   for (int i = 0; i < 100; i++) {
00064     Vector ppos = bbox.get_middle();
00065     float angle = graphicsRandom.randf(-M_PI_2, M_PI_2);
00066     float velocity = graphicsRandom.randf(450, 900);
00067     float vx = sin(angle)*velocity;
00068     float vy = -cos(angle)*velocity;
00069     Vector pspeed = Vector(vx, vy);
00070     Vector paccel = Vector(0, 1000);
00071     Sector::current()->add_object(new SpriteParticle("images/objects/particles/explosion.sprite", "default", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_OBJECTS-1));
00072   }
00073 #endif
00074 
00075   if (push) {
00076     Vector center = get_bbox ().get_middle ();
00077     std::vector<MovingObject*> near_objects = Sector::current()->get_nearby_objects (center, 10.0 * 32.0);
00078 
00079     for (size_t i = 0; i < near_objects.size (); i++) {
00080       MovingObject *obj = near_objects[i];
00081       Vector obj_vector = obj->get_bbox ().get_middle ();
00082       Vector direction = obj_vector - center;
00083       float distance = direction.norm ();
00084 
00085       /* If the distance is very small, for example because "obj" is the badguy
00086        * causing the explosion, skip this object. */
00087       if (distance <= 1.0)
00088         continue;
00089 
00090       /* The force decreases with the distance squared. In the distance of one
00091        * tile (32 pixels) you will have a speed increase of 150 pixels/s. */
00092       float force = 150.0 * 32.0*32.0 / (distance * distance);
00093       if (force > 200.0)
00094         force = 200.0;
00095 
00096       Vector add_speed = direction.unit () * force;
00097 
00098       Player *player = dynamic_cast<Player *> (obj);
00099       if (player) {
00100         player->add_velocity (add_speed);
00101       }
00102 
00103       WalkingBadguy *badguy = dynamic_cast<WalkingBadguy *> (obj);
00104       if (badguy) {
00105         badguy->add_velocity (add_speed);
00106       }
00107     } /* for (i = 0 ... near_objects) */
00108   } /* if (push) */
00109 }
00110 
00111 void 
00112 Explosion::update(float )
00113 {
00114   switch(state) {
00115     case STATE_WAITING:
00116       explode();
00117       break;
00118     case STATE_EXPLODING:
00119       if(sprite->animation_done()) {
00120         remove_me();
00121       }
00122       break;
00123   }
00124 }
00125 
00126 HitResponse
00127 Explosion::collision(GameObject& other, const CollisionHit& )
00128 {
00129   if ((state != STATE_EXPLODING) || !hurt)
00130     return ABORT_MOVE;
00131 
00132   Player* player = dynamic_cast<Player*>(&other);
00133   if(player != 0) {
00134     player->kill(false);
00135   }
00136 
00137   BadGuy* badguy = dynamic_cast<BadGuy*>(&other);
00138   if(badguy != 0) {
00139     badguy->kill_fall();
00140   }
00141 
00142   return ABORT_MOVE;
00143 }
00144 
00145 /* EOF */

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