Colisiones casi acabadas

This commit is contained in:
2022-09-04 19:43:43 +02:00
parent 1351943c79
commit 796a31a099
3 changed files with 138 additions and 142 deletions

View File

@@ -6,7 +6,7 @@ Game::Game(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input)
// Inicia variables
clock = SDL_GetTicks();
currentRoom = "01.room";
spawnPoint = {2 * 8, 12 * 8, 0, 0, 0, STATUS_STANDING, SDL_FLIP_NONE};
spawnPoint = {2 * 8, 12 * 8, 0, 0, 0, s_standing, SDL_FLIP_NONE};
debug = true;
// Copia los punteros
@@ -222,22 +222,13 @@ void Game::renderDebugInfo()
const int inc = debugText->getCharacterWidth() + 1;
int line = 131;
text = std::to_string(player->getRect().x) + "," + std::to_string(player->getRect().y);
text = "X = " + std::to_string((int)player->x) + ", Y = " + std::to_string((int)player->y);
debugText->write(0, line += inc, text);
text = "status: " + std::to_string(player->status);
text = "VX = " + std::to_string(player->vx) + ", VY = " + std::to_string(player->vy);
debugText->write(0, line += inc, text);
text = "foot: " + std::to_string((int)player->getLeftFoot().y);
debugText->write(0, line += inc, text);
const int a = (player->lastPosition.y + 16) / 8;
const int b = player->getLeftFoot().y / 8;
text = "tile: " + std::to_string(a) + " - " + std::to_string(b);
debugText->write(0, line += inc, text);
const bool collision = checkPlayerAndEnemies();
text = "collision: " + std::to_string(collision);
text = "STATE = " + std::to_string(player->state);
debugText->write(0, line += inc, text);
}

View File

