ekku@225: #include "Player.hh" ekku@225: #include "Rope.hh" ekku@225: #include "Engine.hh" terom@412: ekku@225: #include ekku@252: #include ekku@225: terom@235: Rope::Rope(Player &player) : terom@311: PhysicsObject(player.state.world, ROPE_MASS, Vector(0,0), Vector(0,0), ROPE, 0.00, false), terom@311: player(player), terom@311: state(ROPE_FOLDED) terom@235: { terom@235: // XXX: better shape ekku@225: std::vector shape(4); ekku@225: shape[0] = Vector(-1, -1); ekku@225: shape[1] = Vector(-1, 1); ekku@225: shape[2] = Vector(1, 1); ekku@225: shape[3] = Vector(1, -1); ekku@225: setShape(shape); ekku@225: } ekku@225: terom@235: void Rope::throwRope (void) { terom@235: state = ROPE_FLYING; ekku@225: terom@235: // XXX: this should probably be more dynamic? terom@235: length = ROPE_LENGTH; terom@235: terom@235: // copy position + velocity from player ekku@285: setPosition (player.getPosition()); terom@235: velocity = player.getVelocity() + player.getDirection() * ROPE_VELOCITY; terom@235: terom@235: // we are FLYING terom@235: inAir = true; terom@235: terom@235: // enable the physics object ekku@225: enable(); terom@241: terom@241: // inform network terom@241: player.handleRopeState(state); ekku@225: } ekku@225: saiam@273: void Rope::onCollision (Vector collisionPoint, PhysicsObject *other) { ekku@322: // Fix the rope to another player if collided with it ekku@305: if (other != NULL) { terom@328: // we collided with another object ekku@305: if (other->getType() == PLAYER) { terom@328: // set our player's pivot to the object that we collided with ekku@305: Player *target = dynamic_cast(other); terom@328: terom@328: // ignore if the rope hits ourself terom@328: if (target == &this->player) ekku@305: return; terom@328: terom@328: // set player's pivot to the other player terom@328: player.setPivot(target); terom@328: terom@328: // disable ourselves as we're no longer relevant, don't keep colliding with the player terom@328: disable(); terom@328: terom@328: } else { terom@328: // ignore other objects ekku@305: return; ekku@305: } terom@328: terom@328: } else { terom@328: // Collided with terrain, set player's pivot to ourselves ekku@322: player.setPivot(this); ekku@305: } terom@282: terom@235: // attached to something! terom@235: state = ROPE_FIXED; ekku@305: velocity = Vector(0,0); ekku@252: ekku@252: // Ropes location will be used as the pivot point, so move the location to the collisionPoint. ekku@252: // Currently the position is something like one pixel away from the collisionPoint where there isn't ground. terom@328: setPosition(collisionPoint); terom@241: terom@241: // inform network terom@241: player.handleRopeState(state); ekku@225: } ekku@225: ekku@225: void Rope::release (void) { ekku@252: // Remove the rope from the PhysicsWorld ekku@252: disable(); ekku@229: terom@235: state = ROPE_FOLDED; ekku@228: ekku@228: // player doesn't have a pivot anymore terom@235: player.setPivot(NULL); terom@241: terom@241: // inform network terom@241: player.handleRopeState(state); ekku@225: } ekku@225: terom@235: void Rope::changeLength (float delta) { terom@241: // change length terom@235: length += delta; terom@241: terom@241: // minimum length terom@235: if (length < 0) terom@235: length = 0; terom@241: terom@241: // inform network terom@241: player.handleRopeLength(length); ekku@231: } ekku@231: ekku@225: RopeState Rope::getState (void) { terom@235: return state; ekku@225: } terom@241: terom@241: float Rope::getLength (void) { terom@241: return length; terom@241: } terom@241: terom@328: Player *Rope::getPivotPlayer (void) { terom@328: if (player.getPivot() == this) terom@328: return NULL; terom@328: else terom@328: return dynamic_cast(player.getPivot()); terom@328: } terom@328: terom@328: void Rope::updateState (RopeState new_state, Vector position, Vector velocity, float new_length, Player *pivot_player) { terom@241: // update physics enabled/disabled state terom@241: if (new_state == ROPE_FOLDED || new_state == ROPE_FIXED) terom@241: disable(); terom@241: terom@241: else // new_state == ROPE_FLYING terom@241: enable(); terom@241: terom@328: // update player.pivot to either the given pivot_player, or this rope terom@328: if (new_state == ROPE_FIXED) { terom@328: if (pivot_player) terom@328: player.setPivot(pivot_player); terom@328: else terom@328: player.setPivot(this); terom@241: terom@328: } else if (this->state == ROPE_FIXED) terom@241: player.setPivot(NULL); terom@241: terom@241: // update position stuff terom@264: updatePhysics(position, velocity, true, FACING_RIGHT, 0); terom@241: terom@241: // update vars terom@241: this->state = new_state; terom@241: this->length = new_length; terom@241: } terom@241: terom@241: void Rope::updateLength (float length) { terom@241: // update length terom@241: this->length = length; terom@241: } ekku@225: terom@412: void Rope::draw (graphics::Display &display, PixelCoordinate camera) { terom@328: PixelCoordinate player_pos = player.getCoordinate() - camera; terom@328: PixelCoordinate target_pos; terom@377: terom@377: // figure out what target is terom@328: if (state == ROPE_FOLDED) { terom@233: return; terom@233: terom@328: } else if (state == ROPE_FLYING) { terom@328: // target is us terom@328: target_pos = getCoordinate(); terom@255: terom@328: } else { // state == ROPE_FIXED terom@328: // sanity-check terom@328: if (player.getPivot() == NULL) terom@328: throw Error("Rope::draw in state ROPE_FIXED, yet player.getPivot() is NULL"); terom@328: terom@328: // target is our pivot terom@328: target_pos = player.getPivot()->getCoordinate(); terom@328: } terom@377: terom@328: // align with camera terom@328: target_pos -= camera; terom@328: terom@328: // draw a line from the player to the target chosen above terom@412: display.get_gc()->draw_line( terom@257: player_pos.x, player_pos.y, terom@328: target_pos.x, target_pos.y, terom@377: ROPE_COLOR_DARK terom@233: ); ekku@225: } ekku@225: ekku@252: void Rope::tick (TimeMS dt) { terom@328: if (state == ROPE_FLYING) { terom@328: // let PhysicsObject handle the flying stage ekku@252: PhysicsObject::tick(dt); ekku@322: terom@328: } else if (state == ROPE_FIXED) { terom@328: // if player's pivot is some other player, then don't re-check the terrain ekku@322: if (player.getPivot() != this) ekku@322: return; ekku@322: terom@328: // If there's no ground on the pivot point anymore, release the rope terom@408: if (!world.terrain.collides(position)) { terom@328: // XXX: move to some new method ekku@322: state = ROPE_FLYING; ekku@322: length = ROPE_LENGTH; ekku@322: inAir = true; ekku@322: player.setPivot(NULL); terom@263: player.handleRopeState(state); ekku@252: } terom@328: } else { // state == ROPE_FOLDED terom@328: // ignore ticks when folded ekku@252: } ekku@252: } terom@328: