f151b67b8ea6c975c2d84e8733ad445a2e732515
[supertux.git] / src / badguy / stalactite.cpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2006 Matthias Braun <matze@braunis.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 "stalactite.hpp"
23
24 #include "random_generator.hpp"
25 #include "lisp/writer.hpp"
26 #include "object_factory.hpp"
27 #include "object/player.hpp"
28 #include "sprite/sprite.hpp"
29
30 static const int SHAKE_RANGE_X = 40;
31 static const float SHAKE_TIME = .8f;
32 static const float SQUISH_TIME = 2;
33 static const float SHAKE_RANGE_Y = 400;
34
35 Stalactite::Stalactite(const lisp::Lisp& lisp)
36         : BadGuy(lisp, "images/creatures/stalactite/stalactite.sprite", LAYER_TILES - 1), state(STALACTITE_HANGING)
37 {
38   countMe = false;
39 }
40
41 void
42 Stalactite::write(lisp::Writer& writer)
43 {
44   writer.start_list("stalactite");
45   writer.write("x", start_position.x);
46   writer.write("y", start_position.y);
47   writer.end_list("stalactite");
48 }
49
50 void
51 Stalactite::active_update(float elapsed_time)
52 {
53   if(state == STALACTITE_HANGING) {
54     Player* player = this->get_nearest_player();
55     if (player) {
56       if(player->get_bbox().p2.x > bbox.p1.x - SHAKE_RANGE_X
57           && player->get_bbox().p1.x < bbox.p2.x + SHAKE_RANGE_X
58           && player->get_bbox().p2.y > bbox.p1.y
59           && player->get_bbox().p1.y < bbox.p2.y + SHAKE_RANGE_Y) {
60         timer.start(SHAKE_TIME);
61         state = STALACTITE_SHAKING;
62       }
63     }
64   } else if(state == STALACTITE_SHAKING) {
65     if(timer.check()) {
66       state = STALACTITE_FALLING;
67       physic.enable_gravity(true);
68     }
69   } else if(state == STALACTITE_FALLING || state == STALACTITE_SQUISHED) {
70     movement = physic.get_movement(elapsed_time);
71     if(state == STALACTITE_SQUISHED && timer.check())
72       remove_me();
73   }
74 }
75
76 void
77 Stalactite::squish()
78 {
79   state = STALACTITE_SQUISHED;
80   set_colgroup_active(COLGROUP_MOVING_ONLY_STATIC);
81   sprite->set_action("squished");
82   if(!timer.started())
83     timer.start(SQUISH_TIME);
84 }
85
86 void
87 Stalactite::collision_solid(const CollisionHit& hit)
88 {
89   if(state == STALACTITE_FALLING) {
90     if (hit.bottom) squish();
91   }
92   if(state == STALACTITE_SQUISHED) {
93     physic.set_velocity_y(0);
94   }
95 }
96
97 HitResponse
98 Stalactite::collision_player(Player& player)
99 {
100   if(state != STALACTITE_SQUISHED) {
101     player.kill(false);
102   }
103
104   return FORCE_MOVE;
105 }
106
107 HitResponse
108 Stalactite::collision_badguy(BadGuy& other, const CollisionHit& hit)
109 {
110   if (state == STALACTITE_SQUISHED) return FORCE_MOVE;
111   if (state != STALACTITE_FALLING) return BadGuy::collision_badguy(other, hit);
112
113   // ignore other Stalactites
114   if (dynamic_cast<Stalactite*>(&other)) return FORCE_MOVE;
115
116   if (other.is_freezable()) {
117     other.freeze();
118   } else {
119     other.kill_fall();
120   }
121
122   remove_me();
123
124   return FORCE_MOVE;
125 }
126
127 void
128 Stalactite::kill_fall()
129 {
130 }
131
132 void
133 Stalactite::draw(DrawingContext& context)
134 {
135   if(get_state() != STATE_ACTIVE)
136     return;
137
138
139   if(state == STALACTITE_SQUISHED) {
140     sprite->draw(context, get_pos(), LAYER_OBJECTS);
141     return;
142   }
143
144   if(state == STALACTITE_SHAKING) {
145     sprite->draw(context, get_pos() + Vector(systemRandom.rand(-3,3), 0), layer);
146   } else {
147     sprite->draw(context, get_pos(), layer);
148   }
149 }
150
151 void
152 Stalactite::deactivate()
153 {
154   if(state != STALACTITE_HANGING)
155     remove_me();
156 }
157
158 IMPLEMENT_FACTORY(Stalactite, "stalactite")