From: Christoph Sommer Date: Sat, 4 Mar 2006 00:08:09 +0000 (+0000) Subject: experimental Zeekling mod - swoops down when she spots the player X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=f8a4dbe2c664797922d2aa4eaac411bc8746921b;p=supertux.git experimental Zeekling mod - swoops down when she spots the player SVN-Revision: 3071 --- diff --git a/data/images/creatures/zeekling/diving.png b/data/images/creatures/zeekling/diving.png new file mode 100644 index 000000000..082d2b85a Binary files /dev/null and b/data/images/creatures/zeekling/diving.png differ diff --git a/data/images/sprites.strf b/data/images/sprites.strf index fefa3ed52..f81049e3c 100644 --- a/data/images/sprites.strf +++ b/data/images/sprites.strf @@ -930,7 +930,17 @@ (name "squished-right") (x-offset 2) (y-offset -19) - (mirror-action "squished-left"))) + (mirror-action "squished-left")) + (action + (name "diving-left") + (x-offset 2) + (y-offset 4) + (images "creatures/zeekling/diving.png")) + (action + (name "diving-right") + (x-offset 2) + (y-offset 4) + (mirror-action "left"))) ; Angry Stone (sprite (name "angrystone") diff --git a/src/badguy/zeekling.cpp b/src/badguy/zeekling.cpp index 0b2758d06..65ae3e91a 100644 --- a/src/badguy/zeekling.cpp +++ b/src/badguy/zeekling.cpp @@ -1,7 +1,8 @@ // $Id$ // -// SuperTux +// Zeekling - flyer that swoops down when she spots the player // Copyright (C) 2005 Matthias Braun +// Copyright (C) 2006 Christoph Sommer // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -23,8 +24,6 @@ #include "zeekling.hpp" - -//TODO: Make the Zeekling behave more interesting Zeekling::Zeekling(const lisp::Lisp& reader) { reader.get("x", start_position.x); @@ -32,6 +31,7 @@ Zeekling::Zeekling(const lisp::Lisp& reader) bbox.set_size(31.8, 31.8); sprite = sprite_manager->create("zeekling"); set_direction = false; + state = FLYING; } Zeekling::Zeekling(float pos_x, float pos_y, Direction d) @@ -42,6 +42,7 @@ Zeekling::Zeekling(float pos_x, float pos_y, Direction d) sprite = sprite_manager->create("zeekling"); set_direction = true; initial_direction = d; + state = FLYING; } void @@ -74,18 +75,121 @@ Zeekling::collision_squished(Player& player) return true; } -HitResponse -Zeekling::collision_solid(GameObject& , const CollisionHit& hit) -{ - if(fabsf(hit.normal.y) > .5) { // hit floor or roof? +void +Zeekling::onBumpHorizontal() { + if (state == FLYING) { + dir = (dir == LEFT ? RIGHT : LEFT); + sprite->set_action(dir == LEFT ? "left" : "right"); + physic.set_velocity_x(dir == LEFT ? -speed : speed); + } else + if (state == DIVING) { + dir = (dir == LEFT ? RIGHT : LEFT); + state = FLYING; + sprite->set_action(dir == LEFT ? "left" : "right"); + physic.set_velocity_x(dir == LEFT ? -speed : speed); physic.set_velocity_y(0); - } else { // hit right or left + } else + if (state == CLIMBING) { dir = (dir == LEFT ? RIGHT : LEFT); sprite->set_action(dir == LEFT ? "left" : "right"); physic.set_velocity_x(dir == LEFT ? -speed : speed); } +} + +void +Zeekling::onBumpVertical() { + if (state == FLYING) { + physic.set_velocity_y(0); + } else + if (state == DIVING) { + state = CLIMBING; + physic.set_velocity_y(speed); + sprite->set_action(dir == LEFT ? "left" : "right"); + } else + if (state == CLIMBING) { + state = FLYING; + physic.set_velocity_y(0); + } +} + +HitResponse +Zeekling::collision_solid(GameObject& , const CollisionHit& hit) +{ + if(fabsf(hit.normal.y) > .5) { + onBumpVertical(); + } else { + onBumpHorizontal(); + } return CONTINUE; } +/** + * linear prediction of player and badguy positions to decide if we should enter the DIVING state + */ +bool +Zeekling::should_we_dive() { + const MovingObject* player = Sector::current()->player; + const MovingObject* badguy = this; + + const Vector playerPos = player->get_pos(); + const Vector playerMov = player->get_movement(); + + const Vector badguyPos = badguy->get_pos(); + const Vector badguyMov = badguy->get_movement(); + + // new vertical speed to test with + float vy = -2*fabsf(badguyMov.x); + + // do not dive if we are not above the player + float height = playerPos.y - badguyPos.y; + if (height <= 0) return false; + + // do not dive if we would not descend faster than the player + float relSpeed = -vy + playerMov.y; + if (relSpeed <= 0) return false; + + // guess number of frames to descend to same height as player + float estFrames = height / relSpeed; + + // guess where the player would be at this time + float estPx = (playerPos.x + (estFrames * playerMov.x)); + + // guess where we would be at this time + float estBx = (badguyPos.x + (estFrames * badguyMov.x)); + + // near misses are OK, too + if (fabsf(estPx - estBx) < 32) return true; + + return false; +} + +void +Zeekling::active_update(float elapsed_time) { + BadGuy::active_update(elapsed_time); + + if (state == FLYING) { + if (should_we_dive()) { + state = DIVING; + physic.set_velocity_y(-2*fabsf(physic.get_velocity_x())); + sprite->set_action(dir == LEFT ? "diving-left" : "diving-right"); + } + return; + } + + if (state == DIVING) { + return; + } + + if (state == CLIMBING) { + // stop climbing when we're back at initial height + if (get_pos().y <= start_position.y) { + state = FLYING; + physic.set_velocity_y(0); + } + return; + } + +} + IMPLEMENT_FACTORY(Zeekling, "zeekling") diff --git a/src/badguy/zeekling.hpp b/src/badguy/zeekling.hpp index 7dc18af73..ab45abcf0 100644 --- a/src/badguy/zeekling.hpp +++ b/src/badguy/zeekling.hpp @@ -1,7 +1,8 @@ // $Id$ // -// SuperTux +// Zeekling - flyer that swoops down when she spots the player // Copyright (C) 2005 Matthias Braun +// Copyright (C) 2006 Christoph Sommer // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -32,12 +33,28 @@ public: void activate(); void write(lisp::Writer& writer); HitResponse collision_solid(GameObject& other, const CollisionHit& hit); + void active_update(float elapsed_time); protected: bool collision_squished(Player& player); bool set_direction; Direction initial_direction; float speed; + + Timer diveRecoverTimer; + + enum ZeeklingState { + FLYING, + DIVING, + CLIMBING + }; + ZeeklingState state; + +private: + bool should_we_dive(); + void onBumpHorizontal(); + void onBumpVertical(); + }; #endif