From f8a4dbe2c664797922d2aa4eaac411bc8746921b Mon Sep 17 00:00:00 2001 From: Christoph Sommer Date: Sat, 4 Mar 2006 00:08:09 +0000 Subject: [PATCH] experimental Zeekling mod - swoops down when she spots the player SVN-Revision: 3071 --- data/images/creatures/zeekling/diving.png | Bin 0 -> 5798 bytes data/images/sprites.strf | 12 ++- src/badguy/zeekling.cpp | 120 ++++++++++++++++++++++++++++-- src/badguy/zeekling.hpp | 19 ++++- 4 files changed, 141 insertions(+), 10 deletions(-) create mode 100644 data/images/creatures/zeekling/diving.png diff --git a/data/images/creatures/zeekling/diving.png b/data/images/creatures/zeekling/diving.png new file mode 100644 index 0000000000000000000000000000000000000000..082d2b85afcf4ad802ff32f3be3811a885b89395 GIT binary patch literal 5798 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 literal 0 HcmV?d00001 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 -- 2.11.0