1// SuperTux
2// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3//
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.
8//
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.
13//
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/>.
16
17#include "badguy/stalactite.hpp"
18
19#include "audio/sound_manager.hpp"
20#include "editor/editor.hpp"
21#include "math/random.hpp"
22#include "object/bullet.hpp"
23#include "object/player.hpp"
24#include "sprite/sprite.hpp"
25#include "supertux/sector.hpp"
26
27static const int SHAKE_RANGE_X = 40;
28static const float SHAKE_TIME = .8f;
29static const float SHAKE_RANGE_Y = 400;
30
31Stalactite::Stalactite(const ReaderMapping& mapping) :
32 BadGuy(mapping, "images/creatures/stalactite/stalactite.sprite", LAYER_TILES - 1),
33 timer(),
34 state(STALACTITE_HANGING),
35 shake_delta()
36{
37 m_countMe = false;
38 set_colgroup_active(COLGROUP_TOUCHABLE);
39 SoundManager::current()->preload("sounds/cracking.wav");
40 SoundManager::current()->preload("sounds/sizzle.ogg");
41 SoundManager::current()->preload("sounds/icecrash.ogg");
42}
43
44void
45Stalactite::active_update(float dt_sec)
46{
47 if (state == STALACTITE_HANGING) {
48 auto player = get_nearest_player();
49 if (player && !player->get_ghost_mode()) {
50 if (player->get_bbox().get_right() > m_col.m_bbox.get_left() - SHAKE_RANGE_X
51 && player->get_bbox().get_left() < m_col.m_bbox.get_right() + SHAKE_RANGE_X
52 && player->get_bbox().get_bottom() > m_col.m_bbox.get_top()
53 && player->get_bbox().get_top() < m_col.m_bbox.get_bottom() + SHAKE_RANGE_Y
54 && Sector::get().can_see_player(m_col.m_bbox.get_middle())) {
55 timer.start(SHAKE_TIME);
56 state = STALACTITE_SHAKING;
57 SoundManager::current()->play("sounds/cracking.wav", get_pos());
58 }
59 }
60 } else if (state == STALACTITE_SHAKING) {
61 shake_delta = Vector(static_cast<float>(graphicsRandom.rand(-3, 3)), 0.0f);
62 if (timer.check()) {
63 state = STALACTITE_FALLING;
64 m_physic.enable_gravity(true);
65 set_colgroup_active(COLGROUP_MOVING);
66 }
67 } else if (state == STALACTITE_FALLING) {
68 m_col.m_movement = m_physic.get_movement(dt_sec);
69 }
70}
71
72void
73Stalactite::squish()
74{
75 state = STALACTITE_SQUISHED;
76 m_physic.enable_gravity(true);
77 m_physic.set_velocity_x(0);
78 m_physic.set_velocity_y(0);
79 set_state(STATE_SQUISHED);
80 m_sprite->set_action("squished");
81 SoundManager::current()->play("sounds/icecrash.ogg", get_pos());
82 set_group(COLGROUP_MOVING_ONLY_STATIC);
83 run_dead_script();
84}
85
86void
87Stalactite::collision_solid(const CollisionHit& hit)
88{
89 if (state == STALACTITE_FALLING) {
90 if (hit.bottom) squish();
91 }
92 if (state == STALACTITE_SQUISHED) {
93 m_physic.set_velocity_y(0);
94 }
95}
96
97HitResponse
98Stalactite::collision_player(Player& player, const CollisionHit& )
99{
100 if (state != STALACTITE_SQUISHED) {
101 player.kill(false);
102 }
103
104 return FORCE_MOVE;
105}
106
107HitResponse
108Stalactite::collision_badguy(BadGuy& other, const CollisionHit& hit)
109{
110 if (state == STALACTITE_SQUISHED) return FORCE_MOVE;
111
112 // ignore other Stalactites
113 if (dynamic_cast<Stalactite*>(&other)) return FORCE_MOVE;
114
115 if (state != STALACTITE_FALLING) return BadGuy::collision_badguy(other, hit);
116
117 if (other.is_freezable()) {
118 other.freeze();
119 } else {
120 other.kill_fall();
121 }
122
123 return FORCE_MOVE;
124}
125
126HitResponse
127Stalactite::collision_bullet(Bullet& bullet, const CollisionHit& )
128{
129 if (state == STALACTITE_HANGING) {
130 timer.start(SHAKE_TIME);
131 state = STALACTITE_SHAKING;
132 bullet.remove_me();
133 if (bullet.get_type() == FIRE_BONUS)
134 SoundManager::current()->play("sounds/sizzle.ogg", get_pos());
135 SoundManager::current()->play("sounds/cracking.wav", get_pos());
136 }
137
138 return FORCE_MOVE;
139}
140
141void
142Stalactite::kill_fall()
143{
144}
145
146void
147Stalactite::draw(DrawingContext& context)
148{
149 if (Editor::is_active()) {
150 BadGuy::draw(context);
151 return;
152 }
153
154 if (get_state() == STATE_INIT || get_state() == STATE_INACTIVE)
155 return;
156
157 if (state == STALACTITE_SQUISHED) {
158 m_sprite->draw(context.color(), get_pos(), LAYER_OBJECTS);
159 } else if (state == STALACTITE_SHAKING) {
160 m_sprite->draw(context.color(), get_pos() + shake_delta, m_layer);
161 } else {
162 m_sprite->draw(context.color(), get_pos(), m_layer);
163 }
164}
165
166void
167Stalactite::deactivate()
168{
169 if (state != STALACTITE_HANGING)
170 remove_me();
171}
172
173/* EOF */
174