3e00acd5bb64a89b2b490719eff25cafe89b9c34
[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 <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
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   physic.set_velocity_x(0);
35   physic.set_velocity_y(0);
36   physic.enable_gravity(true);
37   sprite->set_action("idle");
38 }
39
40 void
41 AngryStone::write(lisp::Writer& writer)
42 {
43   writer.start_list("angrystone");
44
45   writer.write("x", start_position.x);
46   writer.write("y", start_position.y);
47
48   writer.end_list("angrystone");
49 }
50
51 void
52 AngryStone::collision_solid(const CollisionHit& hit)
53 {
54   // TODO
55   (void) hit;
56 #if 0
57   if ((state == ATTACKING) &&
58       (hit.normal.x == -attackDirection.x) && (hit.normal.y == attackDirection.y)) {
59     state = IDLE;
60     sprite->set_action("idle");
61     physic.set_velocity_x(0);
62     physic.set_velocity_y(0);
63     physic.enable_gravity(true);
64     oldWallDirection.x = attackDirection.x;
65     oldWallDirection.y = attackDirection.y;
66   }
67 #endif
68 }
69
70 void
71 AngryStone::kill_fall()
72 {
73   //prevents AngryStone from getting killed by other enemies or the player
74 }
75
76 HitResponse
77 AngryStone::collision_badguy(BadGuy& badguy, const CollisionHit& )
78 {
79   if (state == ATTACKING) {
80     badguy.kill_fall();
81     return FORCE_MOVE;
82   }
83
84   return FORCE_MOVE;
85 }
86
87 void
88 AngryStone::active_update(float elapsed_time) {
89   BadGuy::active_update(elapsed_time);
90
91   if (state == IDLE) {
92     MovingObject* player = this->get_nearest_player();
93     MovingObject* badguy = this;
94     const Vector playerPos = player->get_pos();
95     const Vector badguyPos = badguy->get_pos();
96     float dx = (playerPos.x - badguyPos.x);
97     float dy = (playerPos.y - badguyPos.y);
98
99     float playerHeight = player->get_bbox().p2.y - player->get_bbox().p1.y;
100     float badguyHeight = badguy->get_bbox().p2.y - badguy->get_bbox().p1.y;
101
102     float playerWidth = player->get_bbox().p2.x - player->get_bbox().p1.x;
103     float badguyWidth = badguy->get_bbox().p2.x - badguy->get_bbox().p1.x;
104
105     if ((dx > -playerWidth) && (dx < badguyWidth)) {
106       if (dy > 0) {
107         attackDirection.x = 0;
108         attackDirection.y = 1;
109       } else {
110         attackDirection.x = 0;
111         attackDirection.y = -1;
112       }
113       if ((attackDirection.x != oldWallDirection.x) || (attackDirection.y != oldWallDirection.y)) {
114         sprite->set_action("charging");
115         timer.start(CHARGE_TIME);
116         state = CHARGING;
117       }
118     } else
119     if ((dy > -playerHeight) && (dy < badguyHeight)) {
120       if (dx > 0) {
121         attackDirection.x = 1;
122         attackDirection.y = 0;
123       } else {
124         attackDirection.x = -1;
125         attackDirection.y = 0;
126       }
127       if ((attackDirection.x != oldWallDirection.x) || (attackDirection.y != oldWallDirection.y)) {
128         sprite->set_action("charging");
129         timer.start(CHARGE_TIME);
130         state = CHARGING;
131       }
132     }
133
134   }
135
136   if (state == CHARGING) {
137     if (timer.check()) {
138       sprite->set_action("attacking");
139       timer.start(ATTACK_TIME);
140       state = ATTACKING;
141       physic.enable_gravity(false);
142       physic.set_velocity_x(SPEED * attackDirection.x);
143       physic.set_velocity_y(SPEED * attackDirection.y);
144       oldWallDirection.x = 0;
145       oldWallDirection.y = 0;
146     }
147   }
148
149   if (state == ATTACKING) {
150     if (timer.check()) {
151       timer.start(RECOVER_TIME);
152       state = RECOVERING;
153       sprite->set_action("idle");
154       physic.enable_gravity(true);
155       physic.set_velocity_x(0);
156       physic.set_velocity_y(0);
157     }
158   }
159
160   if (state == RECOVERING) {
161     if (timer.check()) {
162       state = IDLE;
163       sprite->set_action("idle");
164       physic.enable_gravity(true);
165       physic.set_velocity_x(0);
166       physic.set_velocity_y(0);
167     }
168   }
169
170 }
171
172 IMPLEMENT_FACTORY(AngryStone, "angrystone")