Merged changes from branches/supertux-milestone2-grumbel/ to trunk/supertux/
[supertux.git] / src / badguy / angrystone.cpp
1 //  AngryStone - A spiked block that charges towards the player
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 "badguy/angrystone.hpp"
18
19 #include "object/player.hpp"
20 #include "sprite/sprite.hpp"
21 #include "supertux/object_factory.hpp"
22
23 static const float SPEED = 240;
24
25 static const float CHARGE_TIME = .5;
26 static const float ATTACK_TIME = 1;
27 static const float RECOVER_TIME = .5;
28
29 AngryStone::AngryStone(const Reader& reader) :
30   BadGuy(reader, "images/creatures/angrystone/angrystone.sprite"), 
31   attackDirection(),
32   oldWallDirection(),
33   timer(),
34   state(IDLE)
35 {
36   physic.set_velocity_x(0);
37   physic.set_velocity_y(0);
38   physic.enable_gravity(true);
39   sprite->set_action("idle");
40 }
41
42 void
43 AngryStone::collision_solid(const CollisionHit& hit)
44 {
45   // TODO
46   (void) hit;
47 #if 0
48   if ((state == ATTACKING) &&
49       (hit.normal.x == -attackDirection.x) && (hit.normal.y == attackDirection.y)) {
50     state = IDLE;
51     sprite->set_action("idle");
52     physic.set_velocity_x(0);
53     physic.set_velocity_y(0);
54     physic.enable_gravity(true);
55     oldWallDirection.x = attackDirection.x;
56     oldWallDirection.y = attackDirection.y;
57   }
58 #endif
59 }
60
61 void
62 AngryStone::kill_fall()
63 {
64   //prevents AngryStone from getting killed by other enemies or the player
65 }
66
67 HitResponse
68 AngryStone::collision_badguy(BadGuy& badguy, const CollisionHit& )
69 {
70   if (state == ATTACKING) {
71     badguy.kill_fall();
72     return FORCE_MOVE;
73   }
74
75   return FORCE_MOVE;
76 }
77
78 void
79 AngryStone::active_update(float elapsed_time) {
80   BadGuy::active_update(elapsed_time);
81
82   if (state == IDLE) {
83     MovingObject* player = this->get_nearest_player();
84     if(player) {
85       MovingObject* badguy = this;
86       const Vector playerPos = player->get_pos();
87       const Vector badguyPos = badguy->get_pos();
88       float dx = (playerPos.x - badguyPos.x);
89       float dy = (playerPos.y - badguyPos.y);
90
91       float playerHeight = player->get_bbox().p2.y - player->get_bbox().p1.y;
92       float badguyHeight = badguy->get_bbox().p2.y - badguy->get_bbox().p1.y;
93
94       float playerWidth = player->get_bbox().p2.x - player->get_bbox().p1.x;
95       float badguyWidth = badguy->get_bbox().p2.x - badguy->get_bbox().p1.x;
96
97       if ((dx > -playerWidth) && (dx < badguyWidth)) {
98         if (dy > 0) {
99           attackDirection.x = 0;
100           attackDirection.y = 1;
101         } else {
102           attackDirection.x = 0;
103           attackDirection.y = -1;
104         }
105         if ((attackDirection.x != oldWallDirection.x) || (attackDirection.y != oldWallDirection.y)) {
106           sprite->set_action("charging");
107           timer.start(CHARGE_TIME);
108           state = CHARGING;
109         }
110       } else
111         if ((dy > -playerHeight) && (dy < badguyHeight)) {
112           if (dx > 0) {
113             attackDirection.x = 1;
114             attackDirection.y = 0;
115           } else {
116             attackDirection.x = -1;
117             attackDirection.y = 0;
118           }
119           if ((attackDirection.x != oldWallDirection.x) || (attackDirection.y != oldWallDirection.y)) {
120             sprite->set_action("charging");
121             timer.start(CHARGE_TIME);
122             state = CHARGING;
123           }
124         }
125
126     }
127   }
128
129   if (state == CHARGING) {
130     if (timer.check()) {
131       sprite->set_action("attacking");
132       timer.start(ATTACK_TIME);
133       state = ATTACKING;
134       physic.enable_gravity(false);
135       physic.set_velocity_x(SPEED * attackDirection.x);
136       physic.set_velocity_y(SPEED * attackDirection.y);
137       oldWallDirection.x = 0;
138       oldWallDirection.y = 0;
139     }
140   }
141
142   if (state == ATTACKING) {
143     if (timer.check()) {
144       timer.start(RECOVER_TIME);
145       state = RECOVERING;
146       sprite->set_action("idle");
147       physic.enable_gravity(true);
148       physic.set_velocity_x(0);
149       physic.set_velocity_y(0);
150     }
151   }
152
153   if (state == RECOVERING) {
154     if (timer.check()) {
155       state = IDLE;
156       sprite->set_action("idle");
157       physic.enable_gravity(true);
158       physic.set_velocity_x(0);
159       physic.set_velocity_y(0);
160     }
161   }
162
163 }
164
165 IMPLEMENT_FACTORY(AngryStone, "angrystone");
166
167 /* EOF */