From bcef0c2aef6c8f4f85c87b8b6a25b93b69430c4c Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Tue, 2 Mar 2010 11:25:10 +0000 Subject: [PATCH] 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. SVN-Revision: 6510 --- src/object/explosion.cpp | 83 ++++++++++++++++++++++++++++++++++++------------ src/object/explosion.hpp | 22 +++++++++++++ 2 files changed, 85 insertions(+), 20 deletions(-) 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; }; -- 2.11.0