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
22static const float CHARGE_SPEED = 240;
23
24static const float CHARGE_TIME = .5;
25static const float ATTACK_TIME = 1;
26static const float RECOVER_TIME = .5;
27
28AngryStone::AngryStone(const ReaderMapping& reader) :
29 BadGuy(reader, "images/creatures/angrystone/angrystone.sprite"),
30 attackDirection(),
31 oldWallDirection(),
32 timer(),
33 state(IDLE)
34{
35 m_countMe = false;
36 m_physic.set_velocity_x(0);
37 m_physic.set_velocity_y(0);
38 m_physic.enable_gravity(true);
39 m_sprite->set_action("idle");
40}
41
42void
43AngryStone::collision_solid(const CollisionHit& /*hit*/)
44{
45 // TODO
46#if 0
47 if ((state == ATTACKING) &&
48 (hit.normal.x == -attackDirection.x) && (hit.normal.y == attackDirection.y)) {
49 state = IDLE;
50 sprite->set_action("idle");
51 physic.set_velocity_x(0);
52 physic.set_velocity_y(0);
53 physic.enable_gravity(true);
54 oldWallDirection.x = attackDirection.x;
55 oldWallDirection.y = attackDirection.y;
56 }
57#endif
58}
59
60void
61AngryStone::kill_fall()
62{
63 //prevents AngryStone from getting killed by other enemies or the player
64}
65
66HitResponse
67AngryStone::collision_badguy(BadGuy& badguy, const CollisionHit& )
68{
69 if (state == ATTACKING) {
70 badguy.kill_fall();
71 return FORCE_MOVE;
72 }
73
74 return FORCE_MOVE;
75}
76
77void
78AngryStone::active_update(float dt_sec) {
79 BadGuy::active_update(dt_sec);
80
81 if (m_frozen) {
82 return;
83 }
84
85 switch (state) {
86
87
88 case IDLE: {
89 auto player = get_nearest_player();
90 if (player) {
91 auto badguy = this;
92 const Vector& playerPos = player->get_pos();
93 const Vector& badguyPos = badguy->get_pos();
94 float dx = (playerPos.x - badguyPos.x);
95 float dy = (playerPos.y - badguyPos.y);
96
97 float playerHeight = player->get_bbox().get_height();
98 float badguyHeight = badguy->get_bbox().get_height();
99
100 float playerWidth = player->get_bbox().get_width();
101 float badguyWidth = badguy->get_bbox().get_width();
102
103 if ((dx > -playerWidth) && (dx < badguyWidth)) {
104 if (dy > 0) {
105 attackDirection.x = 0;
106 attackDirection.y = 1;
107 } else {
108 attackDirection.x = 0;
109 attackDirection.y = -1;
110 }
111 if ((attackDirection.x != oldWallDirection.x) || (attackDirection.y != oldWallDirection.y)) {
112 m_sprite->set_action("charging");
113 timer.start(CHARGE_TIME);
114 state = CHARGING;
115 }
116 } else if ((dy > -playerHeight) && (dy < badguyHeight)) {
117 if (dx > 0) {
118 attackDirection.x = 1;
119 attackDirection.y = 0;
120 } else {
121 attackDirection.x = -1;
122 attackDirection.y = 0;
123 }
124 if ((attackDirection.x != oldWallDirection.x) || (attackDirection.y != oldWallDirection.y)) {
125 m_sprite->set_action("charging");
126 timer.start(CHARGE_TIME);
127 state = CHARGING;
128 }
129 }
130 }
131 } break;
132
133 case CHARGING: {
134 if (timer.check()) {
135 m_sprite->set_action("attacking");
136 timer.start(ATTACK_TIME);
137 state = ATTACKING;
138 m_physic.enable_gravity(false);
139 m_physic.set_velocity_x(CHARGE_SPEED * attackDirection.x);
140 m_physic.set_velocity_y(CHARGE_SPEED * attackDirection.y);
141 oldWallDirection.x = 0;
142 oldWallDirection.y = 0;
143 }
144 } break;
145
146 case ATTACKING: {
147 if (timer.check()) {
148 timer.start(RECOVER_TIME);
149 state = RECOVERING;
150 m_sprite->set_action("idle");
151 m_physic.enable_gravity(true);
152 m_physic.set_velocity_x(0);
153 m_physic.set_velocity_y(0);
154 }
155 } break;
156
157 case RECOVERING: {
158 if (timer.check()) {
159 state = IDLE;
160 m_sprite->set_action("idle");
161 m_physic.enable_gravity(true);
162 m_physic.set_velocity_x(0);
163 m_physic.set_velocity_y(0);
164 }
165 } break;
166 }
167
168}
169
170bool
171AngryStone::is_freezable() const
172{
173 return state != ATTACKING;
174}
175
176bool
177AngryStone::is_flammable() const
178{
179 return false;
180}
181
182/* EOF */
183