1 // SuperTux - Badguy "Snail"
2 // Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "badguy/snail.hpp"
19 #include "audio/sound_manager.hpp"
20 #include "object/player.hpp"
21 #include "sprite/sprite.hpp"
22 #include "supertux/object_factory.hpp"
27 const float SNAIL_KICK_SPEED = 500;
28 const int MAX_SNAIL_SQUISHES = 10;
29 const float SNAIL_KICK_SPEED_Y = -500; /**< y-velocity gained when kicked */
32 Snail::Snail(const Reader& reader) :
33 WalkingBadguy(reader, "images/creatures/snail/snail.sprite", "left", "right"),
39 max_drop_height = 600;
40 sound_manager->preload("sounds/iceblock_bump.wav");
41 sound_manager->preload("sounds/stomp.wav");
42 sound_manager->preload("sounds/kick.wav");
45 Snail::Snail(const Vector& pos, Direction d) :
46 WalkingBadguy(pos, d, "images/creatures/snail/snail.sprite", "left", "right"),
52 max_drop_height = 600;
53 sound_manager->preload("sounds/iceblock_bump.wav");
54 sound_manager->preload("sounds/stomp.wav");
55 sound_manager->preload("sounds/kick.wav");
61 WalkingBadguy::initialize();
68 if (state == STATE_NORMAL) return;
71 WalkingBadguy::initialize();
78 sprite->set_action(dir == LEFT ? "flat-left" : "flat-right", 1);
80 physic.set_velocity_x(0);
81 physic.set_velocity_y(0);
87 state = STATE_KICKED_DELAY;
88 sprite->set_action(dir == LEFT ? "flat-left" : "flat-right", 1);
90 physic.set_velocity_x(dir == LEFT ? -SNAIL_KICK_SPEED : SNAIL_KICK_SPEED);
91 physic.set_velocity_y(0);
93 // start a timer to delay addition of upward movement until we are (hopefully) out from under the player
94 kicked_delay_timer.start(0.05f);
99 return state == STATE_KICKED;
103 Snail::active_update(float elapsed_time)
107 BadGuy::active_update(elapsed_time);
114 WalkingBadguy::active_update(elapsed_time);
118 if (sprite->animation_done()) {
123 case STATE_KICKED_DELAY:
124 if (kicked_delay_timer.check()) {
125 physic.set_velocity_x(dir == LEFT ? -SNAIL_KICK_SPEED : SNAIL_KICK_SPEED);
126 physic.set_velocity_y(SNAIL_KICK_SPEED_Y);
127 state = STATE_KICKED;
132 physic.set_velocity_x(physic.get_velocity_x() * pow(0.99, elapsed_time/0.02));
133 if (sprite->animation_done() || (fabsf(physic.get_velocity_x()) < walk_speed)) be_normal();
138 BadGuy::active_update(elapsed_time);
142 Snail::is_freezable() const
148 Snail::collision_solid(const CollisionHit& hit)
152 WalkingBadguy::collision_solid(hit);
158 WalkingBadguy::collision_solid(hit);
161 if(hit.left || hit.right) {
162 sound_manager->play("sounds/iceblock_bump.wav", get_pos());
164 if( ( dir == LEFT && hit.left ) || ( dir == RIGHT && hit.right) ){
165 dir = (dir == LEFT) ? RIGHT : LEFT;
166 sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
168 physic.set_velocity_x(-physic.get_velocity_x());
173 case STATE_KICKED_DELAY:
174 if(hit.top || hit.bottom) {
175 physic.set_velocity_y(0);
180 update_on_ground_flag(hit);
185 Snail::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
188 return WalkingBadguy::collision_badguy(badguy, hit);
192 return WalkingBadguy::collision_badguy(badguy, hit);
194 case STATE_KICKED_DELAY:
207 Snail::collision_player(Player& player, const CollisionHit& hit)
210 return WalkingBadguy::collision_player(player, hit);
212 // handle kicks from left or right side
213 if(state == STATE_FLAT && (hit.left || hit.right)) {
216 } else if(hit.right) {
224 return BadGuy::collision_player(player, hit);
228 Snail::collision_squished(GameObject& object)
231 return WalkingBadguy::collision_squished(object);
233 Player* player = dynamic_cast<Player*>(&object);
234 if(player && (player->does_buttjump || player->is_invincible())) {
236 player->bounce(*this);
245 // Can't stomp in midair
250 if (squishcount >= MAX_SNAIL_SQUISHES) {
254 sound_manager->play("sounds/stomp.wav", get_pos());
259 sound_manager->play("sounds/kick.wav", get_pos());
261 MovingObject* movingobject = dynamic_cast<MovingObject*>(&object);
262 if (movingobject && (movingobject->get_pos().x < get_pos().x)) {
271 case STATE_KICKED_DELAY:
276 if (player) player->bounce(*this);