#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);
}
}