Haywire not moving when jumping on it after freezing
[supertux.git] / src / badguy / haywire.cpp
1 //  SuperTux
2 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3 //  Copyright (C) 2010 Florian Forster <supertux at octo.it>
4 //
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.
9 //
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.
14 //
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/>.
17
18 #include "audio/sound_manager.hpp"
19 #include "badguy/bomb.hpp"
20 #include "badguy/haywire.hpp"
21 #include "object/explosion.hpp"
22 #include "object/player.hpp"
23 #include "sprite/sprite.hpp"
24 #include "sprite/sprite_manager.hpp"
25 #include "supertux/object_factory.hpp"
26 #include "supertux/sector.hpp"
27 #include "util/reader.hpp"
28
29 #define TIME_EXPLOSION 5.0
30 #define TIME_STUNNED   0.5
31
32 Haywire::Haywire(const Reader& reader) :
33   WalkingBadguy(reader, "images/creatures/haywire/haywire.sprite", "left", "right"),
34   is_exploding(false),
35   time_until_explosion(0.0f),
36   is_stunned(false),
37   time_stunned(0.0f)
38 {
39   walk_speed = 80;
40   max_drop_height = 16;
41
42   //Prevent stutter when Tux jumps on Mr Bomb
43   sound_manager->preload("sounds/explosion.wav");
44
45   //Check if we need another sprite
46   if( !reader.get( "sprite", sprite_name ) ){
47     return;
48   }
49   if( sprite_name == "" ){
50     sprite_name = "images/creatures/haywire/haywire.sprite";
51     return;
52   }
53   //Replace sprite
54   sprite = sprite_manager->create( sprite_name );
55 }
56
57 HitResponse
58 Haywire::collision(GameObject& object, const CollisionHit& hit)
59 {
60   return WalkingBadguy::collision(object, hit);
61 }
62
63 HitResponse
64 Haywire::collision_player(Player& player, const CollisionHit& hit)
65 {
66   return WalkingBadguy::collision_player(player, hit);
67 }
68
69 bool
70 Haywire::collision_squished(GameObject& object)
71 {
72   Player* player = dynamic_cast<Player*>(&object);
73   if (player && player->is_invincible()) {
74     player->bounce (*this);
75     kill_fall();
76     return true;
77   }
78
79   if (is_stunned) {
80     if (player)
81       player->bounce (*this);
82     return true;
83   }
84   
85   if(WalkingBadguy::is_frozen()) {
86     WalkingBadguy::unfreeze();
87   }
88
89   if (!is_exploding) {
90     set_action ((dir == LEFT) ? "ticking-left" : "ticking-right", /* loops = */ -1);
91     walk_left_action = "ticking-left";
92     walk_right_action = "ticking-right";
93     set_walk_speed (160);
94     time_until_explosion = TIME_EXPLOSION;
95     is_exploding = true;
96
97     ticking.reset(sound_manager->create_sound_source("sounds/fizz.wav"));
98     ticking->set_position(get_pos());
99     ticking->set_looping(true);
100     ticking->set_reference_distance(32);
101     ticking->play();
102     grunting.reset(sound_manager->create_sound_source("sounds/grunts.ogg"));
103     grunting->set_position(get_pos());
104     grunting->set_looping(true);
105     grunting->set_reference_distance(32);
106     grunting->play();    
107   }
108
109   time_stunned = TIME_STUNNED;
110   is_stunned = true;
111   physic.set_velocity_x (0.0);
112   physic.set_acceleration_x (0.0);
113
114   if (player)
115     player->bounce (*this);
116
117   return true;
118 }
119
120 void
121 Haywire::active_update(float elapsed_time)
122 {
123   if (is_exploding) {
124     ticking->set_position(get_pos());
125     grunting->set_position(get_pos());
126     if (elapsed_time >= time_until_explosion) {
127       kill_fall ();
128       return;
129     }
130     else
131       time_until_explosion -= elapsed_time;
132   }
133
134   if (is_stunned) {
135     if (time_stunned > elapsed_time) {
136       time_stunned -= elapsed_time;
137       return;
138     }
139     else { /* if (time_stunned <= elapsed_time) */
140       elapsed_time -= time_stunned;
141       time_stunned = 0.0;
142       is_stunned = false;
143     }
144   }
145
146   if (is_exploding) {
147     Player *p = this->get_nearest_player ();
148     float target_velocity = 0.0;
149
150     if (p) {
151       /* Player is on the right */
152       if (p->get_pos ().x > this->get_pos ().x)
153         target_velocity = walk_speed;
154       else /* player in on the left */
155         target_velocity = (-1.0) * walk_speed;
156     } /* if (player) */
157
158     WalkingBadguy::active_update(elapsed_time, target_velocity);
159   }
160   else {
161     WalkingBadguy::active_update(elapsed_time);
162   }
163 }
164
165 void
166 Haywire::kill_fall()
167 {
168   if(is_exploding) {
169     ticking->stop();
170     grunting->stop();
171   }
172   if(is_valid()) {
173     remove_me();
174     Explosion* explosion = new Explosion(get_bbox().get_middle());
175     Sector::current()->add_object(explosion);
176   }
177
178   run_dead_script();
179 }
180
181 void
182 Haywire::freeze()
183 {
184   WalkingBadguy::freeze();
185   sprite->set_action(dir == LEFT ? "iced-left" : "iced-right");
186 }
187
188 bool
189 Haywire::is_freezable() const
190 {
191   return true;
192 }
193
194 /* vim: set sw=2 sts=2 et : */
195 /* EOF */