src/Player.cc
author nireco
Sat, 06 Dec 2008 13:58:11 +0000
changeset 217 de56d9d16705
parent 216 a384bf0634f0
child 218 86d22fe82b30
permissions -rw-r--r--
and yet better image drawing
#include "Engine.hh"
#include "Player.hh" 

#include <cstdlib>
#include <ClanLib/display.h>
#include <string>

//Player::image = NULL;

//Player::image = CL_Surface("../../pics/skin.png");

const std::string player_image_filename = "../../pics/skin.png";

CL_Surface player_image;
bool player_image_created = false;

Player::Player(GameState &state, Vector position, bool visible) : 
    PhysicsObject(state.world, PLAYER_MASS, position, Vector(0, 0)), state(state), visible(visible), arsenal(), selectedWeapon(0), changing(false) {
    // TODO: arsenal's size should be affected by some value
    // and weapons should be loaded from somewhere, not generated here
    for(int i = 0; i < 5; i++) {
        arsenal.push_back(Weapon(10000, (5-i)*40+30, i*6+5, i*100+50, "asdf"));
    }

    if(!player_image_created) {
        player_image_created = true;
        player_image = CL_Surface(player_image_filename);
    }
//    if(Player::image == NULL) {
//        Player::image = CL_PNGProvider::create("../../pics/skin.png");
//    }

    std::vector<Vector> shape(4);
    shape[0] = Vector(0,-9);
    shape[1] = Vector(6,0);
    shape[2] = Vector(0,9); 
    shape[3] = Vector(-6,0);
    // Initialize the shape of the player (salmiakki shape)
    setShape(shape);
    collision_elasticity = PLAYER_COLLISION_ELASTICITY;
    world.addPlayerObject(this);
}
 
void Player::handleDig (Vector position, float radius) {
    Vector unitVectorAim = facingRight ? Vector(std::cos(aim), -std::sin(aim)) : 
            Vector(-std::cos(aim), -std::sin(aim));
    float shotspeed = 0*PHYSICS_TICK_MS;
    Vector shotVelocity = unitVectorAim*shotspeed;
    new Projectile(this->state, this->position, shotVelocity, false, radius, 1);

}

void Player::debugInfo (void) {
    Engine::log(DEBUG, "Player.debugInfo") << "In air: " << this->inAir;
}

/**
 * shoots the selected weapon.
 * TODO: selection and weapon information
 */
void LocalPlayer::shoot (void) {
    // here should be somehow considered which projectile it is
    if(!canShoot())
        return;
    reloadTimer += getWeapon().reloadTime;
    Vector unitVectorAim = facingRight ? Vector(std::cos(aim), -std::sin(aim)) : 
            Vector(-std::cos(aim), -std::sin(aim));
    float shotspeed = getWeapon().velocity*PHYSICS_TICK_MS/2;
    Vector shotRelativeVelocity = unitVectorAim * shotspeed;
    Vector shotVelocity = this->velocity + shotRelativeVelocity;
    Vector shotPosition = this->position + unitVectorAim*10;
    new Projectile(this->state, shotPosition, shotVelocity, true, getWeapon().explosionRadius);
}

void LocalPlayer::handleMove (PlayerInput_Move input) {
    float fx = 0; // Force in x-direction
    float da = 0; // Crosshair angle

    // handle left/right
    if ((input & INPUT_MOVE_LEFT) && (velocity.x > -PLAYER_MAX_SPEED))
        fx -= PLAYER_MOVE_FORCE;

    if ((input & INPUT_MOVE_RIGHT) && (velocity.x < PLAYER_MAX_SPEED))
        fx += PLAYER_MOVE_FORCE;

    if (input & INPUT_MOVE_UP)
        da += CROSSHAIR_ANGLE_SPEED;

    if (input & INPUT_MOVE_DOWN)
        da -= CROSSHAIR_ANGLE_SPEED;

    if (input & INPUT_MOVE_JUMP) {
        if ((input & INPUT_MOVE_LEFT))
            jump(-1);
        else if ((input & INPUT_MOVE_RIGHT))
            jump(1);
        else
            jump(0);
    }

    if (input & INPUT_MOVE_DIG) {
        // Should create Projectile which destroys ground, but also should be destroyed then,
        // but it doesn't.
        // But this now just segfaults
//        world.addObject(new Projectile(state, position, true));

        handleDig(position, 15);
    }

    if (input & INPUT_CHANGE) {
        if(changing) {

        } else {
            changing = true;
            selectedWeapon = (selectedWeapon+1)%arsenal.size();
            Engine::log(DEBUG, "Player.cc:input ") << "changed weapon " << selectedWeapon;
        }
    } else {
        changing = false;
    }

    if (input & INPUT_SHOOT) {
        this->shoot();
    }



    // Player facing
    if (fx < 0) setFacing(false);
    else if (fx > 0) setFacing(true);


    this->changeAim(da); // Move crosshair

    // Apply force
    applyForce(Vector(fx, 0));

}

Weapon& Player::getWeapon() {
    return arsenal[selectedWeapon%arsenal.size()];
}

void Player::draw(CL_GraphicContext *gc) {

    int img_num_aim = 9;
    int aim_img_idx = (int)((1 - (getAim()+KG_PI/2)/KG_PI)*img_num_aim);
    int img_height = 9;
    int img_width = 10;

    CL_Rectf destination(position.x-4, position.y-4, position.x+5, position.y+4);
    if(!getFacing()) {
        destination = CL_Rect(position.x+5, position.y-4, position.x-4, position.y+4);
    }

    player_image.draw_subpixel(CL_Rectf(1, aim_img_idx*img_height+1, 1+img_width, (aim_img_idx+1)*img_height+1), 
            destination, gc);
    
    const uint16_t chlen = 10;
    uint16_t x = position.x;
    uint16_t y = position.y;
    if (facingRight) {
        gc->draw_line(x + std::cos(aim)*chlen/2, 
                      y - std::sin(aim)*chlen/2,
                      x + std::cos(aim)*chlen,
                      y - std::sin(aim)*chlen,
                      CL_Color::black);
    } else {
        gc->draw_line(x - std::cos(aim)*chlen/2, 
                      y - std::sin(aim)*chlen/2,
                      x - std::cos(aim)*chlen,
                      y - std::sin(aim)*chlen,
                      CL_Color::black);
    }
}