73c1877412ada4060561932c8bb26e82108e5708
[supertux.git] / src / badguy / mole.cpp
1 //  $Id$
2 //
3 //  SuperTux - Mole Badguy
4 //  Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 #include <config.h>
21
22 #include "mole.hpp"
23 #include "mole_rock.hpp"
24 #include "tile.hpp"
25 #include "object/tilemap.hpp"
26 #include "random_generator.hpp"
27 #include "log.hpp"
28 #include "level.hpp"
29
30 static const float IDLE_TIME = 0.2f; /**< time to wait before and after throwing */
31 static const float THROW_TIME = 4.6f; /**< time to spend throwing */
32 static const float THROW_INTERVAL = 1; /**< time between two thrown rocks */
33 static const float THROW_VELOCITY = 400; /**< initial velocity of thrown rocks */
34
35 Mole::Mole(const lisp::Lisp& reader)
36         : BadGuy(reader, "images/creatures/mole/mole.sprite", LAYER_TILES-1), state(PRE_THROWING)
37 {
38   physic.enable_gravity(false);
39 }
40
41 Mole::Mole(const Vector& pos)
42         : BadGuy(pos, "images/creatures/mole/mole.sprite", LAYER_TILES-1), state(PRE_THROWING)
43 {
44   physic.enable_gravity(false);
45 }
46
47 void
48 Mole::write(lisp::Writer& writer)
49 {
50   writer.start_list("mole");
51   writer.write_float("x", start_position.x);
52   writer.write_float("y", start_position.y);
53   writer.end_list("mole");
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   if (countMe) Sector::current()->get_level()->stats.badguys++;
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   if (countMe) Sector::current()->get_level()->stats.badguys++;
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_group(COLGROUP_DISABLED);
142       timer.start(IDLE_TIME);
143       break;
144     case THROWING:
145       sprite->set_action("idle");
146       set_group(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_group(COLGROUP_DISABLED);
153       timer.start(IDLE_TIME);
154       break;
155     case PEEKING:
156       sprite->set_action("peeking", 1);
157       set_group(COLGROUP_STATIC);
158       break;
159     case DEAD:
160       sprite->set_action("idle");
161       set_group(COLGROUP_DISABLED);
162       break;
163   }
164
165   state = new_state;
166 }
167
168 IMPLEMENT_FACTORY(Mole, "mole")
169