forked from jaildesigner-jailgames/jaildoctors_dilemma
linter
This commit is contained in:
@@ -25,8 +25,8 @@ Enemy::Enemy(const EnemyData& enemy)
|
||||
sprite_->setWidth(enemy.w);
|
||||
sprite_->setHeight(enemy.h);
|
||||
|
||||
const SDL_FlipMode FLIP = (should_flip_ && enemy.vx < 0.0F) ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
|
||||
const SDL_FlipMode MIRROR = should_mirror_ ? SDL_FLIP_VERTICAL : SDL_FLIP_NONE;
|
||||
const int FLIP = (should_flip_ && enemy.vx < 0.0F) ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
|
||||
const int MIRROR = should_mirror_ ? SDL_FLIP_VERTICAL : SDL_FLIP_NONE;
|
||||
sprite_->setFlip(static_cast<SDL_FlipMode>(FLIP | MIRROR));
|
||||
|
||||
collider_ = getRect();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <algorithm> // Para max, min
|
||||
#include <cmath> // Para ceil, abs
|
||||
#include <ranges> // Para std::ranges::any_of
|
||||
|
||||
#include "core/input/input.hpp" // Para Input, InputAction
|
||||
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
|
||||
@@ -213,6 +214,167 @@ void Player::applyGravity() {
|
||||
}
|
||||
}
|
||||
|
||||
// Maneja el movimiento horizontal hacia la izquierda
|
||||
void Player::moveHorizontalLeft() {
|
||||
// Crea el rectangulo de proyección en el eje X para ver si colisiona
|
||||
SDL_FRect proj;
|
||||
proj.x = static_cast<int>(x_ + vx_);
|
||||
proj.y = static_cast<int>(y_);
|
||||
proj.h = HEIGHT;
|
||||
proj.w = static_cast<int>(std::ceil(std::fabs(vx_))); // Para evitar que tenga un ancho de 0 pixels
|
||||
|
||||
#ifdef _DEBUG
|
||||
debug_rect_x_ = proj;
|
||||
#endif
|
||||
|
||||
// Comprueba la colisión con las superficies
|
||||
const int POS = room_->checkRightSurfaces(&proj);
|
||||
|
||||
// Calcula la nueva posición
|
||||
if (POS == -1) {
|
||||
// Si no hay colisión
|
||||
x_ += vx_;
|
||||
} else {
|
||||
// Si hay colisión lo mueve hasta donde no colisiona
|
||||
x_ = POS + 1;
|
||||
}
|
||||
|
||||
// Si ha tocado alguna rampa mientras camina (sin saltar), asciende
|
||||
if (state_ != PlayerState::JUMPING) {
|
||||
const LineVertical LEFT_SIDE = {static_cast<int>(x_), static_cast<int>(y_) + static_cast<int>(HEIGHT) - 2, static_cast<int>(y_) + static_cast<int>(HEIGHT) - 1}; // Comprueba solo los dos pixels de abajo
|
||||
const int LY = room_->checkLeftSlopes(&LEFT_SIDE);
|
||||
if (LY > -1) {
|
||||
y_ = LY - HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
// Si está bajando la rampa, recoloca al jugador
|
||||
if (isOnDownSlope() && state_ != PlayerState::JUMPING) {
|
||||
y_ += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Maneja el movimiento horizontal hacia la derecha
|
||||
void Player::moveHorizontalRight() {
|
||||
// Crea el rectangulo de proyección en el eje X para ver si colisiona
|
||||
SDL_FRect proj;
|
||||
proj.x = x_ + WIDTH;
|
||||
proj.y = y_;
|
||||
proj.h = HEIGHT;
|
||||
proj.w = ceil(vx_); // Para evitar que tenga un ancho de 0 pixels
|
||||
|
||||
#ifdef _DEBUG
|
||||
debug_rect_x_ = proj;
|
||||
#endif
|
||||
|
||||
// Comprueba la colisión
|
||||
const int POS = room_->checkLeftSurfaces(&proj);
|
||||
|
||||
// Calcula la nueva posición
|
||||
if (POS == -1) {
|
||||
// Si no hay colisión
|
||||
x_ += vx_;
|
||||
} else {
|
||||
// Si hay colisión lo mueve hasta donde no colisiona
|
||||
x_ = POS - WIDTH;
|
||||
}
|
||||
|
||||
// Si ha tocado alguna rampa mientras camina (sin saltar), asciende
|
||||
if (state_ != PlayerState::JUMPING) {
|
||||
const LineVertical RIGHT_SIDE = {static_cast<int>(x_) + static_cast<int>(WIDTH) - 1, static_cast<int>(y_) + static_cast<int>(HEIGHT) - 2, static_cast<int>(y_) + static_cast<int>(HEIGHT) - 1}; // Comprueba solo los dos pixels de abajo
|
||||
const int RY = room_->checkRightSlopes(&RIGHT_SIDE);
|
||||
if (RY > -1) {
|
||||
y_ = RY - HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
// Si está bajando la rampa, recoloca al jugador
|
||||
if (isOnDownSlope() && state_ != PlayerState::JUMPING) {
|
||||
y_ += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Maneja el movimiento vertical hacia arriba
|
||||
void Player::moveVerticalUp() {
|
||||
// Crea el rectangulo de proyección en el eje Y para ver si colisiona
|
||||
SDL_FRect proj;
|
||||
proj.x = static_cast<int>(x_);
|
||||
proj.y = static_cast<int>(y_ + vy_);
|
||||
proj.h = static_cast<int>(std::ceil(std::fabs(vy_))); // Para evitar que tenga una altura de 0 pixels
|
||||
proj.w = WIDTH;
|
||||
|
||||
#ifdef _DEBUG
|
||||
debug_rect_y_ = proj;
|
||||
#endif
|
||||
|
||||
// Comprueba la colisión
|
||||
const int POS = room_->checkBottomSurfaces(&proj);
|
||||
|
||||
// Calcula la nueva posición
|
||||
if (POS == -1) {
|
||||
// Si no hay colisión
|
||||
y_ += vy_;
|
||||
} else {
|
||||
// Si hay colisión lo mueve hasta donde no colisiona y entra en caída
|
||||
y_ = POS + 1;
|
||||
setState(PlayerState::FALLING);
|
||||
}
|
||||
}
|
||||
|
||||
// Maneja el movimiento vertical hacia abajo
|
||||
void Player::moveVerticalDown() {
|
||||
// Crea el rectangulo de proyección en el eje Y para ver si colisiona
|
||||
SDL_FRect proj;
|
||||
proj.x = x_;
|
||||
proj.y = y_ + HEIGHT;
|
||||
proj.h = ceil(vy_); // Para evitar que tenga una altura de 0 pixels
|
||||
proj.w = WIDTH;
|
||||
|
||||
#ifdef _DEBUG
|
||||
debug_rect_y_ = proj;
|
||||
#endif
|
||||
|
||||
// Comprueba la colisión con las superficies normales y las automáticas
|
||||
const float POS = std::max(room_->checkTopSurfaces(&proj), room_->checkAutoSurfaces(&proj));
|
||||
if (POS > -1) {
|
||||
// Si hay colisión lo mueve hasta donde no colisiona y pasa a estar sobre la superficie
|
||||
y_ = POS - HEIGHT;
|
||||
setState(PlayerState::STANDING);
|
||||
|
||||
// Deja de estar enganchado a la superficie automatica
|
||||
auto_movement_ = false;
|
||||
} else {
|
||||
// Si no hay colisión con los muros, comprueba la colisión con las rampas
|
||||
if (state_ != PlayerState::JUMPING) { // Las rampas no se miran si se está saltando
|
||||
auto rect = toSDLRect(proj);
|
||||
const LineVertical LEFT_SIDE = {rect.x, rect.y, rect.y + rect.h - 1};
|
||||
const LineVertical RIGHT_SIDE = {rect.x + rect.w - 1, rect.y, rect.y + rect.h - 1};
|
||||
const float POINT = std::max(room_->checkRightSlopes(&RIGHT_SIDE), room_->checkLeftSlopes(&LEFT_SIDE));
|
||||
if (POINT > -1) {
|
||||
// No está saltando y hay colisión con una rampa
|
||||
// Calcula la nueva posición
|
||||
y_ = POINT - HEIGHT;
|
||||
setState(PlayerState::STANDING);
|
||||
#ifdef _DEBUG
|
||||
debug_color_ = static_cast<Uint8>(PaletteColor::YELLOW);
|
||||
debug_point_ = {x_ + (WIDTH / 2), POINT};
|
||||
#endif
|
||||
} else {
|
||||
// No está saltando y no hay colisón con una rampa
|
||||
// Calcula la nueva posición
|
||||
y_ += vy_;
|
||||
#ifdef _DEBUG
|
||||
debug_color_ = static_cast<Uint8>(PaletteColor::RED);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
// Esta saltando y no hay colisión con los muros
|
||||
// Calcula la nueva posición
|
||||
y_ += vy_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recalcula la posición del jugador y su animación
|
||||
void Player::move() {
|
||||
last_position_ = {x_, y_}; // Guarda la posicion actual antes de modificarla
|
||||
@@ -223,179 +385,29 @@ void Player::move() {
|
||||
debug_color_ = static_cast<Uint8>(PaletteColor::GREEN);
|
||||
#endif
|
||||
|
||||
// Se mueve hacia la izquierda
|
||||
// Movimiento horizontal
|
||||
if (vx_ < 0.0F) {
|
||||
// Crea el rectangulo de proyección en el eje X para ver si colisiona
|
||||
SDL_FRect proj;
|
||||
proj.x = static_cast<int>(x_ + vx_);
|
||||
proj.y = static_cast<int>(y_);
|
||||
proj.h = HEIGHT;
|
||||
proj.w = static_cast<int>(std::ceil(std::fabs(vx_))); // Para evitar que tenga un ancho de 0 pixels
|
||||
|
||||
#ifdef _DEBUG
|
||||
debug_rect_x_ = proj;
|
||||
#endif
|
||||
|
||||
// Comprueba la colisión con las superficies
|
||||
const int POS = room_->checkRightSurfaces(&proj);
|
||||
|
||||
// Calcula la nueva posición
|
||||
if (POS == -1) {
|
||||
// Si no hay colisión
|
||||
x_ += vx_;
|
||||
} else {
|
||||
// Si hay colisión lo mueve hasta donde no colisiona
|
||||
x_ = POS + 1;
|
||||
}
|
||||
|
||||
// Si ha tocado alguna rampa mientras camina (sin saltar), asciende
|
||||
if (state_ != PlayerState::JUMPING) {
|
||||
const LineVertical LEFT_SIDE = {static_cast<int>(x_), static_cast<int>(y_) + static_cast<int>(HEIGHT) - 2, static_cast<int>(y_) + static_cast<int>(HEIGHT) - 1}; // Comprueba solo los dos pixels de abajo
|
||||
const int LY = room_->checkLeftSlopes(&LEFT_SIDE);
|
||||
if (LY > -1) {
|
||||
y_ = LY - HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
// Si está bajando la rampa, recoloca al jugador
|
||||
if (isOnDownSlope() && state_ != PlayerState::JUMPING) {
|
||||
y_ += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Se mueve hacia la derecha
|
||||
else if (vx_ > 0.0F) {
|
||||
// Crea el rectangulo de proyección en el eje X para ver si colisiona
|
||||
SDL_FRect proj;
|
||||
proj.x = x_ + WIDTH;
|
||||
proj.y = y_;
|
||||
proj.h = HEIGHT;
|
||||
proj.w = ceil(vx_); // Para evitar que tenga un ancho de 0 pixels
|
||||
|
||||
#ifdef _DEBUG
|
||||
debug_rect_x_ = proj;
|
||||
#endif
|
||||
|
||||
// Comprueba la colisión
|
||||
const int POS = room_->checkLeftSurfaces(&proj);
|
||||
|
||||
// Calcula la nueva posición
|
||||
if (POS == -1) {
|
||||
// Si no hay colisión
|
||||
x_ += vx_;
|
||||
} else {
|
||||
// Si hay colisión lo mueve hasta donde no colisiona
|
||||
x_ = POS - WIDTH;
|
||||
}
|
||||
|
||||
// Si ha tocado alguna rampa mientras camina (sin saltar), asciende
|
||||
if (state_ != PlayerState::JUMPING) {
|
||||
const LineVertical RIGHT_SIDE = {static_cast<int>(x_) + static_cast<int>(WIDTH) - 1, static_cast<int>(y_) + static_cast<int>(HEIGHT) - 2, static_cast<int>(y_) + static_cast<int>(HEIGHT) - 1}; // Comprueba solo los dos pixels de abajo
|
||||
const int RY = room_->checkRightSlopes(&RIGHT_SIDE);
|
||||
if (RY > -1) {
|
||||
y_ = RY - HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
// Si está bajando la rampa, recoloca al jugador
|
||||
if (isOnDownSlope() && state_ != PlayerState::JUMPING) {
|
||||
y_ += 1;
|
||||
}
|
||||
moveHorizontalLeft();
|
||||
} else if (vx_ > 0.0F) {
|
||||
moveHorizontalRight();
|
||||
}
|
||||
|
||||
// Si ha salido del suelo, el jugador cae
|
||||
if (state_ == PlayerState::STANDING && !isOnFloor()) {
|
||||
setState(PlayerState::FALLING);
|
||||
|
||||
// Deja de estar enganchado a la superficie automatica
|
||||
auto_movement_ = false;
|
||||
}
|
||||
|
||||
// Si ha salido de una superficie automatica, detiene el movimiento automatico
|
||||
if (state_ == PlayerState::STANDING && isOnFloor() && !isOnAutoSurface()) {
|
||||
// Deja de estar enganchado a la superficie automatica
|
||||
auto_movement_ = false;
|
||||
}
|
||||
|
||||
// Se mueve hacia arriba
|
||||
// Movimiento vertical
|
||||
if (vy_ < 0.0F) {
|
||||
// Crea el rectangulo de proyección en el eje Y para ver si colisiona
|
||||
SDL_FRect proj;
|
||||
proj.x = static_cast<int>(x_);
|
||||
proj.y = static_cast<int>(y_ + vy_);
|
||||
proj.h = static_cast<int>(std::ceil(std::fabs(vy_))); // Para evitar que tenga una altura de 0 pixels
|
||||
proj.w = WIDTH;
|
||||
|
||||
#ifdef _DEBUG
|
||||
debug_rect_y_ = proj;
|
||||
#endif
|
||||
|
||||
// Comprueba la colisión
|
||||
const int POS = room_->checkBottomSurfaces(&proj);
|
||||
|
||||
// Calcula la nueva posición
|
||||
if (POS == -1) {
|
||||
// Si no hay colisión
|
||||
y_ += vy_;
|
||||
} else {
|
||||
// Si hay colisión lo mueve hasta donde no colisiona y entra en caída
|
||||
y_ = POS + 1;
|
||||
setState(PlayerState::FALLING);
|
||||
}
|
||||
}
|
||||
|
||||
// Se mueve hacia abajo
|
||||
else if (vy_ > 0.0F) {
|
||||
// Crea el rectangulo de proyección en el eje Y para ver si colisiona
|
||||
SDL_FRect proj;
|
||||
proj.x = x_;
|
||||
proj.y = y_ + HEIGHT;
|
||||
proj.h = ceil(vy_); // Para evitar que tenga una altura de 0 pixels
|
||||
proj.w = WIDTH;
|
||||
|
||||
#ifdef _DEBUG
|
||||
debug_rect_y_ = proj;
|
||||
#endif
|
||||
|
||||
// Comprueba la colisión con las superficies normales y las automáticas
|
||||
const float POS = std::max(room_->checkTopSurfaces(&proj), room_->checkAutoSurfaces(&proj));
|
||||
if (POS > -1) {
|
||||
// Si hay colisión lo mueve hasta donde no colisiona y pasa a estar sobre la superficie
|
||||
y_ = POS - HEIGHT;
|
||||
setState(PlayerState::STANDING);
|
||||
|
||||
// Deja de estar enganchado a la superficie automatica
|
||||
auto_movement_ = false;
|
||||
} else {
|
||||
// Si no hay colisión con los muros, comprueba la colisión con las rampas
|
||||
if (state_ != PlayerState::JUMPING) { // Las rampas no se miran si se está saltando
|
||||
auto rect = toSDLRect(proj);
|
||||
const LineVertical LEFT_SIDE = {rect.x, rect.y, rect.y + rect.h - 1};
|
||||
const LineVertical RIGHT_SIDE = {rect.x + rect.w - 1, rect.y, rect.y + rect.h - 1};
|
||||
const float POINT = std::max(room_->checkRightSlopes(&RIGHT_SIDE), room_->checkLeftSlopes(&LEFT_SIDE));
|
||||
if (POINT > -1) {
|
||||
// No está saltando y hay colisión con una rampa
|
||||
// Calcula la nueva posición
|
||||
y_ = POINT - HEIGHT;
|
||||
setState(PlayerState::STANDING);
|
||||
#ifdef _DEBUG
|
||||
debug_color_ = static_cast<Uint8>(PaletteColor::YELLOW);
|
||||
debug_point_ = {x_ + (WIDTH / 2), POINT};
|
||||
#endif
|
||||
} else {
|
||||
// No está saltando y no hay colisón con una rampa
|
||||
// Calcula la nueva posición
|
||||
y_ += vy_;
|
||||
#ifdef _DEBUG
|
||||
debug_color_ = static_cast<Uint8>(PaletteColor::RED);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
// Esta saltando y no hay colisión con los muros
|
||||
// Calcula la nueva posición
|
||||
y_ += vy_;
|
||||
}
|
||||
}
|
||||
moveVerticalUp();
|
||||
} else if (vy_ > 0.0F) {
|
||||
moveVerticalDown();
|
||||
}
|
||||
|
||||
placeSprite(); // Coloca el sprite en la nueva posición
|
||||
@@ -534,12 +546,12 @@ bool Player::checkKillingTiles() {
|
||||
// Actualiza los puntos de colisión
|
||||
updateColliderPoints();
|
||||
|
||||
// Comprueba si hay contacto y retorna en cuanto se encuentra colisión
|
||||
for (const auto& c : collider_points_) {
|
||||
if (room_->getTile(c) == TileType::KILL) {
|
||||
is_alive_ = false; // Mata al jugador inmediatamente
|
||||
return true; // Retorna en cuanto se detecta una colisión
|
||||
}
|
||||
// Comprueba si hay contacto con algún tile que mata
|
||||
if (std::ranges::any_of(collider_points_, [this](const auto& c) {
|
||||
return room_->getTile(c) == TileType::KILL;
|
||||
})) {
|
||||
is_alive_ = false; // Mata al jugador inmediatamente
|
||||
return true; // Retorna en cuanto se detecta una colisión
|
||||
}
|
||||
|
||||
return false; // No se encontró ninguna colisión
|
||||
|
||||
@@ -120,6 +120,18 @@ class Player {
|
||||
// Recalcula la posición del jugador y su animación
|
||||
void move();
|
||||
|
||||
// Maneja el movimiento horizontal hacia la izquierda
|
||||
void moveHorizontalLeft();
|
||||
|
||||
// Maneja el movimiento horizontal hacia la derecha
|
||||
void moveHorizontalRight();
|
||||
|
||||
// Maneja el movimiento vertical hacia arriba
|
||||
void moveVerticalUp();
|
||||
|
||||
// Maneja el movimiento vertical hacia abajo
|
||||
void moveVerticalDown();
|
||||
|
||||
// Establece la animación del jugador
|
||||
void animate();
|
||||
|
||||
@@ -163,7 +175,7 @@ class Player {
|
||||
void applySpawnValues(const PlayerSpawn& spawn);
|
||||
|
||||
// Inicializa el sprite del jugador
|
||||
void initSprite(const std::string& texture_path, const std::string& animations_path);
|
||||
void initSprite(const std::string& surface_path, const std::string& animations_path);
|
||||
|
||||
#ifdef _DEBUG
|
||||
// Pinta la información de debug del jugador
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "game/gameplay/room.hpp"
|
||||
|
||||
#include <algorithm> // Para std::ranges::any_of
|
||||
#include <exception> // Para exception
|
||||
#include <fstream> // Para basic_ostream, operator<<, basic_istream
|
||||
#include <iostream> // Para cout, cerr
|
||||
@@ -60,6 +61,61 @@ std::vector<int> loadRoomTileFile(const std::string& file_path, bool verbose) {
|
||||
return tile_map_file;
|
||||
}
|
||||
|
||||
// Parsea una línea en key y value separados por '='
|
||||
std::pair<std::string, std::string> parseKeyValue(const std::string& line) {
|
||||
int pos = line.find("=");
|
||||
std::string key = line.substr(0, pos);
|
||||
std::string value = line.substr(pos + 1, line.length());
|
||||
return {key, value};
|
||||
}
|
||||
|
||||
// Muestra un warning de parámetro desconocido
|
||||
void logUnknownParameter(const std::string& file_name, const std::string& key, bool verbose) {
|
||||
if (verbose) {
|
||||
std::cout << "Warning: file " << file_name.c_str() << "\n, unknown parameter \"" << key.c_str() << "\"" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Carga un bloque [enemy]...[/enemy] desde un archivo
|
||||
EnemyData loadEnemyFromFile(std::ifstream& file, const std::string& file_name, bool verbose) {
|
||||
EnemyData enemy;
|
||||
enemy.flip = false;
|
||||
enemy.mirror = false;
|
||||
enemy.frame = -1;
|
||||
|
||||
std::string line;
|
||||
do {
|
||||
std::getline(file, line);
|
||||
auto [key, value] = parseKeyValue(line);
|
||||
|
||||
if (!setEnemy(&enemy, key, value)) {
|
||||
logUnknownParameter(file_name, key, verbose);
|
||||
}
|
||||
} while (line != "[/enemy]");
|
||||
|
||||
return enemy;
|
||||
}
|
||||
|
||||
// Carga un bloque [item]...[/item] desde un archivo
|
||||
ItemData loadItemFromFile(std::ifstream& file, const std::string& file_name, bool verbose) {
|
||||
ItemData item;
|
||||
item.counter = 0;
|
||||
item.color1 = stringToColor("yellow");
|
||||
item.color2 = stringToColor("magenta");
|
||||
|
||||
std::string line;
|
||||
do {
|
||||
std::getline(file, line);
|
||||
auto [key, value] = parseKeyValue(line);
|
||||
|
||||
if (!setItem(&item, key, value)) {
|
||||
logUnknownParameter(file_name, key, verbose);
|
||||
}
|
||||
} while (line != "[/item]");
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
// Carga las variables desde un fichero de mapa
|
||||
RoomData loadRoomFile(const std::string& file_path, bool verbose) {
|
||||
RoomData room;
|
||||
@@ -79,70 +135,17 @@ RoomData loadRoomFile(const std::string& file_path, bool verbose) {
|
||||
while (std::getline(file, line)) {
|
||||
// Si la linea contiene el texto [enemy] se realiza el proceso de carga de un enemigo
|
||||
if (line == "[enemy]") {
|
||||
EnemyData enemy;
|
||||
enemy.flip = false;
|
||||
enemy.mirror = false;
|
||||
enemy.frame = -1;
|
||||
|
||||
do {
|
||||
std::getline(file, line);
|
||||
|
||||
// Encuentra la posición del caracter '='
|
||||
int pos = line.find("=");
|
||||
|
||||
// Procesa las dos subcadenas
|
||||
std::string key = line.substr(0, pos);
|
||||
std::string value = line.substr(pos + 1, line.length());
|
||||
if (!setEnemy(&enemy, key, value)) {
|
||||
if (verbose) {
|
||||
std::cout << "Warning: file " << FILE_NAME.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
|
||||
}
|
||||
}
|
||||
} while (line != "[/enemy]");
|
||||
|
||||
// Añade el enemigo al vector de enemigos
|
||||
room.enemies.push_back(enemy);
|
||||
room.enemies.push_back(loadEnemyFromFile(file, FILE_NAME, verbose));
|
||||
}
|
||||
|
||||
// Si la linea contiene el texto [item] se realiza el proceso de carga de un item
|
||||
else if (line == "[item]") {
|
||||
ItemData item;
|
||||
item.counter = 0;
|
||||
item.color1 = stringToColor("yellow");
|
||||
item.color2 = stringToColor("magenta");
|
||||
|
||||
do {
|
||||
std::getline(file, line);
|
||||
|
||||
// Encuentra la posición del caracter '='
|
||||
int pos = line.find("=");
|
||||
|
||||
// Procesa las dos subcadenas
|
||||
std::string key = line.substr(0, pos);
|
||||
std::string value = line.substr(pos + 1, line.length());
|
||||
if (!setItem(&item, key, value)) {
|
||||
if (verbose) {
|
||||
std::cout << "Warning: file " << FILE_NAME.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
} while (line != "[/item]");
|
||||
|
||||
room.items.push_back(item);
|
||||
room.items.push_back(loadItemFromFile(file, FILE_NAME, verbose));
|
||||
}
|
||||
|
||||
// En caso contrario se parsea el fichero para buscar las variables y los valores
|
||||
else {
|
||||
// Encuentra la posición del caracter '='
|
||||
int pos = line.find("=");
|
||||
|
||||
// Procesa las dos subcadenas
|
||||
std::string key = line.substr(0, pos);
|
||||
std::string value = line.substr(pos + 1, line.length());
|
||||
auto [key, value] = parseKeyValue(line);
|
||||
if (!setRoom(&room, key, value)) {
|
||||
if (verbose) {
|
||||
std::cout << "Warning: file " << FILE_NAME.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
|
||||
}
|
||||
logUnknownParameter(FILE_NAME, key, verbose);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,9 +158,7 @@ RoomData loadRoomFile(const std::string& file_path, bool verbose) {
|
||||
}
|
||||
// El fichero no se puede abrir
|
||||
else {
|
||||
{
|
||||
std::cout << "Warning: Unable to open " << FILE_NAME.c_str() << " file" << std::endl;
|
||||
}
|
||||
std::cout << "Warning: Unable to open " << FILE_NAME.c_str() << " file" << std::endl;
|
||||
}
|
||||
|
||||
return room;
|
||||
@@ -555,7 +556,7 @@ TileType Room::getTile(int index) {
|
||||
}
|
||||
|
||||
// La fila 23 es de tiles t_kill
|
||||
else if ((tile_map_[index] >= 23 * tile_set_width_) && (tile_map_[index] < 24 * tile_set_width_)) {
|
||||
if ((tile_map_[index] >= 23 * tile_set_width_) && (tile_map_[index] < 24 * tile_set_width_)) {
|
||||
return TileType::KILL;
|
||||
}
|
||||
}
|
||||
@@ -565,12 +566,9 @@ TileType Room::getTile(int index) {
|
||||
|
||||
// Indica si hay colision con un enemigo a partir de un rectangulo
|
||||
bool Room::enemyCollision(SDL_FRect& rect) {
|
||||
for (const auto& enemy : enemies_) {
|
||||
if (checkCollision(rect, enemy->getCollider())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return std::ranges::any_of(enemies_, [&rect](const auto& enemy) {
|
||||
return checkCollision(rect, enemy->getCollider());
|
||||
});
|
||||
}
|
||||
|
||||
// Indica si hay colision con un objeto a partir de un rectangulo
|
||||
@@ -619,8 +617,8 @@ int Room::getSlopeHeight(SDL_FPoint p, TileType slope) {
|
||||
return base;
|
||||
}
|
||||
|
||||
// Calcula las superficies inferiores
|
||||
void Room::setBottomSurfaces() {
|
||||
// Helper: recopila tiles inferiores (muros sin muro debajo)
|
||||
std::vector<int> Room::collectBottomTiles() {
|
||||
std::vector<int> tile;
|
||||
|
||||
// Busca todos los tiles de tipo muro que no tengan debajo otro muro
|
||||
@@ -638,40 +636,11 @@ void Room::setBottomSurfaces() {
|
||||
|
||||
// Añade un terminador
|
||||
tile.push_back(-1);
|
||||
|
||||
// Recorre el vector de tiles buscando tiles consecutivos para localizar las superficies
|
||||
if ((int)tile.size() > 1) {
|
||||
int i = 0;
|
||||
do {
|
||||
LineHorizontal line;
|
||||
line.x1 = (tile[i] % MAP_WIDTH) * TILE_SIZE;
|
||||
line.y = ((tile[i] / MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
|
||||
int last_one = i;
|
||||
i++;
|
||||
|
||||
if (i <= (int)tile.size() - 1) {
|
||||
while (tile[i] == tile[i - 1] + 1) {
|
||||
last_one = i;
|
||||
if (i == (int)tile.size() - 1) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
line.x2 = ((tile[last_one] % MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
|
||||
bottom_floors_.push_back(line);
|
||||
if (i <= (int)tile.size() - 1) {
|
||||
if (tile[i] == -1) { // Si el siguiente elemento es un separador, hay que saltarlo
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} while (i < (int)tile.size() - 1);
|
||||
}
|
||||
return tile;
|
||||
}
|
||||
|
||||
// Calcula las superficies superiores
|
||||
void Room::setTopSurfaces() {
|
||||
// Helper: recopila tiles superiores (muros o pasables sin muro encima)
|
||||
std::vector<int> Room::collectTopTiles() {
|
||||
std::vector<int> tile;
|
||||
|
||||
// Busca todos los tiles de tipo muro o pasable que no tengan encima un muro
|
||||
@@ -689,36 +658,61 @@ void Room::setTopSurfaces() {
|
||||
|
||||
// Añade un terminador
|
||||
tile.push_back(-1);
|
||||
return tile;
|
||||
}
|
||||
|
||||
// Recorre el vector de tiles buscando tiles consecutivos para localizar las superficies
|
||||
if ((int)tile.size() > 1) {
|
||||
int i = 0;
|
||||
do {
|
||||
LineHorizontal line;
|
||||
line.x1 = (tile[i] % MAP_WIDTH) * TILE_SIZE;
|
||||
line.y = (tile[i] / MAP_WIDTH) * TILE_SIZE;
|
||||
int last_one = i;
|
||||
i++;
|
||||
|
||||
if (i <= (int)tile.size() - 1) {
|
||||
while (tile[i] == tile[i - 1] + 1) {
|
||||
last_one = i;
|
||||
if (i == (int)tile.size() - 1) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
line.x2 = ((tile[last_one] % MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
|
||||
top_floors_.push_back(line);
|
||||
if (i <= (int)tile.size() - 1) {
|
||||
if (tile[i] == -1) { // Si el siguiente elemento es un separador, hay que saltarlo
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} while (i < (int)tile.size() - 1);
|
||||
// Helper: construye lineas horizontales a partir de tiles consecutivos
|
||||
void Room::buildHorizontalLines(const std::vector<int>& tiles, std::vector<LineHorizontal>& lines, bool is_bottom_surface) {
|
||||
if (tiles.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while (i < (int)tiles.size() - 1) {
|
||||
LineHorizontal line;
|
||||
line.x1 = (tiles[i] % MAP_WIDTH) * TILE_SIZE;
|
||||
|
||||
// Calcula Y segun si es superficie inferior o superior
|
||||
if (is_bottom_surface) {
|
||||
line.y = ((tiles[i] / MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
|
||||
} else {
|
||||
line.y = (tiles[i] / MAP_WIDTH) * TILE_SIZE;
|
||||
}
|
||||
|
||||
int last_one = i;
|
||||
i++;
|
||||
|
||||
// Encuentra tiles consecutivos
|
||||
if (i < (int)tiles.size()) {
|
||||
while (tiles[i] == tiles[i - 1] + 1) {
|
||||
last_one = i;
|
||||
i++;
|
||||
if (i >= (int)tiles.size()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
line.x2 = ((tiles[last_one] % MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
|
||||
lines.push_back(line);
|
||||
|
||||
// Salta separadores
|
||||
if (i < (int)tiles.size() && tiles[i] == -1) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calcula las superficies inferiores
|
||||
void Room::setBottomSurfaces() {
|
||||
std::vector<int> tile = collectBottomTiles();
|
||||
buildHorizontalLines(tile, bottom_floors_, true);
|
||||
}
|
||||
|
||||
// Calcula las superficies superiores
|
||||
void Room::setTopSurfaces() {
|
||||
std::vector<int> tile = collectTopTiles();
|
||||
buildHorizontalLines(tile, top_floors_, false);
|
||||
}
|
||||
|
||||
// Calcula las superficies laterales izquierdas
|
||||
@@ -872,7 +866,8 @@ void Room::setRightSlopes() {
|
||||
}
|
||||
|
||||
// Calcula las superficies automaticas
|
||||
void Room::setAutoSurfaces() {
|
||||
// Helper: recopila tiles animados (para superficies automaticas/conveyor belts)
|
||||
std::vector<int> Room::collectAnimatedTiles() {
|
||||
std::vector<int> tile;
|
||||
|
||||
// Busca todos los tiles de tipo animado
|
||||
@@ -888,35 +883,17 @@ void Room::setAutoSurfaces() {
|
||||
}
|
||||
}
|
||||
|
||||
// Recorre el vector de tiles buscando tiles consecutivos para localizar las superficies
|
||||
if ((int)tile.size() > 0) {
|
||||
int i = 0;
|
||||
do {
|
||||
LineHorizontal line;
|
||||
line.x1 = (tile[i] % MAP_WIDTH) * TILE_SIZE;
|
||||
line.y = (tile[i] / MAP_WIDTH) * TILE_SIZE;
|
||||
int last_one = i;
|
||||
i++;
|
||||
|
||||
if (i <= (int)tile.size() - 1) {
|
||||
while (tile[i] == tile[i - 1] + 1) {
|
||||
last_one = i;
|
||||
if (i == (int)tile.size() - 1) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
line.x2 = ((tile[last_one] % MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
|
||||
conveyor_belt_floors_.push_back(line);
|
||||
if (i <= (int)tile.size() - 1) {
|
||||
if (tile[i] == -1) { // Si el siguiente elemento es un separador, hay que saltarlo
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} while (i < (int)tile.size() - 1);
|
||||
// Añade un terminador si hay tiles
|
||||
if (!tile.empty()) {
|
||||
tile.push_back(-1);
|
||||
}
|
||||
|
||||
return tile;
|
||||
}
|
||||
|
||||
void Room::setAutoSurfaces() {
|
||||
std::vector<int> tile = collectAnimatedTiles();
|
||||
buildHorizontalLines(tile, conveyor_belt_floors_, false);
|
||||
}
|
||||
|
||||
// Localiza todos los tiles animados de la habitación
|
||||
@@ -1022,24 +999,16 @@ int Room::checkAutoSurfaces(SDL_FRect* rect) {
|
||||
|
||||
// Comprueba las colisiones
|
||||
bool Room::checkTopSurfaces(SDL_FPoint* p) {
|
||||
for (const auto& s : top_floors_) {
|
||||
if (checkCollision(s, *p)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return std::ranges::any_of(top_floors_, [&](const auto& s) {
|
||||
return checkCollision(s, *p);
|
||||
});
|
||||
}
|
||||
|
||||
// Comprueba las colisiones
|
||||
bool Room::checkAutoSurfaces(SDL_FPoint* p) {
|
||||
for (const auto& s : conveyor_belt_floors_) {
|
||||
if (checkCollision(s, *p)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return std::ranges::any_of(conveyor_belt_floors_, [&](const auto& s) {
|
||||
return checkCollision(s, *p);
|
||||
});
|
||||
}
|
||||
|
||||
// Comprueba las colisiones
|
||||
@@ -1056,13 +1025,9 @@ int Room::checkLeftSlopes(const LineVertical* line) {
|
||||
|
||||
// Comprueba las colisiones
|
||||
bool Room::checkLeftSlopes(SDL_FPoint* p) {
|
||||
for (const auto& slope : left_slopes_) {
|
||||
if (checkCollision(*p, slope)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return std::ranges::any_of(left_slopes_, [&](const auto& slope) {
|
||||
return checkCollision(*p, slope);
|
||||
});
|
||||
}
|
||||
|
||||
// Comprueba las colisiones
|
||||
@@ -1079,13 +1044,9 @@ int Room::checkRightSlopes(const LineVertical* line) {
|
||||
|
||||
// Comprueba las colisiones
|
||||
bool Room::checkRightSlopes(SDL_FPoint* p) {
|
||||
for (const auto& slope : right_slopes_) {
|
||||
if (checkCollision(*p, slope)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return std::ranges::any_of(right_slopes_, [&](const auto& slope) {
|
||||
return checkCollision(*p, slope);
|
||||
});
|
||||
}
|
||||
|
||||
// Abre la Jail si se da el caso
|
||||
|
||||
@@ -115,6 +115,18 @@ class Room {
|
||||
// Pinta el mapa de la habitación en la textura
|
||||
void fillMapTexture();
|
||||
|
||||
// Helper para recopilar tiles inferiores
|
||||
std::vector<int> collectBottomTiles();
|
||||
|
||||
// Helper para recopilar tiles superiores
|
||||
std::vector<int> collectTopTiles();
|
||||
|
||||
// Helper para recopilar tiles animados (para superficies automaticas)
|
||||
std::vector<int> collectAnimatedTiles();
|
||||
|
||||
// Helper para construir lineas horizontales a partir de tiles consecutivos
|
||||
static void buildHorizontalLines(const std::vector<int>& tiles, std::vector<LineHorizontal>& lines, bool is_bottom_surface);
|
||||
|
||||
// Calcula las superficies inferiores
|
||||
void setBottomSurfaces();
|
||||
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
#include "game/gameplay/room_tracker.hpp"
|
||||
|
||||
#include <algorithm> // Para std::ranges::any_of
|
||||
|
||||
// Comprueba si la habitación ya ha sido visitada
|
||||
bool RoomTracker::hasBeenVisited(const std::string& name) {
|
||||
for (const auto& l : list_) {
|
||||
if (l == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return std::ranges::any_of(list_, [&name](const auto& l) { return l == name; });
|
||||
}
|
||||
|
||||
// Añade la habitación a la lista
|
||||
|
||||
@@ -15,8 +15,12 @@
|
||||
#include "utils/utils.hpp" // Para stringToBool, boolToString, safeStoi
|
||||
|
||||
namespace Options {
|
||||
// Declaración de función interna
|
||||
// Declaración de funciones internas
|
||||
bool setOptions(const std::string& var, const std::string& value);
|
||||
std::string trimLine(const std::string& line);
|
||||
bool isCommentOrEmpty(const std::string& line);
|
||||
bool processConfigLine(const std::string& line);
|
||||
bool readConfigFile(const std::string& file_path);
|
||||
|
||||
// Crea e inicializa las opciones del programa
|
||||
void init() {
|
||||
@@ -27,62 +31,82 @@ void init() {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Elimina espacios en blanco al inicio y final de una línea
|
||||
std::string trimLine(const std::string& line) {
|
||||
auto start = std::find_if(line.begin(), line.end(), [](int ch) { return !std::isspace(ch); });
|
||||
auto end = std::find_if(line.rbegin(), line.rend(), [](int ch) { return !std::isspace(ch); }).base();
|
||||
return std::string(start, end);
|
||||
}
|
||||
|
||||
// Verifica si una línea es comentario o está vacía
|
||||
bool isCommentOrEmpty(const std::string& line) {
|
||||
return line.empty() || line[0] == '#';
|
||||
}
|
||||
|
||||
// Procesa una línea de configuración individual
|
||||
bool processConfigLine(const std::string& line) {
|
||||
std::istringstream iss(line);
|
||||
std::string key;
|
||||
std::string value;
|
||||
|
||||
if (iss >> key >> value) {
|
||||
if (!setOptions(key, value)) {
|
||||
if (console) {
|
||||
std::cout << "Warning: file config.txt\n";
|
||||
std::cout << "unknown parameter " << key << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Lee y procesa el fichero de configuración
|
||||
bool readConfigFile(const std::string& file_path) {
|
||||
std::ifstream file(file_path);
|
||||
if (!file.good()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
if (console) {
|
||||
std::cout << "Reading file config.txt\n";
|
||||
}
|
||||
|
||||
std::string line;
|
||||
while (std::getline(file, line)) {
|
||||
line = trimLine(line);
|
||||
|
||||
if (isCommentOrEmpty(line)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!processConfigLine(line)) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (console) {
|
||||
std::cout << "Closing file config.txt\n\n";
|
||||
}
|
||||
file.close();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
// Carga las opciones desde un fichero
|
||||
bool loadFromFile(const std::string& file_path) {
|
||||
// Indicador de éxito en la carga
|
||||
bool success = true;
|
||||
|
||||
// Versión actual del fichero
|
||||
const std::string CONFIG_VERSION = version;
|
||||
version = "";
|
||||
|
||||
// Variables para manejar el fichero
|
||||
std::ifstream file(file_path);
|
||||
// Intenta leer el fichero
|
||||
bool success = readConfigFile(file_path);
|
||||
|
||||
// Si el fichero se puede abrir
|
||||
if (file.good()) {
|
||||
// Procesa el fichero línea a línea
|
||||
if (console) {
|
||||
std::cout << "Reading file config.txt\n";
|
||||
}
|
||||
std::string line;
|
||||
while (std::getline(file, line)) {
|
||||
// Elimina espacios en blanco iniciales y finales
|
||||
line = std::string(std::find_if(line.begin(), line.end(), [](int ch) { return !std::isspace(ch); }),
|
||||
line.end());
|
||||
line.erase(std::find_if(line.rbegin(), line.rend(), [](int ch) { return !std::isspace(ch); })
|
||||
.base(),
|
||||
line.end());
|
||||
|
||||
// Ignora líneas vacías o comentarios
|
||||
if (line.empty() || line[0] == '#') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Usa un stringstream para dividir la línea en dos partes
|
||||
std::istringstream iss(line);
|
||||
std::string key;
|
||||
std::string value;
|
||||
|
||||
if (iss >> key >> value) {
|
||||
if (!setOptions(key, value)) {
|
||||
if (console) {
|
||||
std::cout << "Warning: file config.txt\n";
|
||||
std::cout << "unknown parameter " << key << std::endl;
|
||||
}
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cierra el fichero
|
||||
if (console) {
|
||||
std::cout << "Closing file config.txt\n\n";
|
||||
}
|
||||
file.close();
|
||||
} else {
|
||||
// Crea el fichero con los valores por defecto
|
||||
// Si no se pudo leer, crea el fichero con valores por defecto
|
||||
if (!success) {
|
||||
saveToFile(file_path);
|
||||
success = true;
|
||||
}
|
||||
|
||||
// Si la versión de fichero no coincide, crea un fichero nuevo con los valores por defecto
|
||||
|
||||
@@ -89,7 +89,7 @@ class Game {
|
||||
void renderRoomName();
|
||||
|
||||
// Cambia de habitación
|
||||
bool changeRoom(const std::string& file);
|
||||
bool changeRoom(const std::string& room_path);
|
||||
|
||||
// Comprueba el teclado
|
||||
void checkInput();
|
||||
|
||||
@@ -351,7 +351,7 @@ void LoadingScreen::update() {
|
||||
}
|
||||
|
||||
// Singletones
|
||||
Audio::get()->update(); // Actualiza el objeto Audio
|
||||
Audio::update(); // Actualiza el objeto Audio
|
||||
Screen::get()->update(); // Actualiza el objeto Screen
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user