From: florianf Date: Tue, 2 Mar 2010 11:25:10 +0000 (+0000) Subject: object/explosion.[ch]pp: Added the "hurt" and "push" members. X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=0572873b72bc61f981a810ba0a3fcea31ae9f209;p=supertux.git object/explosion.[ch]pp: Added the "hurt" and "push" members. If "hurt" is set (true by default), then the explosion will hurt Tux and nearby badguys. If "push" is set (false by default), Tux and nearby walking badguys will experience the force of the explosion, possibly throwing them in the air. git-svn-id: http://supertux.lethargik.org/svn/supertux/trunk/supertux@6510 837edb03-e0f3-0310-88ca-d4d4e8b29345 --- diff --git a/src/object/explosion.cpp b/src/object/explosion.cpp index 25a114829..d9e806ca4 100644 --- a/src/object/explosion.cpp +++ b/src/object/explosion.cpp @@ -18,6 +18,7 @@ #include "audio/sound_manager.hpp" #include "badguy/badguy.hpp" +#include "badguy/walking_badguy.hpp" #include "math/random_generator.hpp" #include "object/player.hpp" #include "object/sprite_particle.hpp" @@ -26,15 +27,21 @@ #include -Explosion::Explosion(const Vector& pos) - : MovingSprite(pos, "images/objects/explosion/explosion.sprite", LAYER_OBJECTS+40, COLGROUP_MOVING), state(STATE_WAITING) +Explosion::Explosion(const Vector& pos) : + MovingSprite(pos, "images/objects/explosion/explosion.sprite", LAYER_OBJECTS+40, COLGROUP_MOVING), + hurt(true), + push(false), + state(STATE_WAITING) { sound_manager->preload("sounds/explosion.wav"); set_pos(get_pos() - (get_bbox().get_middle() - get_pos())); } -Explosion::Explosion(const Reader& reader) - : MovingSprite(reader, "images/objects/explosion/explosion.sprite", LAYER_OBJECTS+40, COLGROUP_MOVING), state(STATE_WAITING) +Explosion::Explosion(const Reader& reader) : + MovingSprite(reader, "images/objects/explosion/explosion.sprite", LAYER_OBJECTS+40, COLGROUP_MOVING), + hurt(true), + push(false), + state(STATE_WAITING) { sound_manager->preload("sounds/explosion.wav"); } @@ -42,28 +49,63 @@ Explosion::Explosion(const Reader& reader) void Explosion::explode() { - if (state != STATE_WAITING) return; + if (state != STATE_WAITING) + return; state = STATE_EXPLODING; set_action("default", 1); sprite->set_animation_loops(1); //TODO: this is necessary because set_action will not set "loops" when "action" is the default action sound_manager->play("sounds/explosion.wav", get_pos()); - if (0) - { - // spawn some particles - // TODO: provide convenience function in MovingSprite or MovingObject? - for (int i = 0; i < 100; i++) { - Vector ppos = bbox.get_middle(); - float angle = graphicsRandom.randf(-M_PI_2, M_PI_2); - float velocity = graphicsRandom.randf(450, 900); - float vx = sin(angle)*velocity; - float vy = -cos(angle)*velocity; - Vector pspeed = Vector(vx, vy); - Vector paccel = Vector(0, 1000); - Sector::current()->add_object(new SpriteParticle("images/objects/particles/explosion.sprite", "default", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_OBJECTS-1)); - } +#if 0 + // spawn some particles + // TODO: provide convenience function in MovingSprite or MovingObject? + for (int i = 0; i < 100; i++) { + Vector ppos = bbox.get_middle(); + float angle = graphicsRandom.randf(-M_PI_2, M_PI_2); + float velocity = graphicsRandom.randf(450, 900); + float vx = sin(angle)*velocity; + float vy = -cos(angle)*velocity; + Vector pspeed = Vector(vx, vy); + Vector paccel = Vector(0, 1000); + Sector::current()->add_object(new SpriteParticle("images/objects/particles/explosion.sprite", "default", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_OBJECTS-1)); } +#endif + + if (push) { + Vector center = get_bbox ().get_middle (); + std::vector near_objects = Sector::current()->get_nearby_objects (center, 10.0 * 32.0); + + for (size_t i = 0; i < near_objects.size (); i++) { + MovingObject *obj = near_objects[i]; + Vector obj_vector = obj->get_bbox ().get_middle (); + Vector direction = obj_vector - center; + float distance = direction.norm (); + + /* If the distance is very small, for example because "obj" is the badguy + * causing the explosion, skip this object. */ + if (distance <= 1.0) + continue; + + /* The force decreases with the distance squared. In the distance of one + * tile (32 pixels) you will have a speed increase of 150 pixels/s. */ + float force = 150.0 * 32.0*32.0 / (distance * distance); + if (force > 200.0) + force = 200.0; + + Vector add_speed = direction.unit () * force; + + Player *player = dynamic_cast (obj); + if (player) { + player->add_velocity (add_speed); + } + + WalkingBadguy *badguy = dynamic_cast (obj); + if (badguy) { + badguy->add_velocity (add_speed); + } + } /* for (i = 0 ... near_objects) */ + } /* if (push) */ } void @@ -84,7 +126,8 @@ Explosion::update(float ) HitResponse Explosion::collision(GameObject& other, const CollisionHit& ) { - if(state != STATE_EXPLODING) return ABORT_MOVE; + if ((state != STATE_EXPLODING) || !hurt) + return ABORT_MOVE; Player* player = dynamic_cast(&other); if(player != 0) { diff --git a/src/object/explosion.hpp b/src/object/explosion.hpp index 0d556c4aa..869b982fa 100644 --- a/src/object/explosion.hpp +++ b/src/object/explosion.hpp @@ -34,6 +34,26 @@ public: void update(float elapsed_time); HitResponse collision(GameObject& other, const CollisionHit& hit); + bool hurts (void) const + { + return this->hurt; + } + + void hurts (bool val) + { + this->hurt = val; + } + + bool pushes (void) const + { + return this->push; + } + + void pushes (bool val) + { + this->push = val; + } + protected: /** * plays sound, starts animation @@ -45,6 +65,8 @@ private: STATE_WAITING, STATE_EXPLODING }; + bool hurt; + bool push; State state; };