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 "badguy/haywire.hpp" |
19 | |
20 | #include "audio/sound_manager.hpp" |
21 | #include "audio/sound_source.hpp" |
22 | #include "object/explosion.hpp" |
23 | #include "object/player.hpp" |
24 | #include "sprite/sprite_manager.hpp" |
25 | #include "supertux/sector.hpp" |
26 | #include "util/reader_mapping.hpp" |
27 | |
28 | namespace { |
29 | |
30 | const float TIME_EXPLOSION = 5.0f; |
31 | const float TIME_STUNNED = 0.5f; |
32 | |
33 | const float NORMAL_WALK_SPEED = 80.0f; |
34 | const float EXPLODING_WALK_SPEED = 160.0f; |
35 | |
36 | } // namespace |
37 | |
38 | Haywire::Haywire(const ReaderMapping& reader) : |
39 | WalkingBadguy(reader, "images/creatures/haywire/haywire.sprite" , "left" , "right" ), |
40 | is_exploding(false), |
41 | time_until_explosion(0.0f), |
42 | is_stunned(false), |
43 | time_stunned(0.0f), |
44 | ticking(), |
45 | grunting() |
46 | { |
47 | walk_speed = NORMAL_WALK_SPEED; |
48 | max_drop_height = 16; |
49 | |
50 | //Prevent stutter when Tux jumps on Mr Bomb |
51 | SoundManager::current()->preload("sounds/explosion.wav" ); |
52 | |
53 | //Check if we need another sprite |
54 | if ( !reader.get( "sprite" , m_sprite_name ) ){ |
55 | return; |
56 | } |
57 | if (m_sprite_name.empty()) { |
58 | m_sprite_name = "images/creatures/haywire/haywire.sprite" ; |
59 | return; |
60 | } |
61 | //Replace sprite |
62 | m_sprite = SpriteManager::current()->create( m_sprite_name ); |
63 | } |
64 | |
65 | bool |
66 | Haywire::collision_squished(GameObject& object) |
67 | { |
68 | auto player = dynamic_cast<Player*>(&object); |
69 | if (player && player->is_invincible()) { |
70 | player->bounce (*this); |
71 | kill_fall(); |
72 | return true; |
73 | } |
74 | |
75 | if (is_stunned) { |
76 | if (player) |
77 | player->bounce (*this); |
78 | return true; |
79 | } |
80 | |
81 | if (WalkingBadguy::is_frozen()) { |
82 | WalkingBadguy::unfreeze(); |
83 | } |
84 | |
85 | if (!is_exploding) { |
86 | start_exploding(); |
87 | } |
88 | |
89 | time_stunned = TIME_STUNNED; |
90 | is_stunned = true; |
91 | m_physic.set_velocity_x(0.f); |
92 | m_physic.set_acceleration_x(0.f); |
93 | |
94 | if (player) |
95 | player->bounce (*this); |
96 | |
97 | return true; |
98 | } |
99 | |
100 | void |
101 | Haywire::active_update(float dt_sec) |
102 | { |
103 | if (is_exploding) { |
104 | ticking->set_position(get_pos()); |
105 | grunting->set_position(get_pos()); |
106 | if (dt_sec >= time_until_explosion) { |
107 | kill_fall (); |
108 | return; |
109 | } |
110 | else |
111 | time_until_explosion -= dt_sec; |
112 | } |
113 | |
114 | if (is_stunned) { |
115 | if (time_stunned > dt_sec) { |
116 | time_stunned -= dt_sec; |
117 | } |
118 | else { /* if (time_stunned <= dt_sec) */ |
119 | time_stunned = 0.f; |
120 | is_stunned = false; |
121 | } |
122 | } |
123 | |
124 | if (is_exploding) { |
125 | auto p = get_nearest_player (); |
126 | float target_velocity = 0.f; |
127 | |
128 | if (p && time_stunned == 0.f) { |
129 | /* Player is on the right */ |
130 | if (p->get_pos ().x > get_pos ().x) |
131 | target_velocity = walk_speed; |
132 | else /* player in on the left */ |
133 | target_velocity = (-1.f) * walk_speed; |
134 | } |
135 | |
136 | WalkingBadguy::active_update(dt_sec, target_velocity); |
137 | } |
138 | else { |
139 | WalkingBadguy::active_update(dt_sec); |
140 | } |
141 | } |
142 | |
143 | void |
144 | Haywire::kill_fall() |
145 | { |
146 | if (is_exploding) { |
147 | ticking->stop(); |
148 | grunting->stop(); |
149 | } |
150 | if (is_valid()) { |
151 | remove_me(); |
152 | Sector::get().add<Explosion>(m_col.m_bbox.get_middle()); |
153 | } |
154 | |
155 | run_dead_script(); |
156 | } |
157 | |
158 | bool |
159 | Haywire::is_freezable() const |
160 | { |
161 | return true; |
162 | } |
163 | |
164 | void |
165 | Haywire::ignite() |
166 | { |
167 | kill_fall(); |
168 | } |
169 | |
170 | void |
171 | Haywire::freeze() { |
172 | BadGuy::freeze(); |
173 | if (is_exploding) { |
174 | stop_exploding(); |
175 | } |
176 | } |
177 | |
178 | void |
179 | Haywire::start_exploding() |
180 | { |
181 | set_action ((m_dir == Direction::LEFT) ? "ticking-left" : "ticking-right" , /* loops = */ -1); |
182 | walk_left_action = "ticking-left" ; |
183 | walk_right_action = "ticking-right" ; |
184 | set_walk_speed (EXPLODING_WALK_SPEED); |
185 | time_until_explosion = TIME_EXPLOSION; |
186 | is_exploding = true; |
187 | |
188 | ticking = SoundManager::current()->create_sound_source("sounds/fizz.wav" ); |
189 | ticking->set_position(get_pos()); |
190 | ticking->set_looping(true); |
191 | ticking->set_reference_distance(32); |
192 | ticking->play(); |
193 | grunting = SoundManager::current()->create_sound_source("sounds/grunts.ogg" ); |
194 | grunting->set_position(get_pos()); |
195 | grunting->set_looping(true); |
196 | grunting->set_reference_distance(32); |
197 | grunting->play(); |
198 | } |
199 | |
200 | void |
201 | Haywire::stop_exploding() |
202 | { |
203 | walk_left_action = "left" ; |
204 | walk_right_action = "right" ; |
205 | set_walk_speed(NORMAL_WALK_SPEED); |
206 | time_until_explosion = 0.0f; |
207 | is_exploding = false; |
208 | |
209 | if (ticking) |
210 | ticking->stop(); |
211 | |
212 | if (grunting) |
213 | grunting->stop(); |
214 | } |
215 | |
216 | void Haywire::stop_looping_sounds() |
217 | { |
218 | if (ticking) { |
219 | ticking->stop(); |
220 | } |
221 | if (grunting) { |
222 | grunting->stop(); |
223 | } |
224 | } |
225 | |
226 | void Haywire::play_looping_sounds() |
227 | { |
228 | if (is_exploding) { |
229 | if (ticking) { |
230 | ticking->play(); |
231 | } |
232 | if (grunting) { |
233 | grunting->play(); |
234 | } |
235 | } |
236 | } |
237 | |
238 | /* EOF */ |
239 | |