Seguimos con las nuevas colisiones

This commit is contained in:
2022-09-04 18:04:32 +02:00
parent 8630a0ae56
commit 1351943c79
5 changed files with 111 additions and 104 deletions

View File

@@ -30,6 +30,7 @@ Game::Game(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input)
ticksSpeed = 15; ticksSpeed = 15;
playerLives = 9; playerLives = 9;
itemsPicked = 0; itemsPicked = 0;
player->setInvincible(true);
section.name = SECTION_PROG_GAME; section.name = SECTION_PROG_GAME;
section.subsection = SUBSECTION_GAME_PLAY; section.subsection = SUBSECTION_GAME_PLAY;
@@ -221,19 +222,19 @@ void Game::renderDebugInfo()
const int inc = debugText->getCharacterWidth() + 1; const int inc = debugText->getCharacterWidth() + 1;
int line = 131; int line = 131;
text = std::to_string((int)player->x) + "," + std::to_string((int)player->y); text = std::to_string(player->getRect().x) + "," + std::to_string(player->getRect().y);
debugText->write(0, line += inc, text); debugText->write(0, line += inc, text);
text = "status: " + std::to_string(player->status); text = "status: " + std::to_string(player->status);
debugText->write(0, line += inc, text); debugText->write(0, line += inc, text);
// text = "foot: " + std::to_string((int)player->getLeftFoot().y); text = "foot: " + std::to_string((int)player->getLeftFoot().y);
// debugText->write(0, line += inc, text); debugText->write(0, line += inc, text);
// const int a = (player->lastPosition.y + 16) / 8; const int a = (player->lastPosition.y + 16) / 8;
// const int b = player->getLeftFoot().y / 8; const int b = player->getLeftFoot().y / 8;
// text = "tile: " + std::to_string(a) + " - " + std::to_string(b); text = "tile: " + std::to_string(a) + " - " + std::to_string(b);
// debugText->write(0, line += inc, text); debugText->write(0, line += inc, text);
const bool collision = checkPlayerAndEnemies(); const bool collision = checkPlayerAndEnemies();
text = "collision: " + std::to_string(collision); text = "collision: " + std::to_string(collision);
@@ -313,6 +314,11 @@ void Game::checkPlayerAndItems()
// Mata al jugador // Mata al jugador
void Game::killPlayer() void Game::killPlayer()
{ {
if (player->getInvincible())
{
return;
}
playerLives--; playerLives--;
// Destruye la habitacion y el jugador // Destruye la habitacion y el jugador

View File

@@ -21,6 +21,7 @@ Player::Player(player_t ini, std::string tileset, std::string animation, SDL_Ren
color = stringToColor("white"); color = stringToColor("white");
onBorder = false; onBorder = false;
border = BORDER_TOP; border = BORDER_TOP;
invincible = false;
jump_ini = ini.jump_ini; jump_ini = ini.jump_ini;
status = ini.status; status = ini.status;
@@ -34,8 +35,6 @@ Player::Player(player_t ini, std::string tileset, std::string animation, SDL_Ren
sprite->setPosX(ini.x); sprite->setPosX(ini.x);
sprite->setPosY(ini.y); sprite->setPosY(ini.y);
sprite->setVelX(ini.vx);
sprite->setVelY(ini.vy);
sprite->setWidth(8); sprite->setWidth(8);
sprite->setHeight(16); sprite->setHeight(16);
@@ -64,14 +63,11 @@ void Player::render()
// Actualiza las variables del objeto // Actualiza las variables del objeto
void Player::update() void Player::update()
{ {
setLastPosition(); // Guarda la posición actual en la variable lastPosition checkInput(); // Comprueba las entradas y modifica variables
checkInput(); // Comprueba las entradas y modifica variables move(); // Recalcula la posición del jugador
move(); // Recalcula la posición del jugador y su animación animate(); // Establece la animación del jugador
checkBorders(); // Comprueba si está situado en alguno de los cuatro bordes de la habitación checkBorders(); // Comprueba si está situado en alguno de los cuatro bordes de la habitación
applyGravity(); // Aplica gravedad al jugador checkJumpEnd(); // Comprueba si ha finalizado el salto al alcanzar la altura de inicio
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 // Comprueba las entradas y modifica variables
@@ -114,22 +110,22 @@ int Player::getBorder()
// Comprueba si está situado en alguno de los cuatro bordes de la habitación // Comprueba si está situado en alguno de los cuatro bordes de la habitación
void Player::checkBorders() void Player::checkBorders()
{ {
if (sprite->getPosX() < PLAY_AREA_LEFT) if (x < PLAY_AREA_LEFT)
{ {
border = BORDER_LEFT; border = BORDER_LEFT;
onBorder = true; onBorder = true;
} }
else if (sprite->getPosX() > PLAY_AREA_RIGHT - sprite->getWidth()) else if (x > PLAY_AREA_RIGHT - w)
{ {
border = BORDER_RIGHT; border = BORDER_RIGHT;
onBorder = true; onBorder = true;
} }
else if (sprite->getPosY() < PLAY_AREA_TOP) else if (y < PLAY_AREA_TOP)
{ {
border = BORDER_TOP; border = BORDER_TOP;
onBorder = true; onBorder = true;
} }
else if (sprite->getPosY() > PLAY_AREA_BOTTOM - sprite->getHeight()) else if (y > PLAY_AREA_BOTTOM - h)
{ {
border = BORDER_BOTTOM; border = BORDER_BOTTOM;
onBorder = true; onBorder = true;
@@ -145,7 +141,7 @@ void Player::switchBorders()
{ {
if (border == BORDER_TOP) if (border == BORDER_TOP)
{ {
y = PLAY_AREA_BOTTOM - sprite->getHeight() - 1; y = PLAY_AREA_BOTTOM - h - 1;
jump_ini += 128; jump_ini += 128;
} }
else if (border == BORDER_BOTTOM) else if (border == BORDER_BOTTOM)
@@ -158,7 +154,7 @@ void Player::switchBorders()
} }
if (border == BORDER_LEFT) if (border == BORDER_LEFT)
{ {
x = PLAY_AREA_RIGHT - sprite->getWidth() - 1; x = PLAY_AREA_RIGHT - w - 1;
} }
onBorder = false; onBorder = false;
@@ -167,15 +163,13 @@ void Player::switchBorders()
// Obtiene el valor del pixel inferior izquierdo del jugador // Obtiene el valor del pixel inferior izquierdo del jugador
SDL_Point Player::getLeftFoot() SDL_Point Player::getLeftFoot()
{ {
SDL_Point point = {(int)sprite->getPosX(), (int)sprite->getPosY() + sprite->getHeight()}; return {(int)x, (int)y + h};
return point;
} }
// Obtiene el valor del pixel inferior derecho del jugador // Obtiene el valor del pixel inferior derecho del jugador
SDL_Point Player::getRightFoot() SDL_Point Player::getRightFoot()
{ {
SDL_Point point = {(int)sprite->getPosX() + sprite->getWidth() - 1, (int)sprite->getPosY() + sprite->getHeight()}; return {(int)x + 7, (int)y + h};
return point;
} }
// Cambia el estado del jugador // Cambia el estado del jugador
@@ -211,12 +205,6 @@ int Player::getStatus()
return status; return status;
} }
// Obtiene la velocidad en el eje Y del jugador
float Player::getVelY()
{
return sprite->getVelY();
}
// Aplica gravedad al jugador // Aplica gravedad al jugador
void Player::applyGravity() void Player::applyGravity()
{ {
@@ -233,32 +221,22 @@ void Player::applyGravity()
// Obtiene el rectangulo que delimita al jugador // Obtiene el rectangulo que delimita al jugador
SDL_Rect Player::getRect() SDL_Rect Player::getRect()
{ {
return sprite->getRect(); return {(int)x, (int)y, w, h};
} }
// Obtiene el rectangulo de colision del jugador // Obtiene el rectangulo de colision del jugador
SDL_Rect &Player::getCollider() SDL_Rect &Player::getCollider()
{ {
colliderBox = getRect();
return colliderBox; return colliderBox;
} }
// Guarda la posición actual en la variable lastPosition
void Player::setLastPosition()
{
lastPosition = getRect();
}
// Deshace el ultimo movimiento
void Player::undoLastMove()
{
x = lastPosition.x;
y = lastPosition.y;
}
// Recalcula la posición del jugador y su animación // Recalcula la posición del jugador y su animación
void Player::move() void Player::move()
{ {
const int tileSize = 8; const int tileSize = room->getTileSize();
lastPosition = {(int)x, (int)y};
applyGravity();
// Calcula la nueva posición del jugador y compensa en caso de colisión // Calcula la nueva posición del jugador y compensa en caso de colisión
x += vx; x += vx;
@@ -267,16 +245,16 @@ void Player::move()
if (checkWalls()) if (checkWalls())
{ {
// Recoloca // Recoloca
if (vx > 0) if (vx > 0.0f)
{ {
x -= ((int)x + w) % tileSize; x = (int)x - ((int)x + w) % tileSize;
} }
else else
{ {
x += tileSize - ((int)x % tileSize); x = (int)x + tileSize - ((int)x % tileSize);
} }
// vx = 0.0f; //vx = 0.0f;
} }
y += vy; y += vy;
@@ -284,16 +262,31 @@ void Player::move()
{ {
// Recoloca // Recoloca
if (vy > 0.0f) if (vy > 0.0f)
{ { // Bajando
y -= ((int)y + h) % tileSize; // y -= ((int)y + h) % tileSize;
y -= 8;
setStatus(STATUS_STANDING);
} }
else else
{ { // Subiendo
y += tileSize - ((int)y % tileSize); y += tileSize - ((int)y % tileSize);
setStatus(STATUS_FALLING);
} }
setStatus(STATUS_FALLING); }
else
// Si no colisiona con los muros, comprueba los tiles atravesables
{
checkOnFloor();
} }
// Actualiza la posición del sprite
sprite->setPosX(x);
sprite->setPosY(y);
}
// Establece la animación del jugador
void Player::animate()
{
// Establece la animación // Establece la animación
if (vx != 0) if (vx != 0)
{ {
@@ -304,18 +297,14 @@ void Player::move()
sprite->setCurrentAnimation("stand"); sprite->setCurrentAnimation("stand");
} }
sprite->animate(); sprite->animate();
// Actualiza la posición del sprite
sprite->setPosX(x);
sprite->setPosY(y);
} }
// Comprueba si ha finalizado el salto // Comprueba si ha finalizado el salto al alcanzar la altura de inicio
void Player::checkJump() void Player::checkJumpEnd()
{ {
if (status == STATUS_JUMPING) if (status == STATUS_JUMPING)
if (sprite->getVelY() > 0) if (vy > 0)
if (sprite->getPosY() > jump_ini) if (y >= jump_ini)
{ {
setStatus(STATUS_FALLING); setStatus(STATUS_FALLING);
} }
@@ -324,45 +313,35 @@ void Player::checkJump()
// Comprueba si el jugador esta sobre el suelo // Comprueba si el jugador esta sobre el suelo
void Player::checkOnFloor() void Player::checkOnFloor()
{ {
// Comprueba si tiene suelo bajo los pies solo cuando no hay velocidad de subida const int tileSize = room->getTileSize();
// 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, const int a = (lastPosition.y + h) / tileSize;
// con lo que se saltaria la comprobación const int b = getLeftFoot().y / tileSize;
// *** 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 tile_change = a != b;
const bool is_not_going_up = getVelY() >= 0; const bool going_down = vy >= 0.0f;
const bool is_tile_aligned = getLeftFoot().y % 8 == 0; const bool is_tile_aligned = getLeftFoot().y % tileSize == 0;
if (((is_not_going_up) && (is_tile_aligned)) || ((is_not_going_up) && (tile_change))) if (((going_down) && (is_tile_aligned)) || ((going_down) && (tile_change)))
{ {
bool test = false; bool onFloor = false;
test |= (room->getTile(getLeftFoot()) == TILE_SOLID); onFloor |= (room->getTile(getLeftFoot()) == TILE_SOLID);
test |= (room->getTile(getRightFoot()) == TILE_SOLID); onFloor |= (room->getTile(getRightFoot()) == TILE_SOLID);
test |= (room->getTile(getLeftFoot()) == TILE_TRAVESSABLE); onFloor |= (room->getTile(getLeftFoot()) == TILE_TRAVESSABLE);
test |= (room->getTile(getRightFoot()) == TILE_TRAVESSABLE); onFloor |= (room->getTile(getRightFoot()) == TILE_TRAVESSABLE);
// Tiene uno de los pies sobre una superficie // Tiene uno de los pies sobre una superficie
if (test) if (onFloor)
{ {
setStatus(STATUS_STANDING); setStatus(STATUS_STANDING);
// Si ha habido un cambio de tile, hay que recolocarlo // Si ha habido un cambio de tile recoloca al jugador
if (tile_change) if (tile_change)
{ {
const int offset = (int)y % 8; y = ((int)y - ((int)y % tileSize));
y = ((int)y - offset);
} }
} }
// Tiene ambos pies sobre el vacío // Tiene ambos pies sobre el vacío
else if (getStatus() != STATUS_JUMPING) else if (getStatus() != STATUS_JUMPING)
{ {
@@ -393,10 +372,10 @@ player_t Player::getSpawnParams()
{ {
player_t params; player_t params;
params.x = sprite->getPosX(); params.x = x;
params.y = sprite->getPosY(); params.y = y;
params.vx = sprite->getVelX(); params.vx = vx;
params.vy = sprite->getVelY(); params.vy = vy;
params.jump_ini = jump_ini; params.jump_ini = jump_ini;
params.status = status; params.status = status;
params.flip = sprite->getFlip(); params.flip = sprite->getFlip();
@@ -428,4 +407,16 @@ void Player::updateColliderPoints()
colliderPoints[5] = {rect.x + 7, rect.y + 8}; colliderPoints[5] = {rect.x + 7, rect.y + 8};
colliderPoints[6] = {rect.x + 7, rect.y + 15}; colliderPoints[6] = {rect.x + 7, rect.y + 15};
colliderPoints[7] = {rect.x, rect.y + 15}; colliderPoints[7] = {rect.x, rect.y + 15};
}
// Obtiene el valor de la variable
bool Player::getInvincible()
{
return invincible;
}
// Establece el valor de la variable
void Player::setInvincible(bool value)
{
invincible = value;
} }

View File

@@ -52,6 +52,7 @@ public:
std::vector<SDL_Point> colliderPoints; // Puntos de colisión con el mapa std::vector<SDL_Point> colliderPoints; // Puntos de colisión con el mapa
bool onBorder; // Indica si el jugador esta en uno de los cuatro bordes de la pantalla bool onBorder; // Indica si el jugador esta en uno de los cuatro bordes de la pantalla
int border; // Indica en cual de los cuatro bordes se encuentra int border; // Indica en cual de los cuatro bordes se encuentra
bool invincible; // Si es invencible, no puede morir
// Comprueba las entradas y modifica variables // Comprueba las entradas y modifica variables
void checkInput(); void checkInput();
@@ -65,14 +66,14 @@ public:
// Aplica gravedad al jugador // Aplica gravedad al jugador
void applyGravity(); void applyGravity();
// Guarda la posición actual en la variable lastPosition
void setLastPosition();
// Recalcula la posición del jugador y su animación // Recalcula la posición del jugador y su animación
void move(); void move();
// Comprueba si ha finalizado el salto // Establece la animación del jugador
void checkJump(); void animate();
// Comprueba si ha finalizado el salto al alcanzar la altura de inicio
void checkJumpEnd();
// Comprueba si el jugador esta sobre el suelo // Comprueba si el jugador esta sobre el suelo
void checkOnFloor(); void checkOnFloor();
@@ -122,18 +123,12 @@ public:
// Obtiene el estado del jugador // Obtiene el estado del jugador
int getStatus(); int getStatus();
// Obtiene la velocidad en el eje Y del jugador
float getVelY();
// Obtiene el rectangulo que delimita al jugador // Obtiene el rectangulo que delimita al jugador
SDL_Rect getRect(); SDL_Rect getRect();
// Obtiene el rectangulo de colision del jugador // Obtiene el rectangulo de colision del jugador
SDL_Rect &getCollider(); SDL_Rect &getCollider();
// Deshace el ultimo movimiento
void undoLastMove();
// Obtiene algunos parametros del jugador // Obtiene algunos parametros del jugador
player_t getSpawnParams(); player_t getSpawnParams();
@@ -142,6 +137,12 @@ public:
// Establece el valor de la variable // Establece el valor de la variable
void setRoom(Room *room); void setRoom(Room *room);
// Obtiene el valor de la variable
bool getInvincible();
// Establece el valor de la variable
void setInvincible(bool value);
}; };
#endif #endif

View File

@@ -566,4 +566,10 @@ void Room::reLoadTexture()
{ {
item->reLoadTexture(); item->reLoadTexture();
} }
}
// Obten el tamaño del tile
int Room::getTileSize()
{
return 8;
} }

View File

@@ -109,6 +109,9 @@ public:
// Recarga la textura // Recarga la textura
void reLoadTexture(); void reLoadTexture();
// Obten el tamaño del tile
int getTileSize();
}; };
#endif #endif