diff --git a/source/game.cpp b/source/game.cpp index c6beb0a..d87d88d 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -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); } diff --git a/source/player.cpp b/source/player.cpp index 6f7dd87..2039930 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -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() { diff --git a/source/player.h b/source/player.h index 42095c3..2fd0269 100644 --- a/source/player.h +++ b/source/player.h @@ -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 colliderPoints; // Puntos de colisión con el mapa + std::vector 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();