1// SuperTux - Mole Badguy
2// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.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/mole.hpp"
18
19#include <math.h>
20
21#include "audio/sound_manager.hpp"
22#include "badguy/mole_rock.hpp"
23#include "math/random.hpp"
24#include "math/util.hpp"
25#include "sprite/sprite.hpp"
26#include "supertux/sector.hpp"
27
28static const float MOLE_WAIT_TIME = 0.2f; /**< time to wait before and after throwing */
29static const float THROW_TIME = 4.6f; /**< time to spend throwing */
30static const float THROW_INTERVAL = 1; /**< time between two thrown rocks */
31static const float THROW_VELOCITY = 400; /**< initial velocity of thrown rocks */
32
33Mole::Mole(const ReaderMapping& reader) :
34 BadGuy(reader, "images/creatures/mole/mole.sprite", LAYER_TILES-1),
35 state(PRE_THROWING),
36 timer(),
37 throw_timer()
38{
39 m_physic.enable_gravity(false);
40 SoundManager::current()->preload("sounds/fall.wav");
41 SoundManager::current()->preload("sounds/squish.wav");
42 SoundManager::current()->preload("sounds/dartfire.wav");
43}
44
45void
46Mole::activate()
47{
48 if (state != DEAD) set_state(PRE_THROWING);
49}
50
51void
52Mole::kill_fall()
53{
54 set_state(DEAD);
55 SoundManager::current()->play("sounds/fall.wav", get_pos());
56 run_dead_script();
57}
58
59HitResponse
60Mole::collision_badguy(BadGuy& , const CollisionHit& )
61{
62 return FORCE_MOVE;
63}
64
65bool
66Mole::collision_squished(GameObject& )
67{
68 if (m_frozen) {
69 unfreeze();
70 }
71
72 set_state(DEAD);
73 SoundManager::current()->play("sounds/squish.wav", get_pos());
74 run_dead_script();
75 return true;
76}
77
78void
79Mole::throw_rock()
80{
81 float angle = math::radians(gameRandom.randf(90.0f - 15.0f, 90.0f + 15.0f));
82 float vx = cosf(angle) * THROW_VELOCITY;
83 float vy = -sinf(angle) * THROW_VELOCITY;
84
85 SoundManager::current()->play("sounds/dartfire.wav", get_pos());
86 Sector::get().add<MoleRock>(m_col.m_bbox.get_middle(), Vector(vx, vy), this);
87}
88
89void
90Mole::active_update(float dt_sec)
91{
92 BadGuy::active_update(dt_sec);
93
94 if (m_frozen)
95 return;
96
97 switch (state) {
98 case PRE_THROWING:
99 if (timer.check()) {
100 set_state(THROWING);
101 }
102 break;
103 case THROWING:
104 if (throw_timer.check()) {
105 throw_rock();
106 throw_timer.start(THROW_INTERVAL);
107 }
108 if (timer.check()) {
109 set_state(POST_THROWING);
110 }
111 break;
112 case POST_THROWING:
113 if (timer.check()) {
114 set_state(PEEKING);
115 }
116 break;
117 case PEEKING:
118 if (m_sprite->animation_done()) {
119 set_state(PRE_THROWING);
120 }
121 break;
122 case BURNING:
123 if (m_sprite->animation_done()) {
124 set_state(DEAD);
125 }
126 break;
127 case DEAD:
128 break;
129 }
130
131}
132
133bool
134Mole::is_freezable() const
135{
136 return true;
137}
138
139void
140Mole::set_state(MoleState new_state)
141{
142 if (m_frozen)
143 return;
144
145 switch (new_state) {
146 case PRE_THROWING:
147 m_sprite->set_action("idle");
148 set_colgroup_active(COLGROUP_DISABLED);
149 timer.start(MOLE_WAIT_TIME);
150 break;
151 case THROWING:
152 m_sprite->set_action("idle");
153 set_colgroup_active(COLGROUP_DISABLED);
154 timer.start(THROW_TIME);
155 throw_timer.start(THROW_INTERVAL);
156 break;
157 case POST_THROWING:
158 m_sprite->set_action("idle");
159 set_colgroup_active(COLGROUP_DISABLED);
160 timer.start(MOLE_WAIT_TIME);
161 break;
162 case PEEKING:
163 m_sprite->set_action("peeking", 1);
164 set_colgroup_active(COLGROUP_STATIC);
165 break;
166 case DEAD:
167 m_sprite->set_action("idle");
168 set_colgroup_active(COLGROUP_DISABLED);
169 break;
170 case BURNING:
171 m_sprite->set_action("burning", 1);
172 set_colgroup_active(COLGROUP_DISABLED);
173 break;
174 }
175
176 state = new_state;
177}
178
179void
180Mole::ignite() {
181 set_state(BURNING);
182 run_dead_script();
183 SoundManager::current()->play("sounds/fire.ogg", get_pos());
184}
185
186/* EOF */
187