Trabajando en las nuevas colisiones

This commit is contained in:
2022-09-04 15:39:12 +02:00
parent 5eaf44d0b8
commit 8630a0ae56
5 changed files with 224 additions and 161 deletions

View File

@@ -11,6 +11,7 @@ Player::Player(player_t ini, std::string tileset, std::string animation, SDL_Ren
this->asset = asset;
this->renderer = renderer;
this->input = input;
this->room = room;
// Crea objetos
texture = new LTexture(renderer, asset->get(tileset));
@@ -24,6 +25,13 @@ Player::Player(player_t ini, std::string tileset, std::string animation, SDL_Ren
jump_ini = ini.jump_ini;
status = ini.status;
x = ini.x;
y = ini.y;
vx = ini.vx;
vy = ini.vy;
w = 8;
h = 16;
sprite->setPosX(ini.x);
sprite->setPosY(ini.y);
sprite->setVelX(ini.vx);
@@ -34,7 +42,9 @@ Player::Player(player_t ini, std::string tileset, std::string animation, SDL_Ren
sprite->setFlip(ini.flip);
lastPosition = getRect();
collider = getRect();
colliderBox = getRect();
const SDL_Point p = {0, 0};
colliderPoints.insert(colliderPoints.end(), {p, p, p, p, p, p, p, p});
}
// Destructor
@@ -54,14 +64,14 @@ void Player::render()
// Actualiza las variables del objeto
void Player::update()
{
setLastPosition(); // Guarda la posición actual en la variable lastPosition
checkInput(); // Comprueba las entradas y modifica variables
move(); // Recalcula la posición del jugador y su animación
checkBorders(); // Comprueba si está situado en alguno de los cuatro bordes de la habitación
applyGravity(); // Aplica gravedad al jugador
checkJump(); // Comprueba si ha finalizado el salto
collider = getRect(); // Obtiene el rectangulo que delimita al jugador
setLastPosition(); // Guarda la posición actual en la variable lastPosition
checkInput(); // Comprueba las entradas y modifica variables
move(); // Recalcula la posición del jugador y su animación
checkBorders(); // Comprueba si está situado en alguno de los cuatro bordes de la habitación
applyGravity(); // Aplica gravedad al jugador
checkJump(); // Comprueba si ha finalizado el salto
checkOnFloor(); // Comprueba si el jugador esta sobre el suelo
colliderBox = getRect(); // Obtiene el rectangulo que delimita al jugador
}
// Comprueba las entradas y modifica variables
@@ -70,17 +80,17 @@ void Player::checkInput()
// Solo comprueba las entradas de dirección cuando está de pie
if ((input->checkInput(INPUT_LEFT, REPEAT_TRUE)) && (status == STATUS_STANDING))
{
sprite->setVelX(-0.6f);
vx = -0.6f;
sprite->setFlip(SDL_FLIP_HORIZONTAL);
}
else if ((input->checkInput(INPUT_RIGHT, REPEAT_TRUE)) && (status == STATUS_STANDING))
{
sprite->setVelX(0.6f);
vx = 0.6f;
sprite->setFlip(SDL_FLIP_NONE);
}
else if (status == STATUS_STANDING)
{
sprite->setVelX(0);
vx = 0.0f;
}
if (input->checkInput(INPUT_UP, REPEAT_TRUE))
@@ -135,20 +145,20 @@ void Player::switchBorders()
{
if (border == BORDER_TOP)
{
sprite->setPosY(PLAY_AREA_BOTTOM - sprite->getHeight() - 1);
y = PLAY_AREA_BOTTOM - sprite->getHeight() - 1;
jump_ini += 128;
}
else if (border == BORDER_BOTTOM)
{
sprite->setPosY(PLAY_AREA_TOP + 1);
y = PLAY_AREA_TOP + 1;
}
else if (border == BORDER_RIGHT)
{
sprite->setPosX(PLAY_AREA_LEFT + 1);
x = PLAY_AREA_LEFT + 1;
}
if (border == BORDER_LEFT)
{
sprite->setPosX(PLAY_AREA_RIGHT - sprite->getWidth() - 1);
x = PLAY_AREA_RIGHT - sprite->getWidth() - 1;
}
onBorder = false;
@@ -175,23 +185,23 @@ void Player::setStatus(int value)
if ((value == STATUS_JUMPING) && (status == STATUS_STANDING))
{
status = STATUS_JUMPING;
sprite->setVelY(-MAX_VY);
jump_ini = sprite->getPosY();
vy = -MAX_VY;
jump_ini = y;
}
// Modifica el estado a 'cayendo'
if (value == STATUS_FALLING)
{
status = STATUS_FALLING;
sprite->setVelY(MAX_VY);
sprite->setVelX(0);
vy = MAX_VY;
vx = 0.0f;
}
// Modifica el estado a 'de pie'
if (value == STATUS_STANDING)
{
status = STATUS_STANDING;
sprite->setVelY(0.0f);
vy = 0.0f;
}
}
@@ -212,10 +222,10 @@ void Player::applyGravity()
{
if (status == STATUS_JUMPING)
{
sprite->setVelY(sprite->getVelY() + GRAVITY);
if (sprite->getVelY() > MAX_VY)
vy += GRAVITY;
if (vy > MAX_VY)
{
sprite->setVelY(MAX_VY);
vy = MAX_VY;
}
}
}
@@ -229,7 +239,7 @@ SDL_Rect Player::getRect()
// Obtiene el rectangulo de colision del jugador
SDL_Rect &Player::getCollider()
{
return collider;
return colliderBox;
}
// Guarda la posición actual en la variable lastPosition
@@ -241,15 +251,51 @@ void Player::setLastPosition()
// Deshace el ultimo movimiento
void Player::undoLastMove()
{
sprite->setPosX(lastPosition.x);
sprite->setPosY(lastPosition.y);
x = lastPosition.x;
y = lastPosition.y;
}
// Recalcula la posición del jugador y su animación
void Player::move()
{
sprite->update();
if (sprite->getVelX() != 0)
const int tileSize = 8;
// Calcula la nueva posición del jugador y compensa en caso de colisión
x += vx;
// Comprueba colisiones con muros
if (checkWalls())
{
// Recoloca
if (vx > 0)
{
x -= ((int)x + w) % tileSize;
}
else
{
x += tileSize - ((int)x % tileSize);
}
// vx = 0.0f;
}
y += vy;
if (checkWalls())
{
// Recoloca
if (vy > 0.0f)
{
y -= ((int)y + h) % tileSize;
}
else
{
y += tileSize - ((int)y % tileSize);
}
setStatus(STATUS_FALLING);
}
// Establece la animación
if (vx != 0)
{
sprite->setCurrentAnimation("walk");
}
@@ -257,6 +303,11 @@ void Player::move()
{
sprite->setCurrentAnimation("stand");
}
sprite->animate();
// Actualiza la posición del sprite
sprite->setPosX(x);
sprite->setPosY(y);
}
// Comprueba si ha finalizado el salto
@@ -270,6 +321,73 @@ void Player::checkJump()
}
}
// Comprueba si el jugador esta sobre el suelo
void Player::checkOnFloor()
{
// Comprueba si tiene suelo bajo los pies solo cuando no hay velocidad de subida
// y solo cuando el pie este encima de un bloque, es decir, en multiplos de 8
// *** HAY UN POSIBLE PROBLEMA y es que caiga muy rapido y viaje a mas de un pixel de velocidad,
// con lo que se saltaria la comprobación
// *** POSIBLE SOLUCION. Comprobar si el tile actual del pie es diferente al tile del pie previo.
// Esto indica que se ha saltado la comprobacion cada 8 pixeles.
// En este caso habría que recolocar al jugador en el sitio
// *** PARECE RESUELTO
const int a = (lastPosition.y + 16) / 8;
const int b = getLeftFoot().y / 8;
const bool tile_change = a != b;
const bool is_not_going_up = getVelY() >= 0;
const bool is_tile_aligned = getLeftFoot().y % 8 == 0;
if (((is_not_going_up) && (is_tile_aligned)) || ((is_not_going_up) && (tile_change)))
{
bool test = false;
test |= (room->getTile(getLeftFoot()) == TILE_SOLID);
test |= (room->getTile(getRightFoot()) == TILE_SOLID);
test |= (room->getTile(getLeftFoot()) == TILE_TRAVESSABLE);
test |= (room->getTile(getRightFoot()) == TILE_TRAVESSABLE);
// Tiene uno de los pies sobre una superficie
if (test)
{
setStatus(STATUS_STANDING);
// Si ha habido un cambio de tile, hay que recolocarlo
if (tile_change)
{
const int offset = (int)y % 8;
y = ((int)y - offset);
}
}
// Tiene ambos pies sobre el vacío
else if (getStatus() != STATUS_JUMPING)
{
setStatus(STATUS_FALLING);
}
}
}
// Comprueba que el jugador no atraviese ninguna pared
bool Player::checkWalls()
{
// Actualiza los puntos de colisión
updateColliderPoints();
// Comprueba si ha colisionado con un muro
bool wall = false;
for (auto c : colliderPoints)
{
wall |= (room->getTile(c) == TILE_SOLID);
}
return wall;
}
// Obtiene algunos parametros del jugador
player_t Player::getSpawnParams()
{
@@ -290,4 +408,24 @@ player_t Player::getSpawnParams()
void Player::reLoadTexture()
{
texture->reLoad();
}
// Establece el valor de la variable
void Player::setRoom(Room *room)
{
this->room = room;
}
// Actualiza los puntos de colisión
void Player::updateColliderPoints()
{
const SDL_Rect rect = getRect();
colliderPoints[0] = {rect.x, rect.y};
colliderPoints[1] = {rect.x + 7, rect.y};
colliderPoints[2] = {rect.x + 7, rect.y + 7};
colliderPoints[3] = {rect.x, rect.y + 7};
colliderPoints[4] = {rect.x, rect.y + 8};
colliderPoints[5] = {rect.x + 7, rect.y + 8};
colliderPoints[6] = {rect.x + 7, rect.y + 15};
colliderPoints[7] = {rect.x, rect.y + 15};
}