7f1bb7eb250e8a4dc342b66a22466cc69e9fe37b
[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   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), state(PRE_THROWING)
46 {
47   physic.enable_gravity(false);
48   sound_manager->preload("sounds/fall.wav");
49   sound_manager->preload("sounds/squish.wav");
50   sound_manager->preload("sounds/dartfire.wav");
51 }
52
53 void
54 Mole::write(lisp::Writer& writer)
55 {
56   writer.start_list("mole");
57   writer.write_float("x", start_position.x);
58   writer.write_float("y", start_position.y);
59   writer.end_list("mole");
60 }
61
62 void
63 Mole::activate()
64 {
65   if (state != DEAD) set_state(PRE_THROWING);
66 }
67
68 void
69 Mole::kill_fall()
70 {
71   set_state(DEAD);
72   sound_manager->play("sounds/fall.wav", get_pos());
73   if (countMe) Sector::current()->get_level()->stats.badguys++;
74 }
75
76 HitResponse
77 Mole::collision_badguy(BadGuy& , const CollisionHit& )
78 {
79   return FORCE_MOVE;
80 }
81
82 bool
83 Mole::collision_squished(GameObject& )
84 {
85   set_state(DEAD);
86   sound_manager->play("sounds/squish.wav", get_pos());
87   if (countMe) Sector::current()->get_level()->stats.badguys++;
88   return true;
89 }
90
91 void
92 Mole::throw_rock()
93 {
94   float px = get_bbox().get_middle().x;
95   float py = get_bbox().get_middle().y;
96
97   float angle = systemRandom.rand(90 - 15, 90 + 15) * (M_PI / 180);
98   float vx = cos(angle) * THROW_VELOCITY;
99   float vy = -sin(angle) * THROW_VELOCITY;
100
101   sound_manager->play("sounds/dartfire.wav", get_pos());
102   Sector::current()->add_object(new MoleRock(Vector(px, py), Vector(vx, vy), this));
103 }
104
105 void
106 Mole::active_update(float elapsed_time)
107 {
108   BadGuy::active_update(elapsed_time);
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 void
142 Mole::set_state(MoleState new_state)
143 {
144   switch (new_state) {
145     case PRE_THROWING:
146       sprite->set_action("idle");
147       set_colgroup_active(COLGROUP_DISABLED);
148       timer.start(IDLE_TIME);
149       break;
150     case THROWING:
151       sprite->set_action("idle");
152       set_colgroup_active(COLGROUP_DISABLED);
153       timer.start(THROW_TIME);
154       throw_timer.start(THROW_INTERVAL);
155       break;
156     case POST_THROWING:
157       sprite->set_action("idle");
158       set_colgroup_active(COLGROUP_DISABLED);
159       timer.start(IDLE_TIME);
160       break;
161     case PEEKING:
162       sprite->set_action("peeking", 1);
163       set_colgroup_active(COLGROUP_STATIC);
164       break;
165     case DEAD:
166       sprite->set_action("idle");
167       set_colgroup_active(COLGROUP_DISABLED);
168       break;
169   }
170
171   state = new_state;
172 }
173
174 IMPLEMENT_FACTORY(Mole, "mole")