Renamed Rect to Rectf
[supertux.git] / src / object / icecrusher.cpp
1 //  IceCrusher - A block to stand on, which can drop down to crush the player
2 //  Copyright (C) 2008 Christoph Sommer <christoph.sommer@2008.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 "object/icecrusher.hpp"
18
19 #include "badguy/badguy.hpp"
20 #include "sprite/sprite.hpp"
21 #include "object/player.hpp"
22 #include "supertux/object_factory.hpp"
23 #include "supertux/sector.hpp"
24
25 namespace {
26 const float DROP_SPEED = 500;
27 const float RECOVER_SPEED = 200;
28 }
29
30 IceCrusher::IceCrusher(const Reader& reader) :
31   MovingSprite(reader, "images/creatures/icecrusher/icecrusher.sprite", LAYER_OBJECTS, COLGROUP_STATIC), 
32   state(IDLE), 
33   start_position(),
34   speed(Vector(0,0))
35 {
36   start_position = get_bbox().p1;
37   set_state(state, true);
38 }
39
40 /*
41   IceCrusher::IceCrusher(const IceCrusher& other)
42   : MovingSprite(other), 
43   state(other.state), speed(other.speed) 
44   {
45   start_position = get_bbox().p1;
46   set_state(state, true);
47   }
48 */
49 void 
50 IceCrusher::set_state(IceCrusherState state, bool force) 
51 {
52   if ((this->state == state) && (!force)) return;
53   switch(state) {
54     case IDLE:
55       set_group(COLGROUP_STATIC);
56       speed=Vector(0,0);
57       sprite->set_action("idle");
58       break;
59     case CRUSHING:
60       set_group(COLGROUP_MOVING_STATIC);
61       speed=Vector(0, DROP_SPEED);
62       sprite->set_action("idle");
63       break;
64     case RECOVERING:
65       set_group(COLGROUP_MOVING_STATIC);
66       speed=Vector(0, -RECOVER_SPEED);
67       sprite->set_action("idle");
68       break;
69     default:
70       log_debug << "IceCrusher in invalid state" << std::endl;
71       break;
72   }
73   this->state = state;
74 }
75
76 HitResponse
77 IceCrusher::collision(GameObject& other, const CollisionHit& hit)
78 {
79   Player* player = dynamic_cast<Player*>(&other);
80   if (player && hit.bottom) {
81     if(player->is_invincible()) {
82       if (state == CRUSHING) set_state(RECOVERING);
83       return ABORT_MOVE;
84     }
85     player->kill(false);
86     if (state == CRUSHING) set_state(RECOVERING);
87     return FORCE_MOVE;
88   }
89   BadGuy* badguy = dynamic_cast<BadGuy*>(&other);
90   if (badguy) {
91     badguy->kill_fall();
92   }
93   return FORCE_MOVE;
94 }
95     
96 void 
97 IceCrusher::collision_solid(const CollisionHit& )
98 {
99   switch(state) {
100     case IDLE:
101       break;
102     case CRUSHING:
103       set_state(RECOVERING);
104       break;
105     case RECOVERING:
106       break;
107     default:
108       log_debug << "IceCrusher in invalid state" << std::endl;
109       break;
110   }
111 }
112
113 void
114 IceCrusher::update(float elapsed_time)
115 {
116   switch(state) {
117     case IDLE:
118       if (found_victim()) set_state(CRUSHING);
119       break;
120     case CRUSHING:
121       break;
122     case RECOVERING:
123       if (get_bbox().p1.y <= start_position.y+1) {
124         set_pos(start_position);
125         set_state(IDLE);
126       }
127       break;
128     default:
129       log_debug << "IceCrusher in invalid state" << std::endl;
130       break;
131   }
132   movement = speed * elapsed_time;
133 }
134
135 Player*
136 IceCrusher::get_nearest_player()
137 {
138   // FIXME: does not really return nearest player
139
140   std::vector<Player*> players = Sector::current()->get_players();
141   for (std::vector<Player*>::iterator playerIter = players.begin(); playerIter != players.end(); ++playerIter) {
142     Player* player = *playerIter;
143     if (player->is_dying() || player->is_dead()) continue;
144     return player;
145   }
146
147   return 0;
148 }
149
150 bool
151 IceCrusher::found_victim()
152 {
153   Player* player = this->get_nearest_player();
154   if (!player) return false;
155
156   const Rectf& pr = player->get_bbox();
157   const Rectf& br = get_bbox();
158   if ((pr.p2.x > br.p1.x) && (pr.p1.x < br.p2.x) && (pr.p1.y >= br.p2.y)) {
159     return true;
160   }
161   return false;
162 }
163
164 /* EOF */