Index: Games/Pingus/src/actions/faller.cxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/actions/faller.cxx,v retrieving revision 1.40 diff -u -r1.40 faller.cxx --- Games/Pingus/src/actions/faller.cxx 19 Apr 2003 10:23:18 -0000 1.40 +++ Games/Pingus/src/actions/faller.cxx 13 Nov 2003 00:23:19 -0000 @@ -23,7 +23,7 @@ #include "../debug.hxx" #include "../globals.hxx" #include "../gui/graphic_context.hxx" -#include "../movers/linear_mover.hxx" +#include "../movers/gravitational_mover.hxx" #include "../pingu.hxx" #include "../string_converter.hxx" #include "../world.hxx" @@ -51,80 +51,96 @@ tumbler.update(); faller.update(); - // Pingu stands on ground - if (rel_getpixel(0, -1) != Groundtype::GP_NOTHING) - { - pingu->set_action(Actions::Walker); - return; - } - // FIXME: This should be triggered at a later point, when close to - // FIXME: deadly_velocity or something like that. A translation + // FIXME: fatal_speed or something like that. A translation // FIXME: animation for the floater might also help if (pingu->get_velocity().y > 5.0 && pingu->request_fall_action()) return; - // Apply gravity - pingu->set_velocity(pingu->get_velocity() - + Vector(0.0f, WorldObj::get_world()->get_gravity()) ); + // Create a mover object + Movers::GravitationalMover mover(WorldObj::get_world(), + pingu->get_pos(), + pingu->get_velocity()); bool collided; - - Vector velocity = pingu->get_velocity(); - Vector move = velocity; - - Movers::LinearMover mover(WorldObj::get_world(), pingu->get_pos()); + int collision_pixel; + Vector pos; + Vector move = mover.get_remaining(); + Vector velocity; + Vector collision_pos; + Vector collision_pixel_pos; do { - // Move the Pingu as far is it can go - mover.update(move, Colliders::PinguCollider(pingu_height)); - - pingu->set_pos(mover.get_pos()); + // 'Move' the Pingu + mover.update(Colliders::PinguCollider(pingu_height), move); + // Get the state of the Pingu after the 'move' + pos = mover.get_pos(); + velocity = mover.get_velocity(); collided = mover.collided(); // If the Pingu collided with something... if (collided) { - move = mover.remaining(); + move = mover.get_remaining(); + + // Find out the position of the Pingu when it collided + collision_pos = mover.get_collision_pos(); - // If the Pingu collided into something while moving down... - if (velocity.y > 0.0f - && rel_getpixel(0, -1) != Groundtype::GP_NOTHING) + // Find out what the Pingu collided with and where it is + collision_pixel = mover.get_collision_pixel(); + collision_pixel_pos = mover.get_collision_pixel_pos(); + + // If the Pingu collided with something deadly... + if (collision_pixel == Groundtype::GP_WATER + || collision_pixel == Groundtype::GP_LAVA) + { + pingu->set_action(Actions::Drown); + } + // Else if the Pingu has gone out of the screen + else if (collision_pixel == Groundtype::GP_OUTOFSCREEN) { - // Ping is on ground/water/something - if ( rel_getpixel(0, -1) == Groundtype::GP_WATER - || rel_getpixel(0, -1) == Groundtype::GP_LAVA) - { - pingu->set_action(Actions::Drown); - } - // Did we stop too fast? - else if (fabs(pingu->get_velocity().y) > deadly_velocity) - { - pingu->set_action(Actions::Splashed); - } - else if (fabs(pingu->get_velocity().x) > deadly_velocity) - { - pout(PINGUS_DEBUG_ACTIONS) << "Pingu: x Smashed on ground, jumping" << std::endl; - } - - break; - } - // If the Pingu collided into something while moving up... - // NB: +1 because Mover backs out of something it has collided with. - else if (velocity.y < 0.0f - && rel_getpixel(0, pingu_height + 1) != Groundtype::GP_NOTHING) + pingu->set_status(PS_DEAD); + } + // Else, taking into account that the Pingu could have collided at an + // angle, if the Pingu collided at or above the fatal speed... + else if (mover.get_velocity().length() >= fatal_speed) + { + pingu->set_action(Actions::Splashed); + } + // Else if the Pingu moved into something below it... + else if (static_cast(collision_pos.y) > static_cast(pos.y) + && static_cast(collision_pixel_pos.y) + >= static_cast(collision_pos.y)) + { + // Round down the Pingu's y pos otherwise a Pingu with y = 1.9 and + // another with y = 1.0 both on the same platform could react + // differently when falling off it. + pos.y = static_cast(pos.y); + + // Reset the velocity + velocity.x = 0.0f; + velocity.y = 0.0f; + + // Pingu has safely collided with the ground + pingu->set_action(Actions::Walker); + } + // Else if the Pingu moved into something above it... + else if (static_cast(collision_pos.y) < static_cast(pos.y) + && static_cast(collision_pixel_pos.y) + <= static_cast(collision_pos.y) - pingu_height) { // Don't make the Pingu go up any further. move.y = 0.0f; velocity.y = 0.0f; } + // Else assume the Pingu has hit a wall... else { // Make Pingu bounce off wall - move.x = -(move.x / 3.0f); - velocity.x = -(velocity.x / 3.0f); + move.x /= -3.0f; + velocity.x /= -3.0f; // Make the Pingu face the correct direction. NB: Pingu may // previously have been facing in the opposite direction of its @@ -134,13 +150,18 @@ else pingu->direction.left(); } - } - // Update the Pingu's velocity - pingu->set_velocity(velocity); + mover.set_velocity(velocity); + } } - // Loop if the Pingu still needs to be moved - while (collided); + // While the move has not been completed, the Pingu is not dead and is still + // a Faller + while (collided && pingu->get_status() != PS_DEAD + && pingu->get_action() == Actions::Faller); + + // Update the Pingu's position and velocity + pingu->set_pos(pos); + pingu->set_velocity(velocity); } void @@ -157,8 +178,8 @@ Faller::is_tumbling () const { // If we are going fast enough to get smashed, start tumbling - return ( fabs(pingu->get_velocity().x) > deadly_velocity - || fabs(pingu->get_velocity().y) > deadly_velocity); + return ( fabs(pingu->get_velocity().x) > fatal_speed + || fabs(pingu->get_velocity().y) > fatal_speed); } bool Index: Games/Pingus/src/actions/bomber.cxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/actions/bomber.cxx,v retrieving revision 1.34 diff -u -r1.34 bomber.cxx --- Games/Pingus/src/actions/bomber.cxx 19 Apr 2003 10:23:18 -0000 1.34 +++ Games/Pingus/src/actions/bomber.cxx 13 Nov 2003 00:23:20 -0000 @@ -81,29 +81,86 @@ { sprite.update (); - Movers::LinearMover mover(WorldObj::get_world(), pingu->get_pos()); - - Vector velocity = pingu->get_velocity(); - - // Move the Pingu - mover.update(velocity, Colliders::PinguCollider(pingu_height)); - - pingu->set_pos(mover.get_pos()); - - // If the Bomber hasn't 'exploded' yet and it has hit Water or Lava - if (sprite.get_frame () <= 9 && (rel_getpixel(0, -1) == Groundtype::GP_WATER - || rel_getpixel(0, -1) == Groundtype::GP_LAVA)) - { - pingu->set_action(Actions::Drown); - return; - } - - // If the Bomber hasn't 'exploded' yet and it has hit the ground too quickly - if (sprite.get_frame () <= 9 && rel_getpixel(0, -1) != Groundtype::GP_NOTHING - && velocity.y > deadly_velocity) + if (sprite.get_frame () <= 9) { - pingu->set_action(Actions::Splashed); - return; + // Could use a Gravitational Mover here, with an upthrust equalling + // gravity. However, if this the case, the Gravitational Mover would + // act exactly like a Linear Mover. So might as well just use a Linear + // Mover. + Movers::LinearMover mover(WorldObj::get_world(), pingu->get_pos()); + + + bool collided; + int collision_pixel; + Vector pos; + Vector move = pingu->get_velocity(); + Vector velocity = move; + Vector collision_pos; + Vector collision_pixel_pos; + + do + { + // 'Move' the Pingu + mover.update(Colliders::PinguCollider(pingu_height), move); + + // Get the state of the Pingu after the 'move' + pos = mover.get_pos(); + collided = mover.collided(); + + // If the Pingu collided with something... + if (collided) + { + move = mover.get_remaining(); + + // Find out the position of the Pingu when it collided + collision_pos = mover.get_collision_pos(); + + // Find with what the Pingu collided with and where it is + collision_pixel = mover.get_collision_pixel(); + collision_pixel_pos = mover.get_collision_pixel_pos(); + + // If the Pingu collided with something deadly... + if (collision_pixel == Groundtype::GP_WATER + || collision_pixel == Groundtype::GP_LAVA) + { + pingu->set_action(Actions::Drown); + } + // Else if the Pingu has gone out of the screen + else if (collision_pixel == Groundtype::GP_OUTOFSCREEN) + { + pingu->set_status(PS_DEAD); + } + // Else if the Pingu moved into something above or below it... + else if ((static_cast(collision_pos.y) + < static_cast(pos.y) + && static_cast(collision_pixel_pos.y) + <= (static_cast(collision_pos.y) + - pingu_height) ) + || (static_cast(collision_pos.y) + > static_cast(pos.y) + && static_cast(collision_pixel_pos.y) + >= static_cast(collision_pos.y)) ) + { + // Make Pingu bounce off ground or ceiling + move.y /= -3.0f; + velocity.y /= -3.0f; + } + else + { + // Make Pingu bounce off wall + move.x /= -3.0f; + velocity.x /= -3.0f; + } + } + } + // While the move has not been completed, the Pingu is not dead and is + // still a Bomber + while (collided && pingu->get_status() != PS_DEAD + && pingu->get_action() == Actions::Faller); + + // Update the Pingu's position and velocity + pingu->set_pos(pos); + pingu->set_velocity(velocity); } if (sprite.get_frame () > 9 && !sound_played) { Index: Games/Pingus/src/actions/faller.hxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/actions/faller.hxx,v retrieving revision 1.20 diff -u -r1.20 faller.hxx --- Games/Pingus/src/actions/faller.hxx 19 Apr 2003 10:23:18 -0000 1.20 +++ Games/Pingus/src/actions/faller.hxx 13 Nov 2003 00:23:20 -0000 @@ -31,8 +31,6 @@ Sprite faller; Sprite tumbler; - int falling; - public: Faller(Pingu*); virtual ~Faller(); Index: Games/Pingus/src/actions/drown.hxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/actions/drown.hxx,v retrieving revision 1.13 diff -u -r1.13 drown.hxx --- Games/Pingus/src/actions/drown.hxx 19 Apr 2003 10:23:18 -0000 1.13 +++ Games/Pingus/src/actions/drown.hxx 13 Nov 2003 00:23:23 -0000 @@ -38,7 +38,9 @@ void draw (GraphicContext& gc); void update (); + bool allow_set_countdown_action () { return false; } bool catchable () { return false; } + bool change_allowed (Actions::ActionName) { return false; } private: Drown (const Drown&); Index: Games/Pingus/src/actions/splashed.hxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/actions/splashed.hxx,v retrieving revision 1.15 diff -u -r1.15 splashed.hxx --- Games/Pingus/src/actions/splashed.hxx 19 Apr 2003 10:23:18 -0000 1.15 +++ Games/Pingus/src/actions/splashed.hxx 13 Nov 2003 00:23:23 -0000 @@ -39,6 +39,7 @@ void draw (GraphicContext& gc); void update (); + bool allow_set_countdown_action () { return false; } bool catchable () { return false; } bool change_allowed (Actions::ActionName) { return false; } Index: Games/Pingus/src/actions/exiter.hxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/actions/exiter.hxx,v retrieving revision 1.14 diff -u -r1.14 exiter.hxx --- Games/Pingus/src/actions/exiter.hxx 19 Apr 2003 10:23:18 -0000 1.14 +++ Games/Pingus/src/actions/exiter.hxx 13 Nov 2003 00:23:24 -0000 @@ -39,6 +39,10 @@ void draw (GraphicContext& gc); void update(); + bool allow_set_countdown_action () { return false; } + bool catchable () { return false; } + bool change_allowed (Actions::ActionName) { return false; } + private: Exiter (const Exiter&); Exiter& operator= (const Exiter&); Index: Games/Pingus/src/actions/laser_kill.hxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/actions/laser_kill.hxx,v retrieving revision 1.14 diff -u -r1.14 laser_kill.hxx --- Games/Pingus/src/actions/laser_kill.hxx 19 Apr 2003 10:23:18 -0000 1.14 +++ Games/Pingus/src/actions/laser_kill.hxx 13 Nov 2003 00:23:24 -0000 @@ -41,7 +41,9 @@ void draw (GraphicContext& gc); void update (); + bool allow_set_countdown_action () { return false; } bool catchable () { return false; } + bool change_allowed (Actions::ActionName) { return false; } private: LaserKill (const LaserKill&); Index: Games/Pingus/src/actions/bomber.hxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/actions/bomber.hxx,v retrieving revision 1.20 diff -u -r1.20 bomber.hxx --- Games/Pingus/src/actions/bomber.hxx 19 Apr 2003 10:23:18 -0000 1.20 +++ Games/Pingus/src/actions/bomber.hxx 13 Nov 2003 00:23:24 -0000 @@ -51,6 +51,10 @@ void draw (GraphicContext& gc); void update(); + bool allow_set_countdown_action () { return false; } + bool catchable () { return false; } + bool change_allowed (Actions::ActionName) { return false; } + int activation_time() { return 150; } void on_successfull_apply (); Index: Games/Pingus/src/actions/smashed.hxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/actions/smashed.hxx,v retrieving revision 1.15 diff -u -r1.15 smashed.hxx --- Games/Pingus/src/actions/smashed.hxx 19 Apr 2003 10:23:18 -0000 1.15 +++ Games/Pingus/src/actions/smashed.hxx 13 Nov 2003 00:23:24 -0000 @@ -41,7 +41,9 @@ void draw (GraphicContext& gc); void update (); + bool allow_set_countdown_action () { return false; } bool catchable () { return false; } + bool change_allowed (Actions::ActionName) { return false; } private: Smashed (const Smashed&); Index: Games/Pingus/src/actions/teleported.hxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/actions/teleported.hxx,v retrieving revision 1.14 diff -u -r1.14 teleported.hxx --- Games/Pingus/src/actions/teleported.hxx 19 Apr 2003 10:23:18 -0000 1.14 +++ Games/Pingus/src/actions/teleported.hxx 13 Nov 2003 00:23:25 -0000 @@ -37,7 +37,9 @@ void draw (GraphicContext& gc); void update(); + bool allow_set_countdown_action () { return false; } bool catchable () { return false; } + bool change_allowed (Actions::ActionName) { return false; } int x_target, y_target; // <- FIXME: Ugly! Index: Games/Pingus/src/mover.cxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/mover.cxx,v retrieving revision 1.2 diff -u -r1.2 mover.cxx --- Games/Pingus/src/mover.cxx 9 Mar 2003 20:41:30 -0000 1.2 +++ Games/Pingus/src/mover.cxx 13 Nov 2003 00:23:25 -0000 @@ -17,12 +17,14 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +#include "col_map.hxx" #include "mover.hxx" +#include "world.hxx" Mover::Mover(World* const world_arg, const Vector& pos_arg) : world(world_arg), pos(pos_arg), - remaining_move(0.0f, 0.0f, 0.0f), + remaining(0.0f, 0.0f, 0.0f), collision(false) { } @@ -36,9 +38,25 @@ return pos; } -Vector Mover::remaining() const +Vector Mover::get_collision_pos() const { - return remaining_move; + return collision_pos; +} + +Vector Mover::get_collision_pixel_pos() const +{ + return collision_pixel_pos; +} + +int Mover::get_collision_pixel() const +{ + return world->get_colmap()->getpixel(static_cast(collision_pixel_pos.x), + static_cast(collision_pixel_pos.y)); +} + +Vector Mover::get_remaining() const +{ + return remaining; } bool Mover::collided() const Index: Games/Pingus/src/pingu_enums.cxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/pingu_enums.cxx,v retrieving revision 1.8 diff -u -r1.8 pingu_enums.cxx --- Games/Pingus/src/pingu_enums.cxx 24 Apr 2003 15:18:19 -0000 1.8 +++ Games/Pingus/src/pingu_enums.cxx 13 Nov 2003 00:23:26 -0000 @@ -20,9 +20,10 @@ #include "gettext.h" #include "pingu_enums.hxx" -// Pingu "globals". Make [deadly_velocity = 20 * sqrt("normal gravity")] so -// that the "deadly distance" is the same and therefore doesn't break levels. -const float deadly_velocity = 10.0f; +// Pingu "globals". Make fatal_speed above sqrt(2 * 210 pixels * "normal +// gravity") and below sqrt(2 * 211 pixels * "normal gravity") so that the +// fatal distance is the same and therefore doesn't break levels. +const float fatal_speed = 10.26f; const int pingu_height = 26; namespace Actions { Index: Games/Pingus/src/pingu_enums.hxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/pingu_enums.hxx,v retrieving revision 1.12 diff -u -r1.12 pingu_enums.hxx --- Games/Pingus/src/pingu_enums.hxx 18 Apr 2003 17:08:56 -0000 1.12 +++ Games/Pingus/src/pingu_enums.hxx 13 Nov 2003 00:23:26 -0000 @@ -79,7 +79,7 @@ // Pingu "globals" extern const int pingu_height; -extern const float deadly_velocity; +extern const float fatal_speed; #endif Index: Games/Pingus/src/collider.hxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/collider.hxx,v retrieving revision 1.3 diff -u -r1.3 collider.hxx --- Games/Pingus/src/collider.hxx 18 Mar 2003 17:03:01 -0000 1.3 +++ Games/Pingus/src/collider.hxx 13 Nov 2003 00:23:27 -0000 @@ -32,9 +32,11 @@ /** Destructor for abstract class */ virtual ~Collider() = 0; - /** Find out if object will collide with something */ - virtual bool operator() (World* const world, Vector current_pos, - const Vector& step_vector) const = 0; + /** Find out if object will collide with something and where the collision + would take place */ + virtual bool operator() (Vector& collision_pos, World* const world, + const Vector& current_pos, const Vector& step_vector) + const = 0; protected: /** Get the Collision Map pixel at the specified position in the specified Index: Games/Pingus/src/collider.cxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/collider.cxx,v retrieving revision 1.3 diff -u -r1.3 collider.cxx --- Games/Pingus/src/collider.cxx 18 Mar 2003 17:03:01 -0000 1.3 +++ Games/Pingus/src/collider.cxx 13 Nov 2003 00:23:27 -0000 @@ -30,9 +30,10 @@ { } -bool Collider::operator() (World* const world, Vector current_pos, - const Vector& step_vector) const +bool Collider::operator() (Vector& collision_pos, World* const world, + const Vector& current_pos, const Vector& step_vector) const { + UNUSED_ARG(collision_pos); UNUSED_ARG(world); UNUSED_ARG(current_pos); UNUSED_ARG(step_vector); Index: Games/Pingus/src/mover.hxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/mover.hxx,v retrieving revision 1.3 diff -u -r1.3 mover.hxx --- Games/Pingus/src/mover.hxx 19 Apr 2003 10:23:17 -0000 1.3 +++ Games/Pingus/src/mover.hxx 13 Nov 2003 00:23:27 -0000 @@ -35,17 +35,26 @@ virtual ~Mover() = 0; /** Updates the position of the object taking into account collisions */ - virtual void update(const Vector& move, const Collider& collider) = 0; + virtual void update(const Collider& collider, const Vector& move) = 0; /** Get the resulting position vector */ Vector get_pos() const; - /** Get the move vector remaining after a collision */ - Vector remaining() const; + /** Get the position of the object when it collided with something */ + Vector get_collision_pos() const; + + /** Get the position of the pixel with which the object collided */ + Vector get_collision_pixel_pos() const; + + /** Get the "pixel" that the object collided with */ + int get_collision_pixel() const; /** Get whether object stopped moving because it collided with something */ bool collided() const; + /** Get the move vector remaining after a collision */ + Vector get_remaining() const; + protected: /** World in which the object should move */ World* const world; @@ -53,8 +62,14 @@ /** Position of the object to move */ Vector pos; + /** Position of the object when it collided with something */ + Vector collision_pos; + + /** Position of the pixel the object collided with */ + Vector collision_pixel_pos; + /** Move vector remaining after a collision */ - Vector remaining_move; + Vector remaining; /** Flag to denote whether object has had a collision */ bool collision; Index: Games/Pingus/src/pingu.cxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/pingu.cxx,v retrieving revision 1.43 diff -u -r1.43 pingu.cxx --- Games/Pingus/src/pingu.cxx 24 Apr 2003 15:18:19 -0000 1.43 +++ Games/Pingus/src/pingu.cxx 13 Nov 2003 00:23:34 -0000 @@ -322,7 +322,10 @@ if (action_time > -1) --action_time; - if (action_time == 0 && countdown_action) + // If the countdown has reached zero, there is a countdown action and the + // current action is allowed to be interrupted by a countdown action... + if (action_time == 0 && countdown_action + && action->allow_set_countdown_action() == true) { set_action(countdown_action); // Reset the countdown action handlers Index: Games/Pingus/src/pingu_action.cxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/pingu_action.cxx,v retrieving revision 1.26 diff -u -r1.26 pingu_action.cxx --- Games/Pingus/src/pingu_action.cxx 20 Apr 2003 21:25:29 -0000 1.26 +++ Games/Pingus/src/pingu_action.cxx 13 Nov 2003 00:23:35 -0000 @@ -237,7 +237,7 @@ { // FIXME: this shouldn't be really here, but its a // FIXME: quick&dirty way to kill falling pingus - if (resultant_force.y >= deadly_velocity) + if (resultant_force.y >= fatal_speed) { pingu->set_action(Actions::Splashed); return; Index: Games/Pingus/src/pingu_action.hxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/pingu_action.hxx,v retrieving revision 1.27 diff -u -r1.27 pingu_action.hxx --- Games/Pingus/src/pingu_action.hxx 19 Apr 2003 10:23:17 -0000 1.27 +++ Games/Pingus/src/pingu_action.hxx 13 Nov 2003 00:23:36 -0000 @@ -62,7 +62,7 @@ /** Checks if this action allows to be overwritten with the given new action */ virtual bool change_allowed (Actions::ActionName) { return true; } - + /// The "AI" of the pingu. virtual void update () = 0; @@ -92,6 +92,11 @@ /// The time the action needs to get activated (see bomber.cxx) virtual int activation_time () { return -1; }; + /** After the countdown has reached zero, this finds out if the countdown + action is allowed to be set during this action. Unless overridden, the + default is true. */ + virtual bool allow_set_countdown_action() { return true; }; + /** Return true if the pingu can be catched with the mouse and another action can be applied, false otherwise (exiter, splashed, etc.) */ Index: Games/Pingus/src/colliders/pingu_collider.cxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/colliders/pingu_collider.cxx,v retrieving revision 1.3 diff -u -r1.3 pingu_collider.cxx --- Games/Pingus/src/colliders/pingu_collider.cxx 18 Mar 2003 17:03:02 -0000 1.3 +++ Games/Pingus/src/colliders/pingu_collider.cxx 13 Nov 2003 00:23:36 -0000 @@ -17,6 +17,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +#include "../mover.hxx" #include "../pingu_action.hxx" #include "../groundtype.hxx" #include "../vector.hxx" @@ -32,53 +33,73 @@ { } -bool PinguCollider::operator() (World* const world, Vector current_pos, - const Vector& step_vector) const +bool PinguCollider::operator() (Vector& collision_pos, World* const world, + const Vector& current_pos, + const Vector& step_vector) const { - Vector new_pos = current_pos + step_vector; - int pixel; - bool falling = false; + bool moving_up = false; + + if (step_vector.y < 0.0f) + moving_up = true; + + Vector check_pos = current_pos + step_vector; + bool collided = false; - if (step_vector.y > 0.0f) - falling = true; + // If moving down on to a Bridge pixel, collide with it. + if (!moving_up && getpixel(world, check_pos) == Groundtype::GP_BRIDGE) + { + collision_pos = check_pos; - // If the Pingu is going to move sideways to the next pixel... - if (static_cast(new_pos.x) != static_cast(current_pos.x)) + collided = true; + } + + int y = 0; + + // If the Pingu is not moving sideways when going to the next pixel... + if (static_cast(check_pos.x) == static_cast(current_pos.x)) { - float top_of_pingu = new_pos.y - height; + // Only need to check one pixel. Must only be one pixel because when a + // walker turns into a faller, it could collide into a solid block of + // pixels. + y = height; + + // If moving up, then check the top pixel + if (moving_up) + check_pos.y -= height; + } - for (; new_pos.y >= top_of_pingu; --new_pos.y) + int collision_pixel; + + for (; y <= height; --check_pos.y, ++y) + { + // If the Pingu is about to check the last and therefore top most pixel, + // is moving upwards and the Pingu has already collided with something, + // stop the collision pixel from being set to the top most pixel. + // Otherwise, what should be a side collision could be detected as a + // collision with the ceiling. + if (collided && moving_up && y == height) + break; + + collision_pixel = getpixel(world, check_pos); + + // If the Pingu has moved into something solid or deadly... + if (collision_pixel != Groundtype::GP_BRIDGE + && collision_pixel != Groundtype::GP_NOTHING) { - pixel = getpixel(world, new_pos); + collided = true; + + collision_pos = check_pos; - // If there is something in the way, then Pingu has collided with - // something. However, if not falling and colliding with a - // Bridge, allow Pingu to go through it. - if ((!falling || pixel != Groundtype::GP_BRIDGE) - && pixel != Groundtype::GP_NOTHING) + // If the Pingu has moved into something deadly... + if (collision_pixel == Groundtype::GP_WATER + || collision_pixel == Groundtype::GP_LAVA) { - collided = true; + // Stop checking for any more pixels as there is no need to break; } } } - // If the Pingu is not falling... - else if (!falling) - { - pixel = getpixel(world, Vector(new_pos.x, new_pos.y - height)); - - // If the top of the Pingu has hit something except a bridge... - if (pixel != Groundtype::GP_NOTHING && pixel != Groundtype::GP_BRIDGE) - { - collided = true; - } - } - // If the Pingu's "feet" has hit something... - else if (getpixel(world, new_pos) != Groundtype::GP_NOTHING) - { - collided = true; - } return collided; } Index: Games/Pingus/src/colliders/pingu_collider.hxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/colliders/pingu_collider.hxx,v retrieving revision 1.3 diff -u -r1.3 pingu_collider.hxx --- Games/Pingus/src/colliders/pingu_collider.hxx 18 Mar 2003 17:03:02 -0000 1.3 +++ Games/Pingus/src/colliders/pingu_collider.hxx 13 Nov 2003 00:23:37 -0000 @@ -34,9 +34,9 @@ ~PinguCollider(); /** Find out if a Pingu at the specified position is colliding with - something */ - bool operator() (World* const world, Vector current_pos, - const Vector& step_vector) const; + something and where the collision is */ + bool operator() (Vector& collision_pos, World* const world, + const Vector& current_pos, const Vector& step_vector) const; private: /** Pingu could be on its belly. Therefore, this is the current height of Index: Games/Pingus/src/movers/linear_mover.cxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/movers/linear_mover.cxx,v retrieving revision 1.3 diff -u -r1.3 linear_mover.cxx --- Games/Pingus/src/movers/linear_mover.cxx 18 Mar 2003 17:03:02 -0000 1.3 +++ Games/Pingus/src/movers/linear_mover.cxx 13 Nov 2003 00:23:37 -0000 @@ -31,7 +31,7 @@ { } -void LinearMover::update(const Vector& move, const Collider& collision_check) +void LinearMover::update(const Collider& collision_check, const Vector& move) { Vector target_pos = pos + move; Vector step_vector = move; @@ -44,19 +44,51 @@ collision = false; + Vector new_pos; + // Move to the destination one unit vector at a time - for (int i = 0; i < move_length && !collision; ++i) + for (int i = 0; i <= move_length; ++i) { - collision = collision_check(world, pos, step_vector); + // If a 'fraction' of a move is left... + if (i >= move_length) + { + // Make the fraction of the move that is left to the target position + new_pos = target_pos; + step_vector = target_pos - pos; + } + else + { + new_pos = pos + step_vector; + } + + // Only check for a collision if the object has moved to a different + // pixel. Movers keep moving the object until there is no collision. + // Therefore, if the object is already on a collision pixel and the + // pixels around it are collision pixels, the Mover can make the game get + // stuck in an infinite loop. This can be caused by the user + // accidentally putting an entrance in a solid. So, don't make the pixel + // the object is already at "collideable." In order to handle the + // collision pixels around it, the amount to move the object should be + // dampened/decreased when it collides with such surrouding pixels. + if (static_cast(new_pos.x) != static_cast(pos.x) + || static_cast(new_pos.y) != static_cast(pos.y)) + { + collision = collision_check(collision_pixel_pos, world, pos, + step_vector); + } + + if (collision) + { + // Set the pos of the object where the collision took place + collision_pos = new_pos; - pos += step_vector; - } + break; + } - // If on a collision pixel, back away from it. - if (collision) - pos -= step_vector; + pos = new_pos; + } - remaining_move = target_pos - pos; + remaining = target_pos - pos; } } // namespace Movers Index: Games/Pingus/src/movers/linear_mover.hxx =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/movers/linear_mover.hxx,v retrieving revision 1.3 diff -u -r1.3 linear_mover.hxx --- Games/Pingus/src/movers/linear_mover.hxx 19 Apr 2003 10:23:19 -0000 1.3 +++ Games/Pingus/src/movers/linear_mover.hxx 13 Nov 2003 00:23:38 -0000 @@ -36,7 +36,7 @@ ~LinearMover(); /** Updates the position of the object taking into account collisions */ - void update(const Vector& move, const Collider& collision_at); + void update(const Collider& collision_check, const Vector& move); }; } // namespace Movers Index: Games/Pingus/src/movers/Makefile.am =================================================================== RCS file: /var/lib/cvs/Games/Pingus/src/movers/Makefile.am,v retrieving revision 1.4 diff -u -r1.4 Makefile.am --- Games/Pingus/src/movers/Makefile.am 21 Mar 2003 22:08:06 -0000 1.4 +++ Games/Pingus/src/movers/Makefile.am 13 Nov 2003 00:23:39 -0000 @@ -21,6 +21,7 @@ noinst_LIBRARIES = libpingus_movers.a libpingus_movers_a_SOURCES = \ + gravitational_mover.cxx gravitational_mover.hxx \ linear_mover.cxx linear_mover.hxx # EOF #