forked from jaildesigner-jailgames/jaildoctors_dilemma
Colisiones casi acabadas
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
const int a = (lastPosition.y + h) / tileSize;
|
||||
const int b = getLeftFoot().y / tileSize;
|
||||
const bool tile_change = a != b;
|
||||
|
||||
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)))
|
||||
{
|
||||
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);
|
||||
updateFeet();
|
||||
|
||||
// Si ha habido un cambio de tile recoloca al jugador
|
||||
if (tile_change)
|
||||
for (auto f : underFeet)
|
||||
{
|
||||
y = ((int)y - ((int)y % tileSize));
|
||||
}
|
||||
onFloor |= ((room->getTile(f) == TILE_SOLID) || (room->getTile(f) == TILE_TRAVESSABLE));
|
||||
}
|
||||
|
||||
// Tiene ambos pies sobre el vacío
|
||||
else if (getStatus() != STATUS_JUMPING)
|
||||
{
|
||||
setStatus(STATUS_FALLING);
|
||||
}
|
||||
}
|
||||
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()
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user