@@ -24,7 +24,7 @@ Player::Player(player_t ini, std::string tileset, std::string animation, SDL_Ren
invincible = false;
jump_ini = ini.jump_ini;
status = ini.status;
state = ini.state;
x = ini.x;
y = ini.y;
@@ -32,6 +32,7 @@ Player::Player(player_t ini, std::string tileset, std::string animation, SDL_Ren
vy = ini.vy;
w = 8;
h = 16;
maxVY = 1.2f;
sprite->setPosX(ini.x);
sprite->setPosY(ini.y);
@@ -44,6 +45,7 @@ Player::Player(player_t ini, std::string tileset, std::string animation, SDL_Ren
colliderBox = getRect();
const SDL_Point p = {0, 0};
colliderPoints.insert(colliderPoints.end(), {p, p, p, p, p, p, p, p});
underFeet.insert(underFeet.end(), {p, p});
}
// Destructor
@@ -74,24 +76,29 @@ void Player::update()
void Player::checkInput()
{
// Solo comprueba las entradas de dirección cuando está de pie
if ((input->checkInput(INPUT_LEFT, REPEAT_TRUE)) && (status == STATUS_STANDING))
if ((input->checkInput(INPUT_LEFT, REPEAT_TRUE)) && (state == s_standing))
{
vx = -0.6f;
sprite->setFlip(SDL_FLIP_HORIZONTAL);
}
else if ((input->checkInput(INPUT_RIGHT, REPEAT_TRUE)) && (status == STATUS_STANDING))
else if ((input->checkInput(INPUT_RIGHT, REPEAT_TRUE)) && (state == s_standing))
{
vx = 0.6f;
sprite->setFlip(SDL_FLIP_NONE);
}
else if (status == STATUS_STANDING)
else if (state == s_standing)
{
vx = 0.0f;
}
if (input->checkInput(INPUT_UP, REPEAT_TRUE))
{
setStatus(STATUS_JUMPING);
if (state == s_standing)
{
state = s_jumping;
vy = -maxVY;
jump_ini = y;
}
}
}
@@ -136,6 +143,21 @@ void Player::checkBorders()
}
}
// Comprueba el estado del jugador
void Player::checkState()
{
if (state == s_falling)
{
vx = 0.0f;
vy = maxVY;
}
else if (state == s_standing)
{
vy = 0.0f;
}
}
// Cambia al jugador de un borde al opuesto. Util para el cambio de pantalla
void Player::switchBorders()
{
@@ -160,60 +182,18 @@ void Player::switchBorders()
onBorder = false;
}
// Obtiene el valor del pixel inferior izquierdo del jugador
SDL_Point Player::getLeftFoot()
{
return {(int)x, (int)y + h};
}
// Obtiene el valor del pixel inferior derecho del jugador
SDL_Point Player::getRightFoot()
{
return {(int)x + 7, (int)y + h};
}
// Cambia el estado del jugador
void Player::setStatus(int value)
{
// Si quiere cambiar a saltando, ha de ser desde quieto
if ((value == STATUS_JUMPING) && (status == STATUS_STANDING))
{
status = STATUS_JUMPING;
vy = -MAX_VY;
jump_ini = y;
}
// Modifica el estado a 'cayendo'
if (value == STATUS_FALLING)
{
status = STATUS_FALLING;
vy = MAX_VY;
vx = 0.0f;
}
// Modifica el estado a 'de pie'
if (value == STATUS_STANDING)
{
status = STATUS_STANDING;
vy = 0.0f;
}
}
// Obtiene el estado del jugador
int Player::getStatus()
{
return status;
}
// Aplica gravedad al jugador
void Player::applyGravity()
{
if (status == STATUS_JUMPING)
const float gf = 0.035f;
// La gravedad solo se aplica cuando está saltando
if (state == s_jumping)
{
vy += GRAVITY;
if (vy > MAX_VY)
vy += gf;
if (vy > maxVY)
{
vy = MAX_VY;
vy = maxVY;
}
}
}
@@ -235,8 +215,9 @@ SDL_Rect &Player::getCollider()
void Player::move()
{
const int tileSize = room->getTileSize();
lastPosition = {(int)x, (int)y};
applyGravity();
lastPosition = {(int)x, (int)y}; // Guarda la posicion actual antes de modificarla
applyGravity(); // Aplica gravedad al jugador
checkState(); // Comprueba el estado del jugador
// Calcula la nueva posición del jugador y compensa en caso de colisión
x += vx;
@@ -253,8 +234,6 @@ void Player::move()
{
x = (int)x + tileSize - ((int)x % tileSize);
}
//vx = 0.0f;
}
y += vy;
@@ -263,20 +242,68 @@ void Player::move()
// Recoloca
if (vy > 0.0f)
{ // Bajando
// y -= ((int)y + h) % tileSize;
y -= 8;
setStatus(STATUS_STANDING);
y -= ((int)y + h) % tileSize;
state = s_standing;
}
else
{ // Subiendo
y += tileSize - ((int)y % tileSize);
setStatus(STATUS_FALLING);
state = s_falling;
}
}
else
// Si no colisiona con los muros, comprueba los tiles atravesables
// Si no colisiona con los muros, haz comprobaciones extra
{
checkOnFloor();
const int a = (lastPosition.y + h) / tileSize;
const int b = ((int)y + h) / tileSize;
const bool tile_change = a != b;
bool going_down = vy >= 0.0f;
bool tile_aligned = ((int)y + h) % tileSize == 0;
// Si está cayendo y hay cambio de tile o está justo sobre uno
if (going_down && (tile_aligned || tile_change))
{
// Comprueba si tiene uno de los pies sobre una superficie
if (isOnFloor())
{ // Y deja al jugador de pie
state = s_standing;
// Si ademas ha habido un cambio de tile recoloca al jugador
if (tile_change)
{
y = ((int)y - ((int)y % tileSize));
}
}
// Si tiene ambos pies sobre el vacío y no está saltando
else if (state != s_jumping)
{
state = s_falling;
}
}
going_down = vy >= 0.0f;
tile_aligned = ((int)y + h) % tileSize == 0;
// Si simplemente está cayendo (sin mirar si hay cambio de tile o si está justo sobre uno)
if (going_down)
{
if (state != s_jumping)
{
state = s_falling;
}
// Si está alineado con el tile mira el suelo (para que no lo mire si está
// dentro de un tile atravesable y lo deje a medias)
if (tile_aligned)
{
if (isOnFloor())
{
state = s_standing;
}
}
}
}
// Actualiza la posición del sprite
@@ -302,52 +329,27 @@ void Player::animate()
// Comprueba si ha finalizado el salto al alcanzar la altura de inicio
void Player::checkJumpEnd()
{
if (status == STATUS_JUMPING)
if (state == s_jumping)
if (vy > 0)
if (y >= jump_ini)
{
setStatus(STATUS_FALLING);
state = s_falling;
}
}
// Comprueba si el jugador esta sobre el suelo
void Player::checkOnFloor()
// Comprueba si el jugador tiene suelo debajo de los pies
bool Player::isOnFloor()
{
const int tileSize = room->getTileSize();
bool onFloor = false;
const int a = (lastPosition.y + h) / tileSize;
const int b = getLeftFoot().y / tileSize;
const bool tile_change = a != b;
updateFeet();
const bool going_down = vy >= 0.0f;
const bool is_tile_aligned = getLeftFoot().y % tileSize == 0;
if (((going_down) && (is_tile_aligned)) || ((going_down) && (tile_change)))
for (auto f : underFeet)
{
bool onFloor = false;
onFloor |= (room->getTile(getLeftFoot()) == TILE_SOLID);
onFloor |= (room->getTile(getRightFoot()) == TILE_SOLID);
onFloor |= (room->getTile(getLeftFoot()) == TILE_TRAVESSABLE);
onFloor |= (room->getTile(getRightFoot()) == TILE_TRAVESSABLE);
// Tiene uno de los pies sobre una superficie
if (onFloor)
{
setStatus(STATUS_STANDING);
// Si ha habido un cambio de tile recoloca al jugador
if (tile_change)
{
y = ((int)y - ((int)y % tileSize));
}
}
// Tiene ambos pies sobre el vacío
else if (getStatus() != STATUS_JUMPING)
{
setStatus(STATUS_FALLING);
}
onFloor |= ((room->getTile(f) == TILE_SOLID) || (room->getTile(f) == TILE_TRAVESSABLE));
}
return onFloor;
}
// Comprueba que el jugador no atraviese ninguna pared
@@ -377,7 +379,7 @@ player_t Player::getSpawnParams()
params.vx = vx;
params.vy = vy;
params.jump_ini = jump_ini;
params.status = status;
params.state = state;
params.flip = sprite->getFlip();
return params;
@@ -409,6 +411,15 @@ void Player::updateColliderPoints()
colliderPoints[7] = {rect.x, rect.y + 15};
}
// 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};
}
// Obtiene el valor de la variable
bool Player::getInvincible()
{

View File

@@ -13,13 +13,12 @@
#ifndef PLAYER_H
#define PLAYER_H
//#define VX 0.6
#define STATUS_STANDING 0
#define STATUS_JUMPING 1
#define STATUS_FALLING 2
#define GRAVITY 0.035f
#define MAX_VY 1.2f
enum state_e
{
s_standing,
s_jumping,
s_falling
};
struct player_t
{
@@ -28,7 +27,7 @@ struct player_t
float vx;
float vy;
int jump_ini;
int status;
state_e state;
SDL_RendererFlip flip;
};
@@ -42,17 +41,23 @@ public:
float vy; // Velocidad/desplazamiento del jugador en el eje Y
int w; // Ancho del jugador
int h; // ALto del jugador
LTexture *texture; // Textura con los graficos del enemigo
Input *input; // Objeto para gestionar la entrada
SDL_Renderer *renderer; // El renderizador de la ventana
Input *input; // Objeto para gestionar la entrada
Asset *asset; // Objeto con la ruta a todos los ficheros de recursos
Room *room; // Objeto encargado de gestionar cada habitación del juego
LTexture *texture; // Textura con los graficos del enemigo
AnimatedSprite *sprite; // Sprite del enemigo
color_t color; // Color del jugador
SDL_Rect colliderBox; // Caja de colisión con los enemigos u objetos
std::vector<SDL_Point> colliderPoints; // Puntos de colisión con el mapa
std::vector<SDL_Point> underFeet; // Contiene los puntos que hay bajo cada pie del jugador
state_e state; // Estado en el que se encuentra el jugador. Util apara saber si está saltando o cayendo
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
bool invincible; // Si es invencible, no puede morir
SDL_Rect lastPosition; // Contiene la ultima posición del jugador, por si hay que deshacer algun movimiento
int jump_ini; // Valor del eje Y en el que se inicia el salto
float maxVY; // Velocidad máxima que puede alcanzar al desplazarse en vertical
// Comprueba las entradas y modifica variables
void checkInput();
@@ -60,6 +65,9 @@ public:
// Comprueba si se halla en alguno de los cuatro bordes
void checkBorders();
// Comprueba el estado del jugador
void checkState();
// Asigna velocidad negativa en el eje Y al jugador
void jump();
@@ -75,27 +83,19 @@ public:
// Comprueba si ha finalizado el salto al alcanzar la altura de inicio
void checkJumpEnd();
// Comprueba si el jugador esta sobre el suelo
void checkOnFloor();
// Comprueba si el jugador tiene suelo debajo de los pies
bool isOnFloor();
// Comprueba que el jugador no atraviese ninguna pared
bool checkWalls();
// Obtiene el valor del pixel inferior izquierdo del jugador
SDL_Point getLeftFoot();
// Obtiene el valor del pixel inferior derecho del jugador
SDL_Point getRightFoot();
// Actualiza los puntos de colisión
void updateColliderPoints();
public:
AnimatedSprite *sprite; // Sprite del enemigo
SDL_Rect lastPosition; // Contiene la ultima posición del jugador, por si hay que deshacer algun movimiento
int jump_ini; // Valor del eje Y en el que se inicia el salto
int status; // Estado en el que se encuentra el jugador. Util apara saber si está saltando o cayendo
// Actualiza los puntos de los pies
void updateFeet();
public:
// Constructor
Player(player_t ini, std::string tileset, std::string animation, SDL_Renderer *renderer, Asset *asset, Input *input, Room *room);
@@ -117,12 +117,6 @@ public:
// Cambia al jugador de un borde al opuesto. Util para el cambio de pantalla
void switchBorders();
// Cambia el estado del jugador
void setStatus(int value);
// Obtiene el estado del jugador
int getStatus();
// Obtiene el rectangulo que delimita al jugador
SDL_Rect getRect();