Random stuff that I should have committed ages ago.
[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 #include "lisp/writer.hpp"
26 #include "object/player.hpp"
27 #include "object_factory.hpp"
28 #include "sprite/sprite.hpp"
29
30 static const float SPEED = 240;
31
32 static const float CHARGE_TIME = .5;
33 static const float ATTACK_TIME = 1;
34 static const float RECOVER_TIME = .5;
35
36 AngryStone::AngryStone(const lisp::Lisp& reader)
37         : BadGuy(reader, "images/creatures/angrystone/angrystone.sprite"), state(IDLE)
38 {
39   physic.set_velocity_x(0);
40   physic.set_velocity_y(0);
41   physic.enable_gravity(true);
42   sprite->set_action("idle");
43 }
44
45 void
46 AngryStone::write(lisp::Writer& writer)
47 {
48   writer.start_list("angrystone");
49
50   writer.write("x", start_position.x);
51   writer.write("y", start_position.y);
52
53   writer.end_list("angrystone");
54 }
55
56 void
57 AngryStone::collision_solid(const CollisionHit& hit)
58 {
59   // TODO
60   (void) hit;
61 #if 0
62   if ((state == ATTACKING) &&
63       (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 #endif
73 }
74
75 void
76 AngryStone::kill_fall()
77 {
78   //prevents AngryStone from getting killed by other enemies or the player
79 }
80
81 HitResponse
82 AngryStone::collision_badguy(BadGuy& badguy, const CollisionHit& )
83 {
84   if (state == ATTACKING) {
85     badguy.kill_fall();
86     return FORCE_MOVE;
87   }
88
89   return FORCE_MOVE;
90 }
91
92 void
93 AngryStone::active_update(float elapsed_time) {
94   BadGuy::active_update(elapsed_time);
95
96   if (state == IDLE) {
97     MovingObject* player = this->get_nearest_player();
98     if(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
143   if (state == CHARGING) {
144     if (timer.check()) {
145       sprite->set_action("attacking");
146       timer.start(ATTACK_TIME);
147       state = ATTACKING;
148       physic.enable_gravity(false);
149       physic.set_velocity_x(SPEED * attackDirection.x);
150       physic.set_velocity_y(SPEED * attackDirection.y);
151       oldWallDirection.x = 0;
152       oldWallDirection.y = 0;
153     }
154   }
155
156   if (state == ATTACKING) {
157     if (timer.check()) {
158       timer.start(RECOVER_TIME);
159       state = RECOVERING;
160       sprite->set_action("idle");
161       physic.enable_gravity(true);
162       physic.set_velocity_x(0);
163       physic.set_velocity_y(0);
164     }
165   }
166
167   if (state == RECOVERING) {
168     if (timer.check()) {
169       state = IDLE;
170       sprite->set_action("idle");
171       physic.enable_gravity(true);
172       physic.set_velocity_x(0);
173       physic.set_velocity_y(0);
174     }
175   }
176
177 }
178
179 IMPLEMENT_FACTORY(AngryStone, "angrystone")