2 // Copyright (C) 2006 Matthias Braun <matze@braunis.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/mriceblock.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 KICKSPEED = 500;
28 const int MAXSQUISHES = 10;
29 const float NOKICK_TIME = 0.1f;
32 MrIceBlock::MrIceBlock(const Reader& reader) :
33 WalkingBadguy(reader, "images/creatures/mr_iceblock/mr_iceblock.sprite", "left", "right"),
34 ice_state(ICESTATE_NORMAL),
40 max_drop_height = 600;
41 sound_manager->preload("sounds/iceblock_bump.wav");
42 sound_manager->preload("sounds/stomp.wav");
43 sound_manager->preload("sounds/kick.wav");
46 MrIceBlock::MrIceBlock(const Vector& pos, Direction d) :
47 WalkingBadguy(pos, d, "images/creatures/mr_iceblock/mr_iceblock.sprite", "left", "right"),
48 ice_state(ICESTATE_NORMAL),
54 max_drop_height = 600;
55 sound_manager->preload("sounds/iceblock_bump.wav");
56 sound_manager->preload("sounds/stomp.wav");
57 sound_manager->preload("sounds/kick.wav");
61 MrIceBlock::initialize()
63 WalkingBadguy::initialize();
64 set_state(ICESTATE_NORMAL);
68 MrIceBlock::active_update(float elapsed_time)
70 if(ice_state == ICESTATE_GRABBED)
73 if(ice_state == ICESTATE_FLAT && flat_timer.check()) {
74 set_state(ICESTATE_NORMAL);
77 if (ice_state == ICESTATE_NORMAL)
79 WalkingBadguy::active_update(elapsed_time);
83 BadGuy::active_update(elapsed_time);
87 MrIceBlock::can_break(){
88 return ice_state == ICESTATE_KICKED;
92 MrIceBlock::collision_solid(const CollisionHit& hit)
94 update_on_ground_flag(hit);
96 if(hit.top || hit.bottom) { // floor or roof
97 physic.set_velocity_y(0);
102 case ICESTATE_NORMAL:
103 WalkingBadguy::collision_solid(hit);
105 case ICESTATE_KICKED: {
106 if((hit.right && dir == RIGHT) || (hit.left && dir == LEFT)) {
107 dir = (dir == LEFT) ? RIGHT : LEFT;
108 sound_manager->play("sounds/iceblock_bump.wav", get_pos());
109 physic.set_velocity_x(-physic.get_velocity_x()*.975);
111 this->set_action(dir == LEFT ? "flat-left" : "flat-right", /* loops = */ -1);
112 if(fabsf(physic.get_velocity_x()) < walk_speed*1.5)
113 set_state(ICESTATE_NORMAL);
117 physic.set_velocity_x(0);
119 case ICESTATE_GRABBED:
125 MrIceBlock::collision(GameObject& object, const CollisionHit& hit)
127 if(ice_state == ICESTATE_GRABBED)
130 return BadGuy::collision(object, hit);
134 MrIceBlock::collision_player(Player& player, const CollisionHit& hit)
136 // handle kicks from left or right side
137 if(ice_state == ICESTATE_FLAT && get_state() == STATE_ACTIVE) {
141 set_state(ICESTATE_KICKED);
143 } else if(hit.right) {
146 set_state(ICESTATE_KICKED);
151 return BadGuy::collision_player(player, hit);
155 MrIceBlock::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
158 case ICESTATE_NORMAL:
159 return WalkingBadguy::collision_badguy(badguy, hit);
162 case ICESTATE_KICKED:
173 MrIceBlock::collision_squished(GameObject& object)
175 Player* player = dynamic_cast<Player*>(&object);
176 if(player && (player->does_buttjump || player->is_invincible())) {
177 player->bounce(*this);
183 case ICESTATE_KICKED:
185 BadGuy* badguy = dynamic_cast<BadGuy*>(&object);
193 case ICESTATE_NORMAL:
196 if (squishcount >= MAXSQUISHES) {
202 set_state(ICESTATE_FLAT);
203 nokick_timer.start(NOKICK_TIME);
207 MovingObject* movingobject = dynamic_cast<MovingObject*>(&object);
208 if (movingobject && (movingobject->get_pos().x < get_pos().x)) {
214 if (nokick_timer.check()) set_state(ICESTATE_KICKED);
216 case ICESTATE_GRABBED:
221 if (player) player->bounce(*this);
226 MrIceBlock::set_state(IceState state, bool up)
228 if(ice_state == state)
232 case ICESTATE_NORMAL:
233 this->set_action(dir == LEFT ? "left" : "right", /* loops = */ -1);
234 WalkingBadguy::initialize();
238 physic.set_velocity_y(-KICKSPEED);
240 sound_manager->play("sounds/stomp.wav", get_pos());
241 physic.set_velocity_x(0);
242 physic.set_velocity_y(0);
244 this->set_action(dir == LEFT ? "flat-left" : "flat-right", /* loops = */ -1);
247 case ICESTATE_KICKED:
248 sound_manager->play("sounds/kick.wav", get_pos());
250 physic.set_velocity_x(dir == LEFT ? -KICKSPEED : KICKSPEED);
251 this->set_action(dir == LEFT ? "flat-left" : "flat-right", /* loops = */ -1);
252 // we should slide above 1 block holes now...
253 bbox.set_size(34, 31.8f);
255 case ICESTATE_GRABBED:
265 MrIceBlock::grab(MovingObject&, const Vector& pos, Direction dir)
267 movement = pos - get_pos();
269 this->set_action(dir == LEFT ? "flat-left" : "flat-right", /* loops = */ -1);
270 set_state(ICESTATE_GRABBED);
271 set_colgroup_active(COLGROUP_DISABLED);
275 MrIceBlock::ungrab(MovingObject& , Direction dir)
278 set_state(ICESTATE_FLAT, true);
281 set_state(ICESTATE_KICKED);
283 set_colgroup_active(COLGROUP_MOVING);
287 MrIceBlock::is_portable() const
289 return ice_state == ICESTATE_FLAT;