278 lines
5.6 KiB
C++
278 lines
5.6 KiB
C++
#include "player.h"
|
|
|
|
// Constructor
|
|
Player::Player(SDL_Renderer *renderer, Asset *asset, Input *input, Map *map)
|
|
{
|
|
this->asset = asset;
|
|
this->renderer = renderer;
|
|
this->input = input;
|
|
this->map = map;
|
|
|
|
sound_jump = JA_LoadSound(asset->get("sound_player_jump.wav").c_str());
|
|
sound_death = JA_LoadSound(asset->get("sound_player_death.wav").c_str());
|
|
sound_coin = JA_LoadSound(asset->get("sound_player_coin.wav").c_str());
|
|
|
|
texture = new LTexture();
|
|
loadTextureFromFile(texture, asset->get("player.png"), renderer);
|
|
|
|
sprite = new AnimatedSprite(texture, renderer, asset->get("player.ani"));
|
|
|
|
w = 16;
|
|
h = 24;
|
|
x = 3 * 16;
|
|
y = 168;
|
|
vx = 0;
|
|
vy = 0;
|
|
const SDL_Rect rect = {(int)x, (int)y, 16, 24};
|
|
sprite->setPos(rect);
|
|
sprite->setCurrentAnimation("stand");
|
|
sprite->setFlip(SDL_FLIP_HORIZONTAL);
|
|
|
|
// jumpStrenght = -5.6f;
|
|
jumpStrenght = 2.0f;
|
|
gravity = 0.3f;
|
|
accelX = 0.12f;
|
|
maxVX = 1.5f;
|
|
maxVY = 4.0f;
|
|
|
|
jumping = false;
|
|
jumpPressed = false;
|
|
standing = true;
|
|
invulnerable = false;
|
|
enabled = true;
|
|
cooldown = 0;
|
|
lives = 10;
|
|
coins = 0;
|
|
key.insert(key.end(), {0, 0, 0, 0, 0, 0});
|
|
const SDL_Point p = {0, 0};
|
|
collider.insert(collider.end(), {p, p, p, p, p, p, p, p, p, p, p, p});
|
|
underFeet.insert(underFeet.end(), {p, p, p});
|
|
}
|
|
|
|
// Destructor
|
|
Player::~Player()
|
|
{
|
|
JA_DeleteSound(sound_jump);
|
|
JA_DeleteSound(sound_death);
|
|
JA_DeleteSound(sound_coin);
|
|
|
|
texture->unload();
|
|
delete texture;
|
|
|
|
delete sprite;
|
|
}
|
|
|
|
// Actualiza todas las variables
|
|
void Player::update()
|
|
{
|
|
checkInput();
|
|
addGravity();
|
|
move();
|
|
animate();
|
|
}
|
|
|
|
// Dibuja el objeto
|
|
void Player::render()
|
|
{
|
|
sprite->render();
|
|
}
|
|
|
|
// Comprueba las entradas y modifica variables
|
|
void Player::checkInput()
|
|
{
|
|
if (input->checkInput(INPUT_LEFT, REPEAT_TRUE))
|
|
{
|
|
vx = std::max(vx -= accelX, -maxVX);
|
|
sprite->setFlip(SDL_FLIP_NONE);
|
|
}
|
|
else if (input->checkInput(INPUT_RIGHT, REPEAT_TRUE))
|
|
{
|
|
vx = std::min(vx += accelX, maxVX);
|
|
sprite->setFlip(SDL_FLIP_HORIZONTAL);
|
|
}
|
|
else
|
|
{
|
|
if (vx > 0.0f)
|
|
{
|
|
vx = std::max(vx -= accelX, 0.0f);
|
|
}
|
|
else
|
|
{
|
|
vx = std::min(vx += accelX, 0.0f);
|
|
}
|
|
}
|
|
|
|
if (input->checkInput(INPUT_UP, REPEAT_TRUE))
|
|
{
|
|
if (!jumping)
|
|
{
|
|
if (!jumpPressed)
|
|
{
|
|
jumpStrenght = 2.0f;
|
|
vy -= jumpStrenght;
|
|
jumping = true;
|
|
jumpPressed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
jumpStrenght = std::max(jumpStrenght -= 0.4f, 0.0f);
|
|
vy -= jumpStrenght;
|
|
}
|
|
jumpPressed = true;
|
|
}
|
|
else
|
|
{
|
|
jumpPressed = false;
|
|
}
|
|
}
|
|
|
|
// Aplica la gravedad
|
|
void Player::addGravity()
|
|
{
|
|
if (!isOnFloor())
|
|
{
|
|
vy = std::min(vy += gravity, maxVY);
|
|
jumping = true;
|
|
}
|
|
}
|
|
|
|
// Actualiza los puntos de colisión
|
|
void Player::updateColliders()
|
|
{
|
|
const SDL_Point p = {(int)x, (int)y};
|
|
|
|
// Lado izquierdo
|
|
collider[0] = p;
|
|
collider[1] = {p.x, p.y + 7};
|
|
collider[2] = {p.x, p.y + 12};
|
|
collider[3] = {p.x, p.y + 18};
|
|
collider[4] = {p.x, p.y + 23};
|
|
|
|
// Lado derecho
|
|
collider[5] = {p.x + 15, p.y};
|
|
collider[6] = {p.x + 15, p.y + 7};
|
|
collider[7] = {p.x + 15, p.y + 12};
|
|
collider[8] = {p.x + 15, p.y + 18};
|
|
collider[9] = {p.x + 15, p.y + 23};
|
|
|
|
// Centro
|
|
collider[10] = {p.x + 7, p.y};
|
|
collider[11] = {p.x + 7, p.y + 23};
|
|
}
|
|
|
|
// Actualiza los puntos de los pies
|
|
void Player::updateFeet()
|
|
{
|
|
const SDL_Point p = {(int)x, (int)y};
|
|
|
|
underFeet[0] = {p.x, p.y + h};
|
|
underFeet[1] = {p.x + 7, p.y + h};
|
|
underFeet[2] = {p.x + 15, p.y + h};
|
|
}
|
|
|
|
// Compruena las colisiones con el mapa
|
|
bool Player::checkMapCollisions()
|
|
{
|
|
bool collision = false;
|
|
|
|
updateColliders();
|
|
|
|
for (auto c : collider)
|
|
{
|
|
collision |= (map->getTile(c) == wall);
|
|
}
|
|
|
|
return collision;
|
|
}
|
|
|
|
// Mueve al jugador en función de la velocidad/desplazamiento
|
|
void Player::move()
|
|
{
|
|
const int tile = map->getTileWidth();
|
|
|
|
x += vx;
|
|
if (checkMapCollisions())
|
|
{
|
|
// Recoloca
|
|
if (vx > 0)
|
|
{
|
|
do
|
|
{
|
|
x--;
|
|
} while (checkMapCollisions());
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
x++;
|
|
} while (checkMapCollisions());
|
|
}
|
|
|
|
vx = 0.0f;
|
|
}
|
|
|
|
const bool wasOnFloor = isOnFloor();
|
|
y += vy;
|
|
if (checkMapCollisions())
|
|
{
|
|
// Recoloca
|
|
if (vy > 0.0f)
|
|
{
|
|
y -= ((int)y + h) % tile;
|
|
}
|
|
else
|
|
{
|
|
y += tile - ((int)y % tile);
|
|
}
|
|
|
|
jumping = false;
|
|
vy = 0.0f;
|
|
}
|
|
else if ((!wasOnFloor) && (isOnFloor()) && (vy > 0.0f))
|
|
{
|
|
jumping = false;
|
|
vy = 0.0f;
|
|
y -= ((int)y + h) % tile;
|
|
}
|
|
|
|
sprite->setPosX(x);
|
|
sprite->setPosY(y);
|
|
}
|
|
|
|
// Anima al jugador
|
|
void Player::animate()
|
|
{
|
|
if (jumping)
|
|
{
|
|
sprite->setCurrentAnimation("jump");
|
|
}
|
|
else
|
|
{
|
|
if (abs(vx) < 0.50f)
|
|
{
|
|
sprite->setCurrentAnimation("stand");
|
|
}
|
|
else
|
|
{
|
|
sprite->setCurrentAnimation("walk");
|
|
}
|
|
}
|
|
|
|
sprite->animate();
|
|
}
|
|
|
|
// Comprueba si el jugador tiene suelo debajo de los pies
|
|
bool Player::isOnFloor()
|
|
{
|
|
bool onFloor = false;
|
|
|
|
updateFeet();
|
|
|
|
for (auto f : underFeet)
|
|
{
|
|
onFloor |= ((map->getTile(f) == wall) || (map->getTile(f) == passable));
|
|
}
|
|
return onFloor;
|
|
} |