1 // IceCrusher - A block to stand on, which can drop down to crush the player
2 // Copyright (C) 2008 Christoph Sommer <christoph.sommer@2008.expires.deltadevelopment.de>
3 // Copyright (C) 2010 Florian Forster <supertux at octo.it>
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 "object/icecrusher.hpp"
20 #include "badguy/badguy.hpp"
21 #include "sprite/sprite.hpp"
22 #include "object/player.hpp"
23 #include "supertux/object_factory.hpp"
24 #include "supertux/sector.hpp"
27 /* Maximum movement speed in pixels per LOGICAL_FPS */
28 const float MAX_DROP_SPEED = 10.0;
29 const float RECOVER_SPEED = -3.125;
30 const float DROP_ACTIVATION_DISTANCE = 4.0;
31 const float PAUSE_TIME = 0.5;
34 IceCrusher::IceCrusher(const Reader& reader) :
35 MovingSprite(reader, "images/creatures/icecrusher/icecrusher.sprite", LAYER_OBJECTS, COLGROUP_STATIC),
41 start_position = get_bbox().p1;
42 set_state(state, true);
46 IceCrusher::IceCrusher(const IceCrusher& other)
47 : MovingSprite(other),
48 state(other.state), speed(other.speed)
50 start_position = get_bbox().p1;
51 set_state(state, true);
55 IceCrusher::set_state(IceCrusherState state, bool force)
57 if ((this->state == state) && (!force)) return;
60 set_group(COLGROUP_STATIC);
61 physic.enable_gravity (false);
62 sprite->set_action("idle");
65 set_group(COLGROUP_MOVING_STATIC);
67 physic.enable_gravity (true);
68 sprite->set_action("crushing");
71 set_group(COLGROUP_MOVING_STATIC);
72 physic.enable_gravity (false);
73 sprite->set_action("recovering");
76 log_debug << "IceCrusher in invalid state" << std::endl;
83 IceCrusher::collision(GameObject& other, const CollisionHit& hit)
85 Player* player = dynamic_cast<Player*>(&other);
87 /* If the other object is the player, and the collision is at the bottom of
88 * the ice crusher, hurt the player. */
89 if (player && hit.bottom) {
90 if(player->is_invincible()) {
91 if (state == CRUSHING)
92 set_state(RECOVERING);
96 if (state == CRUSHING)
97 set_state(RECOVERING);
100 BadGuy* badguy = dynamic_cast<BadGuy*>(&other);
108 IceCrusher::collision_solid(const CollisionHit& hit)
115 cooldown_timer = PAUSE_TIME;
116 set_state(RECOVERING);
122 log_debug << "IceCrusher in invalid state" << std::endl;
128 IceCrusher::update(float elapsed_time)
130 if (cooldown_timer >= elapsed_time)
132 cooldown_timer -= elapsed_time;
135 else if (cooldown_timer != 0.0)
137 elapsed_time -= cooldown_timer;
138 cooldown_timer = 0.0;
143 movement = Vector (0, 0);
148 movement = physic.get_movement (elapsed_time);
149 if (movement.y > MAX_DROP_SPEED)
150 movement.y = MAX_DROP_SPEED;
153 if (get_bbox().p1.y <= start_position.y+1) {
154 set_pos(start_position);
155 movement = Vector (0, 0);
156 cooldown_timer = PAUSE_TIME;
160 movement = Vector (0, RECOVER_SPEED);
164 log_debug << "IceCrusher in invalid state" << std::endl;
170 IceCrusher::found_victim()
172 Player* player = Sector::current()->get_nearest_player (this->get_bbox ());
173 if (!player) return false;
175 const Rectf& player_bbox = player->get_bbox();
176 const Rectf& crusher_bbox = get_bbox();
177 if ((player_bbox.p1.y >= crusher_bbox.p2.y) /* player is below crusher */
178 && (player_bbox.p2.x > (crusher_bbox.p1.x - DROP_ACTIVATION_DISTANCE))
179 && (player_bbox.p1.x < (crusher_bbox.p2.x + DROP_ACTIVATION_DISTANCE)))