src/Rope.cc
author ekku
Mon, 08 Dec 2008 15:37:34 +0000
changeset 285 c080c8c70333
parent 282 e0e4dfc3e528
child 296 4d3ebaa29430
permissions -rw-r--r--
Previous position added, and unsigned int bug fixed
#include "Player.hh"
#include "Rope.hh"      
#include "Engine.hh"
#include "Graphics.hh"
#include <math.h>
#include <stdexcept>

Rope::Rope(Player &player) : 
    PhysicsObject(player.state.world, ROPE_MASS, Vector(0,0), Vector(0,0), ROPE, false), player(player), state(ROPE_FOLDED) 
{
    // XXX: better shape
    std::vector<Vector> shape(4);
    shape[0] = Vector(-1, -1);
    shape[1] = Vector(-1, 1);
    shape[2] = Vector(1, 1);
    shape[3] = Vector(1, -1);
    setShape(shape);
}

void Rope::throwRope (void) {
    state = ROPE_FLYING;

    // XXX: this should probably be more dynamic?
    length = ROPE_LENGTH;
    
    // copy position + velocity from player
    setPosition (player.getPosition());
    velocity = player.getVelocity() + player.getDirection() * ROPE_VELOCITY;
    
    // we are FLYING
    inAir = true;
    
    // enable the physics object
    enable();

    // inform network
    player.handleRopeState(state);
}

void Rope::onCollision (Vector collisionPoint, PhysicsObject *other) {
    (void) other;

    // attached to something!
    state = ROPE_FIXED;
        
    // 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);

    // set player's pivot
    player.setPivot(this);
    
    // inform network
    player.handleRopeState(state);
}

void Rope::release (void) {
    // Remove the rope from the PhysicsWorld
    disable();

    state = ROPE_FOLDED;
    
    // player doesn't have a pivot anymore
    player.setPivot(NULL);
    
    // inform network
    player.handleRopeState(state);
}

void Rope::changeLength (float delta) {
    // change length
    length += delta;
    
    // minimum length
    if (length < 0)
        length = 0;

    // inform network
    player.handleRopeLength(length);
}

RopeState Rope::getState (void) {
    return state;
}
        
float Rope::getLength (void) {
    return length;
}

void Rope::updateState (RopeState new_state, Vector position, Vector velocity, float new_length) {
    // update physics enabled/disabled state
    if (new_state == ROPE_FOLDED || new_state == ROPE_FIXED)
        disable();

    else // new_state == ROPE_FLYING
        enable();
    
    // update player.pivot
    if (new_state == ROPE_FIXED)
        player.setPivot(this);

    else if (this->state == ROPE_FIXED)
        player.setPivot(NULL);

    // update position stuff
    updatePhysics(position, velocity, true, FACING_RIGHT, 0);

    // update vars
    this->state = new_state;
    this->length = new_length;
}

void Rope::updateLength (float length) {
    // update length
    this->length = length;
}

float Rope::getPivotForce (PhysicsObject *bob) {
    if ((position - bob->getPosition()).length() >= length)
        return ROPE_FORCE;
    else
        return 0;
}

void Rope::draw (Graphics *g, PixelCoordinate camera) {
    if (state == ROPE_FOLDED)
        return;

    PixelCoordinate player_pos = player.getCoordinate() - camera;
    PixelCoordinate self_pos = getCoordinate() - camera;

    g->get_gc()->draw_line(
        player_pos.x, player_pos.y,
        self_pos.x, self_pos.y,
        CL_Color::black
    );
}

void Rope::tick (TimeMS dt) {
    if (this->state == ROPE_FLYING) {
        // super
        PhysicsObject::tick(dt); 
    }
    else if (this->state == ROPE_FIXED) {
        // If there's not ground on the pivot point anymore, release the rope
        if (!world.collides(position)) { 
            this->state = ROPE_FLYING;
            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
    }
}