# HG changeset patch # User terom # Date 1228778509 0 # Node ID 51d644c8d5a2b2da4dcb0b9363d577d3251076d7 # Parent 09a3b505586262daace915bbbbe02e877d7ac6de fix player-pivoted rope diff -r 09a3b5055862 -r 51d644c8d5a2 src/Network/Client.cc --- a/src/Network/Client.cc Mon Dec 08 23:11:40 2008 +0000 +++ b/src/Network/Client.cc Mon Dec 08 23:21:49 2008 +0000 @@ -222,16 +222,25 @@ Engine::log(INFO, "client_player.on_rope_throw") << this << ": position=" << position << ", velocity=" << velocity << ", length=" << length; - rope.updateState(ROPE_FLYING, position, velocity, length); + rope.updateState(ROPE_FLYING, position, velocity, length, NULL); } void NetworkClientPlayerBase::on_rope_fixed (NetworkPacketInput &pkt) { Vector position = pkt.read_vector(); float length = pkt.read_float32(); + NetworkObject *player_obj = controller.read_object(pkt); + + NetworkClientPlayerBase *player = NULL; + + if (player_obj != NULL && (player = dynamic_cast(player_obj)) == NULL) { + Engine::log(ERROR, "client.on_rope_fixed") << this << ": Unknown player object"; + return; + } - Engine::log(INFO, "client_player.on_rope_fixed") << this << ": position=" << position << ", length=" << length; + Engine::log(INFO, "client_player.on_rope_fixed") << this << ": position=" << position << ", length=" << length + << ", player=" << player; - rope.updateState(ROPE_FIXED, position, Vector(0, 0), length); + rope.updateState(ROPE_FIXED, position, Vector(0, 0), length, player); } void NetworkClientPlayerBase::on_rope_released (NetworkPacketInput &pkt) { @@ -240,7 +249,7 @@ Engine::log(INFO, "client_player.on_rope_released") << this; // use rope.getPosition() instead of e.g. Vector(0, 0) because it will collide there... - rope.updateState(ROPE_FOLDED, rope.getPosition(), Vector(0, 0), 0); + rope.updateState(ROPE_FOLDED, rope.getPosition(), Vector(0, 0), 0, NULL); } void NetworkClientPlayerBase::on_rope_length (NetworkPacketInput &pkt) { diff -r 09a3b5055862 -r 51d644c8d5a2 src/Network/Object.cc --- a/src/Network/Object.cc Mon Dec 08 23:11:40 2008 +0000 +++ b/src/Network/Object.cc Mon Dec 08 23:21:49 2008 +0000 @@ -32,14 +32,14 @@ uint32_t obj_id = pkt.read_uint32(); // lookup object - NetworkObject *obj = objects[obj_id]; + NetworkObject *obj = obj_id ? objects[obj_id] : NULL; // return return obj; } void NetworkObjectController::write_object (NetworkPacketOutput &pkt, NetworkObject *obj) { - pkt.write_uint32(obj->obj_id); + pkt.write_uint32(obj ? obj->obj_id : 0); } /* diff -r 09a3b5055862 -r 51d644c8d5a2 src/Network/Object.hh --- a/src/Network/Object.hh Mon Dec 08 23:11:40 2008 +0000 +++ b/src/Network/Object.hh Mon Dec 08 23:21:49 2008 +0000 @@ -79,13 +79,18 @@ public: /** - * Read an NetworkObjectID from the given packet, and return the corresponding NetworkObject, or NULL if we - * don't know it. + * Read an NetworkObjectID from the given packet, and return the corresponding NetworkObject, or NULL if: + * * it was zero + * * we don't know the object (should this thrown an exception instead?) + * + * @return the NetworkObject* corresponding to the NetworkObjectID in the packet, or NULL if zero/not found */ NetworkObject* read_object (NetworkPacketInput &pkt); /** - * Write the given Object's NetworkObjectID to the given packet + * Write the given Object's NetworkObjectID (or 0, if the obj is NULL) to the given packet + * + * @param the NetworkObject* whose NetworkObjectID to write to the packet, or NULL to write zero */ void write_object (NetworkPacketOutput &pkt, NetworkObject *obj); }; diff -r 09a3b5055862 -r 51d644c8d5a2 src/Network/Protocol.hh --- a/src/Network/Protocol.hh Mon Dec 08 23:11:40 2008 +0000 +++ b/src/Network/Protocol.hh Mon Dec 08 23:21:49 2008 +0000 @@ -119,6 +119,7 @@ * * Vector position * float length + * Object? player */ NETMSG_PLAYER_ROPE_FIXED = 0x0332, diff -r 09a3b5055862 -r 51d644c8d5a2 src/Network/Server.cc --- a/src/Network/Server.cc Mon Dec 08 23:11:40 2008 +0000 +++ b/src/Network/Server.cc Mon Dec 08 23:21:49 2008 +0000 @@ -123,7 +123,7 @@ void NetworkServerPlayer::handleRopeState (RopeState state) { NetworkPacket pkt; - Engine::log(INFO, "server_player.rope_state") << "state=" << rope.getState() << ", position=" << rope.getPosition() << ", velocity=" << rope.getVelocity() << ", length=" << rope.getLength(); + Engine::log(INFO, "server_player.rope_state") << "state=" << rope.getState() << ", position=" << rope.getPosition() << ", velocity=" << rope.getVelocity() << ", length=" << rope.getLength() << ", pivotPlayer=" << rope.getPivotPlayer(); switch (state) { case ROPE_FLYING: @@ -135,13 +135,20 @@ break; - case ROPE_FIXED: + case ROPE_FIXED: { + Player *player_base = rope.getPivotPlayer(); + NetworkServerPlayer *player = NULL; + + if (player_base != NULL && (player = dynamic_cast(player_base)) == NULL) + throw Error("NetworkServerPlayer::handleRopeState: rope's pivotPlayer is not a NetworkServerPlayer"); + pkt.write_vector(rope.getPosition()); pkt.write_float32(rope.getLength()); + controller.write_object(pkt, player); // may be NULL send_all(NETMSG_PLAYER_ROPE_FIXED, pkt, true); - break; + } break; case ROPE_FOLDED: send_all(NETMSG_PLAYER_ROPE_RELEASED, pkt, true); diff -r 09a3b5055862 -r 51d644c8d5a2 src/Rope.cc --- a/src/Rope.cc Mon Dec 08 23:11:40 2008 +0000 +++ b/src/Rope.cc Mon Dec 08 23:21:49 2008 +0000 @@ -42,15 +42,28 @@ void Rope::onCollision (Vector collisionPoint, PhysicsObject *other) { // Fix the rope to another player if collided with it if (other != NULL) { + // we collided with another object if (other->getType() == PLAYER) { + // set our player's pivot to the object that we collided with Player *target = dynamic_cast(other); - if (target == &(this->player)) + + // ignore if the rope hits ourself + if (target == &this->player) return; - this->player.pivot = target; - } else if (other->getType() == PROJECTILE) { + + // set player's pivot to the other player + player.setPivot(target); + + // disable ourselves as we're no longer relevant, don't keep colliding with the player + disable(); + + } else { + // ignore other objects return; } - } else { // Collided with terrain + + } else { + // Collided with terrain, set player's pivot to ourselves player.setPivot(this); } @@ -60,7 +73,7 @@ // Ropes location will be used as the pivot point, so move the location to the collisionPoint. // Currently the position is something like one pixel away from the collisionPoint where there isn't ground. - setPosition (collisionPoint); + setPosition(collisionPoint); // inform network player.handleRopeState(state); @@ -99,7 +112,14 @@ return length; } -void Rope::updateState (RopeState new_state, Vector position, Vector velocity, float new_length) { +Player *Rope::getPivotPlayer (void) { + if (player.getPivot() == this) + return NULL; + else + return dynamic_cast(player.getPivot()); +} + +void Rope::updateState (RopeState new_state, Vector position, Vector velocity, float new_length, Player *pivot_player) { // update physics enabled/disabled state if (new_state == ROPE_FOLDED || new_state == ROPE_FIXED) disable(); @@ -107,11 +127,14 @@ else // new_state == ROPE_FLYING enable(); - // update player.pivot - if (new_state == ROPE_FIXED) - player.setPivot(this); + // update player.pivot to either the given pivot_player, or this rope + if (new_state == ROPE_FIXED) { + if (pivot_player) + player.setPivot(pivot_player); + else + player.setPivot(this); - else if (this->state == ROPE_FIXED) + } else if (this->state == ROPE_FIXED) player.setPivot(NULL); // update position stuff @@ -128,44 +151,57 @@ } void Rope::draw (Graphics *g, PixelCoordinate camera) { - if (state == ROPE_FOLDED) + PixelCoordinate player_pos = player.getCoordinate() - camera; + PixelCoordinate target_pos; + + if (state == ROPE_FOLDED) { return; - PixelCoordinate player_pos = player.getCoordinate() - camera; - PixelCoordinate self_pos = getCoordinate() - camera; + } else if (state == ROPE_FLYING) { + // target is us + target_pos = getCoordinate(); + } else { // state == ROPE_FIXED + // sanity-check + if (player.getPivot() == NULL) + throw Error("Rope::draw in state ROPE_FIXED, yet player.getPivot() is NULL"); + + // target is our pivot + target_pos = player.getPivot()->getCoordinate(); + } + + // align with camera + target_pos -= camera; + + // draw a line from the player to the target chosen above g->get_gc()->draw_line( player_pos.x, player_pos.y, - self_pos.x, self_pos.y, + target_pos.x, target_pos.y, CL_Color::black ); } void Rope::tick (TimeMS dt) { - if (this->state == ROPE_FLYING) { - // super + if (state == ROPE_FLYING) { + // let PhysicsObject handle the flying stage PhysicsObject::tick(dt); - } - else if (this->state == ROPE_FIXED) { - this->position = player.getPivot()->getPosition(); - - // If players pivot is not this rope but some other player don't do anything - // (though it should be released atleast when the player dies) + } else if (state == ROPE_FIXED) { + // if player's pivot is some other player, then don't re-check the terrain if (player.getPivot() != this) return; - // If there's not ground on the pivot point anymore, release the rope + // If there's no ground on the pivot point anymore, release the rope if (!world.collides(position)) { + // XXX: move to some new method state = ROPE_FLYING; length = ROPE_LENGTH; inAir = true; player.setPivot(NULL); player.handleRopeState(state); } - } - else { // ROPE_FOLDED - // Rope shouldn't be ticking if it is folded, but this can still happen - // immediately after the rope has been released + } else { // state == ROPE_FOLDED + // ignore ticks when folded } } + diff -r 09a3b5055862 -r 51d644c8d5a2 src/Rope.hh --- a/src/Rope.hh Mon Dec 08 23:11:40 2008 +0000 +++ b/src/Rope.hh Mon Dec 08 23:21:49 2008 +0000 @@ -26,13 +26,13 @@ */ class Rope : public PhysicsObject { private: - // the owner + /** the owner */ Player &player; - // How long is the rope in its unstrected state + /** How long is the rope in its unstreched state */ float length; - // basic state + /** Current state */ RopeState state; protected: @@ -45,35 +45,40 @@ public: Rope(Player &player); - /* + /** * Throw the rope, so it flies up and away: o._-* */ void throwRope (void); - /* + /** * Release the rope, so if it's currently fixed or flying, then fold it */ void release (void); - /* + /** * Climb up/down the rope */ void changeLength (float delta); - /* + /** * Current state */ RopeState getState (void); - /* + /** * Current length */ float getLength (void); + /** + * If this Rope's player is pivoted to another player, return that player-pivot, else return NULL + */ + Player *getPivotPlayer (void); + /* * For use by NetworkClient */ - void updateState (RopeState state, Vector position, Vector velocity, float length); + void updateState (RopeState state, Vector position, Vector velocity, float length, Player *pivot_player); void updateLength (float length); virtual void tick (TimeMS dt);