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