1 // SuperTux BadGuy GoldBomb - a bomb that throws up coins when exploding
2 // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3 // Copyright (C) 2013 LMH <lmh.0013@gmail.com>
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "audio/sound_manager.hpp"
19 #include "badguy/goldbomb.hpp"
20 #include "object/coin_explode.hpp"
21 #include "object/explosion.hpp"
22 #include "object/player.hpp"
23 #include "object/portable.hpp"
24 #include "sprite/sprite.hpp"
25 #include "sprite/sprite_manager.hpp"
26 #include "supertux/object_factory.hpp"
27 #include "supertux/sector.hpp"
28 #include "util/reader.hpp"
30 GoldBomb::GoldBomb(const Reader& reader) :
31 WalkingBadguy(reader, "images/creatures/gold_bomb/gold_bomb.sprite", "left", "right"),
39 //Prevent stutter when Tux jumps on Gold Bomb
40 sound_manager->preload("sounds/explosion.wav");
42 //Check if we need another sprite
43 if( !reader.get( "sprite", sprite_name ) ){
46 if( sprite_name == "" ){
47 sprite_name = "images/creatures/gold_bomb/gold_bomb.sprite";
51 sprite = sprite_manager->create( sprite_name );
55 GoldBomb::collision_solid(const CollisionHit& hit)
57 if(tstate == STATE_TICKING) {
59 physic.set_velocity_y(0);
60 physic.set_velocity_x(0);
61 }else if (hit.left || hit.right)
62 physic.set_velocity_x(-physic.get_velocity_x());
64 physic.set_velocity_y(0);
67 WalkingBadguy::collision_solid(hit);
71 GoldBomb::collision(GameObject& object, const CollisionHit& hit)
73 if(tstate == STATE_TICKING)
77 return WalkingBadguy::collision(object, hit);
81 GoldBomb::collision_player(Player& player, const CollisionHit& hit)
83 if(tstate == STATE_TICKING)
87 return WalkingBadguy::collision_player(player, hit);
91 GoldBomb::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
93 if(tstate == STATE_TICKING)
95 return WalkingBadguy::collision_badguy(badguy, hit);
99 GoldBomb::collision_squished(GameObject& object)
101 Player* player = dynamic_cast<Player*>(&object);
102 if(player && player->is_invincible()) {
103 player->bounce(*this);
107 if(is_valid() && tstate == STATE_NORMAL) {
108 tstate = STATE_TICKING;
110 set_action(dir == LEFT ? "ticking-left" : "ticking-right", 1);
111 physic.set_velocity_x(0);
114 player->bounce(*this);
116 ticking.reset(sound_manager->create_sound_source("sounds/fizz.wav"));
117 ticking->set_position(get_pos());
118 ticking->set_looping(true);
119 ticking->set_gain(2.0);
120 ticking->set_reference_distance(32);
127 GoldBomb::active_update(float elapsed_time)
129 if(tstate == STATE_TICKING) {
130 ticking->set_position(get_pos());
131 if(sprite->animation_done()) {
135 movement = physic.get_movement(elapsed_time);
141 WalkingBadguy::active_update(elapsed_time);
145 GoldBomb::kill_fall()
147 if(tstate == STATE_TICKING)
150 // Make the player let go before we explode, otherwise the player is holding
151 // an invalid object. There's probably a better way to do this than in the
153 if (grabber != NULL) {
154 Player* player = dynamic_cast<Player*>(grabber);
157 player->stop_grabbing();
162 Sector::current()->add_object(new Explosion(get_bbox().get_middle()));
163 Sector::current()->add_object(new CoinExplode(get_pos() + Vector (0, -40), 1));
170 GoldBomb::grab(MovingObject& object, const Vector& pos, Direction dir)
172 if(tstate == STATE_TICKING){
173 movement = pos - get_pos();
176 // We actually face the opposite direction of Tux here to make the fuse more
177 // visible instead of hiding it behind Tux
178 sprite->set_action_continued(dir == LEFT ? "ticking-right" : "ticking-left");
179 set_colgroup_active(COLGROUP_DISABLED);
184 movement = pos - get_pos();
186 sprite->set_action(dir == LEFT ? "iced-left" : "iced-right");
187 set_colgroup_active(COLGROUP_DISABLED);
193 GoldBomb::ungrab(MovingObject& object, Direction dir)
195 int toss_velocity_x = 0;
196 int toss_velocity_y = 0;
197 Player* player = dynamic_cast<Player*> (&object);
201 toss_velocity_y += -500;
203 // toss to the side when moving sideways
204 if(player && player->physic.get_velocity_x()*(dir == LEFT ? -1 : 1) > 1) {
205 toss_velocity_x += (dir == LEFT) ? -200 : 200;
206 toss_velocity_y = (toss_velocity_y < -200) ? toss_velocity_y : -200;
207 // toss farther when running
208 if(player && player->physic.get_velocity_x()*(dir == LEFT ? -1 : 1) > 200)
209 toss_velocity_x += player->physic.get_velocity_x()-(190*(dir == LEFT ? -1 : 1));
211 log_warning << toss_velocity_x << toss_velocity_y << std::endl;////
213 //set_pos(object.get_pos() + Vector((dir == LEFT ? -33 : 33), get_bbox().get_height()*0.66666 - 32));
214 physic.set_velocity(toss_velocity_x, toss_velocity_y);
215 set_colgroup_active(COLGROUP_MOVING);
222 if(tstate == STATE_NORMAL){
223 WalkingBadguy::freeze();
224 sprite->set_action(dir == LEFT ? "iced-left" : "iced-right");
229 GoldBomb::is_freezable() const
235 GoldBomb::is_portable() const
237 return (frozen || (tstate == STATE_TICKING));