3 // Zeekling - flyer that swoops down when she spots the player
4 // Copyright (C) 2005 Matthias Braun <matze@braunis.de>
5 // Copyright (C) 2006 Christoph Sommer <supertux@2006.expires.deltadevelopment.de>
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 #include "zeekling.hpp"
27 Zeekling::Zeekling(const lisp::Lisp& reader)
29 reader.get("x", start_position.x);
30 reader.get("y", start_position.y);
31 bbox.set_size(31.8, 31.8);
32 sprite = sprite_manager->create("images/creatures/zeekling/zeekling.sprite");
33 set_direction = false;
37 Zeekling::Zeekling(float pos_x, float pos_y, Direction d)
39 start_position.x = pos_x;
40 start_position.y = pos_y;
41 bbox.set_size(63.8, 50.8);
42 sprite = sprite_manager->create("images/creatures/zeekling/zeekling.sprite");
44 initial_direction = d;
49 Zeekling::write(lisp::Writer& writer)
51 writer.start_list("zeekling");
53 writer.write_float("x", start_position.x);
54 writer.write_float("y", start_position.y);
56 writer.end_list("zeekling");
62 speed = 130 + (rand() % 41);
63 if (set_direction) {dir = initial_direction;}
64 physic.set_velocity_x(dir == LEFT ? -speed : speed);
65 physic.enable_gravity(false);
66 sprite->set_action(dir == LEFT ? "left" : "right");
70 Zeekling::collision_squished(Player& player)
72 sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
73 kill_squished(player);
79 Zeekling::onBumpHorizontal() {
80 if (state == FLYING) {
81 dir = (dir == LEFT ? RIGHT : LEFT);
82 sprite->set_action(dir == LEFT ? "left" : "right");
83 physic.set_velocity_x(dir == LEFT ? -speed : speed);
85 if (state == DIVING) {
86 dir = (dir == LEFT ? RIGHT : LEFT);
88 sprite->set_action(dir == LEFT ? "left" : "right");
89 physic.set_velocity_x(dir == LEFT ? -speed : speed);
90 physic.set_velocity_y(0);
92 if (state == CLIMBING) {
93 dir = (dir == LEFT ? RIGHT : LEFT);
94 sprite->set_action(dir == LEFT ? "left" : "right");
95 physic.set_velocity_x(dir == LEFT ? -speed : speed);
100 Zeekling::onBumpVertical() {
101 if (state == FLYING) {
102 physic.set_velocity_y(0);
104 if (state == DIVING) {
106 physic.set_velocity_y(speed);
107 sprite->set_action(dir == LEFT ? "left" : "right");
109 if (state == CLIMBING) {
111 physic.set_velocity_y(0);
116 Zeekling::collision_solid(GameObject& , const CollisionHit& hit)
118 if(fabsf(hit.normal.y) > .5) {
128 * linear prediction of player and badguy positions to decide if we should enter the DIVING state
131 Zeekling::should_we_dive() {
132 const MovingObject* player = this->get_nearest_player();
133 if (!player) return false;
135 const MovingObject* badguy = this;
137 const Vector playerPos = player->get_pos();
138 const Vector playerMov = player->get_movement();
140 const Vector badguyPos = badguy->get_pos();
141 const Vector badguyMov = badguy->get_movement();
143 // new vertical speed to test with
144 float vy = -2*fabsf(badguyMov.x);
146 // do not dive if we are not above the player
147 float height = playerPos.y - badguyPos.y;
148 if (height <= 0) return false;
150 // do not dive if we would not descend faster than the player
151 float relSpeed = -vy + playerMov.y;
152 if (relSpeed <= 0) return false;
154 // guess number of frames to descend to same height as player
155 float estFrames = height / relSpeed;
157 // guess where the player would be at this time
158 float estPx = (playerPos.x + (estFrames * playerMov.x));
160 // guess where we would be at this time
161 float estBx = (badguyPos.x + (estFrames * badguyMov.x));
163 // near misses are OK, too
164 if (fabsf(estPx - estBx) < 32) return true;
170 Zeekling::active_update(float elapsed_time) {
171 BadGuy::active_update(elapsed_time);
173 if (state == FLYING) {
174 if (should_we_dive()) {
176 physic.set_velocity_y(-2*fabsf(physic.get_velocity_x()));
177 sprite->set_action(dir == LEFT ? "diving-left" : "diving-right");
182 if (state == DIVING) {
186 if (state == CLIMBING) {
187 // stop climbing when we're back at initial height
188 if (get_pos().y <= start_position.y) {
190 physic.set_velocity_y(0);
197 IMPLEMENT_FACTORY(Zeekling, "zeekling")