| 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 | |