Merged changes from branches/supertux-milestone2-grumbel/ to trunk/supertux/
[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 IDLE_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   sound_manager->preload("sounds/fall.wav");
40   sound_manager->preload("sounds/squish.wav");
41   sound_manager->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   sound_manager->preload("sounds/fall.wav");
52   sound_manager->preload("sounds/squish.wav");
53   sound_manager->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   sound_manager->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   set_state(DEAD);
80   sound_manager->play("sounds/squish.wav", get_pos());
81   run_dead_script();
82   return true;
83 }
84
85 void
86 Mole::throw_rock()
87 {
88   float px = get_bbox().get_middle().x;
89   float py = get_bbox().get_middle().y;
90
91   float angle = systemRandom.rand(90 - 15, 90 + 15) * (M_PI / 180);
92   float vx = cos(angle) * THROW_VELOCITY;
93   float vy = -sin(angle) * THROW_VELOCITY;
94
95   sound_manager->play("sounds/dartfire.wav", get_pos());
96   Sector::current()->add_object(new MoleRock(Vector(px, py), Vector(vx, vy), this));
97 }
98
99 void
100 Mole::active_update(float elapsed_time)
101 {
102   BadGuy::active_update(elapsed_time);
103
104   switch (state) {
105     case PRE_THROWING:
106       if (timer.check()) {
107         set_state(THROWING);
108       }
109       break;
110     case THROWING:
111       if (throw_timer.check()) {
112         throw_rock();
113         throw_timer.start(THROW_INTERVAL);
114       }
115       if (timer.check()) {
116         set_state(POST_THROWING);
117       }
118       break;
119     case POST_THROWING:
120       if (timer.check()) {
121         set_state(PEEKING);
122       }
123       break;
124     case PEEKING:
125       if (sprite->animation_done()) {
126         set_state(PRE_THROWING);
127       }
128       break;
129     case DEAD:
130       break;
131   }
132
133 }
134
135 void
136 Mole::set_state(MoleState new_state)
137 {
138   switch (new_state) {
139     case PRE_THROWING:
140       sprite->set_action("idle");
141       set_colgroup_active(COLGROUP_DISABLED);
142       timer.start(IDLE_TIME);
143       break;
144     case THROWING:
145       sprite->set_action("idle");
146       set_colgroup_active(COLGROUP_DISABLED);
147       timer.start(THROW_TIME);
148       throw_timer.start(THROW_INTERVAL);
149       break;
150     case POST_THROWING:
151       sprite->set_action("idle");
152       set_colgroup_active(COLGROUP_DISABLED);
153       timer.start(IDLE_TIME);
154       break;
155     case PEEKING:
156       sprite->set_action("peeking", 1);
157       set_colgroup_active(COLGROUP_STATIC);
158       break;
159     case DEAD:
160       sprite->set_action("idle");
161       set_colgroup_active(COLGROUP_DISABLED);
162       break;
163   }
164
165   state = new_state;
166 }
167
168 IMPLEMENT_FACTORY(Mole, "mole");
169
170 /* EOF */