00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "badguy/zeekling.hpp"
00019
00020 #include <math.h>
00021
00022 #include "math/random_generator.hpp"
00023 #include "object/player.hpp"
00024 #include "sprite/sprite.hpp"
00025 #include "supertux/object_factory.hpp"
00026
00027 Zeekling::Zeekling(const Reader& reader) :
00028 BadGuy(reader, "images/creatures/zeekling/zeekling.sprite"),
00029 speed(),
00030 diveRecoverTimer(),
00031 state(),
00032 last_player(0),
00033 last_player_pos(),
00034 last_self_pos()
00035 {
00036 state = FLYING;
00037 speed = gameRandom.rand(130, 171);
00038 physic.enable_gravity(false);
00039 }
00040
00041 Zeekling::Zeekling(const Vector& pos, Direction d) :
00042 BadGuy(pos, d, "images/creatures/zeekling/zeekling.sprite"),
00043 speed(),
00044 diveRecoverTimer(),
00045 state(),
00046 last_player(0),
00047 last_player_pos(),
00048 last_self_pos()
00049 {
00050 state = FLYING;
00051 speed = gameRandom.rand(130, 171);
00052 physic.enable_gravity(false);
00053 }
00054
00055 void
00056 Zeekling::initialize()
00057 {
00058 physic.set_velocity_x(dir == LEFT ? -speed : speed);
00059 sprite->set_action(dir == LEFT ? "left" : "right");
00060 }
00061
00062 bool
00063 Zeekling::collision_squished(GameObject& object)
00064 {
00065 sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
00066 kill_squished(object);
00067 return true;
00068 }
00069
00070 void
00071 Zeekling::onBumpHorizontal() {
00072 if (state == FLYING) {
00073 dir = (dir == LEFT ? RIGHT : LEFT);
00074 sprite->set_action(dir == LEFT ? "left" : "right");
00075 physic.set_velocity_x(dir == LEFT ? -speed : speed);
00076 } else
00077 if (state == DIVING) {
00078 dir = (dir == LEFT ? RIGHT : LEFT);
00079 state = FLYING;
00080 sprite->set_action(dir == LEFT ? "left" : "right");
00081 physic.set_velocity_x(dir == LEFT ? -speed : speed);
00082 physic.set_velocity_y(0);
00083 } else
00084 if (state == CLIMBING) {
00085 dir = (dir == LEFT ? RIGHT : LEFT);
00086 sprite->set_action(dir == LEFT ? "left" : "right");
00087 physic.set_velocity_x(dir == LEFT ? -speed : speed);
00088 } else {
00089 assert(false);
00090 }
00091 }
00092
00093 void
00094 Zeekling::onBumpVertical() {
00095 if (state == FLYING) {
00096 physic.set_velocity_y(0);
00097 } else
00098 if (state == DIVING) {
00099 state = CLIMBING;
00100 physic.set_velocity_y(-speed);
00101 sprite->set_action(dir == LEFT ? "left" : "right");
00102 } else
00103 if (state == CLIMBING) {
00104 state = FLYING;
00105 physic.set_velocity_y(0);
00106 }
00107 }
00108
00109 void
00110 Zeekling::collision_solid(const CollisionHit& hit)
00111 {
00112 if(hit.top || hit.bottom) {
00113 onBumpVertical();
00114 } else if(hit.left || hit.right) {
00115 onBumpHorizontal();
00116 }
00117 }
00118
00122 bool
00123 Zeekling::should_we_dive() {
00124
00125 const MovingObject* player = this->get_nearest_player();
00126 if (player && last_player && (player == last_player)) {
00127
00128
00129 const Vector player_pos = player->get_pos();
00130 const Vector player_mov = (player_pos - last_player_pos);
00131 const Vector self_pos = this->get_pos();
00132 const Vector self_mov = (self_pos - last_self_pos);
00133
00134
00135 float vy = 2*fabsf(self_mov.x);
00136
00137
00138 float height = player_pos.y - self_pos.y;
00139 if (height <= 0) return false;
00140
00141
00142 if (height > 512) return false;
00143
00144
00145 float relSpeed = vy - player_mov.y;
00146 if (relSpeed <= 0) return false;
00147
00148
00149 float estFrames = height / relSpeed;
00150
00151
00152 float estPx = (player_pos.x + (estFrames * player_mov.x));
00153
00154
00155 float estBx = (self_pos.x + (estFrames * self_mov.x));
00156
00157
00158 if (fabsf(estPx - estBx) < 8) return true;
00159 }
00160
00161
00162 last_player = player;
00163 if (player) {
00164 last_player_pos = player->get_pos();
00165 last_self_pos = this->get_pos();
00166 }
00167
00168 return false;
00169 }
00170
00171 void
00172 Zeekling::active_update(float elapsed_time) {
00173 if (state == FLYING) {
00174 if (should_we_dive()) {
00175 state = DIVING;
00176 physic.set_velocity_y(2*fabsf(physic.get_velocity_x()));
00177 sprite->set_action(dir == LEFT ? "diving-left" : "diving-right");
00178 }
00179 BadGuy::active_update(elapsed_time);
00180 return;
00181 } else if (state == DIVING) {
00182 BadGuy::active_update(elapsed_time);
00183 return;
00184 } else if (state == CLIMBING) {
00185
00186 if (get_pos().y <= start_position.y) {
00187 state = FLYING;
00188 physic.set_velocity_y(0);
00189 }
00190 BadGuy::active_update(elapsed_time);
00191 return;
00192 } else {
00193 assert(false);
00194 }
00195 }
00196
00197