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