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