--- 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<NetworkClientPlayerBase*>(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) {
--- 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);
}
/*
--- 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);
};
--- 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,
--- 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<NetworkServerPlayer*>(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);
--- 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<Player*>(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*>(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
}
}
+
--- 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);