fix: nou metode per ordenar i dibuixar els jugadors ordenats en l'eix Z
codi: eliminat tot el codi mort de Hit
This commit is contained in:
@@ -1,50 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL.h> // Para SDL_FPoint
|
||||
|
||||
#include <memory> // Para std::unique_ptr y std::shared_ptr
|
||||
|
||||
#include "sprite.hpp" // Para Sprite
|
||||
#include "texture.hpp" // Para Texture
|
||||
|
||||
// --- Estructura Hit: representa una colisión o impacto visual ---
|
||||
struct Hit {
|
||||
public:
|
||||
// --- Constructor ---
|
||||
Hit() = delete; // Elimina el constructor por defecto para obligar a pasar una textura
|
||||
explicit Hit(const std::shared_ptr<Texture>& texture) // Constructor con textura obligatoria
|
||||
: sprite_(std::make_unique<Sprite>(texture)) {}
|
||||
|
||||
// --- Métodos principales ---
|
||||
void create(SDL_FPoint position) { // Crea un "Hit" en la posición especificada
|
||||
setPos(position);
|
||||
enable(true);
|
||||
}
|
||||
void render() { // Dibuja el hit
|
||||
if (enabled_) {
|
||||
sprite_->render();
|
||||
}
|
||||
}
|
||||
void disable() { // Deshabilita el hit
|
||||
enabled_ = false;
|
||||
}
|
||||
|
||||
// --- Configuración ---
|
||||
void setPos(SDL_FPoint position) { // Establece la posición del Sprite en el espacio
|
||||
SDL_FPoint centered_position = {position.x - (sprite_->getWidth() / 2), position.y - (sprite_->getHeight() / 2)};
|
||||
sprite_->setPosition(centered_position);
|
||||
}
|
||||
void enable(bool value) { // Activa o desactiva el Hit
|
||||
enabled_ = value;
|
||||
}
|
||||
|
||||
// --- Getters ---
|
||||
[[nodiscard]] auto isEnabled() const -> bool { // Consulta si el Hit está activo
|
||||
return enabled_;
|
||||
}
|
||||
|
||||
private:
|
||||
// --- Variables de estado ---
|
||||
std::unique_ptr<Sprite> sprite_; // Sprite asociado al Hit
|
||||
bool enabled_{false}; // Indica si el Hit está activo
|
||||
};
|
||||
@@ -96,7 +96,6 @@ auto setParams(const std::string& var, const std::string& value) -> bool {
|
||||
{"game.play_area.rect.h", [](const std::string& v) { param.game.play_area.rect.h = std::stoi(v); }},
|
||||
{"game.name_entry_idle_time", [](const std::string& v) { param.game.name_entry_idle_time = std::stoi(v); }},
|
||||
{"game.name_entry_total_time", [](const std::string& v) { param.game.name_entry_total_time = std::stoi(v); }},
|
||||
{"game.hit_stop_ms", [](const std::string& v) { param.game.hit_stop_ms = std::stoi(v); }},
|
||||
{"fade.num_squares_width", [](const std::string& v) { param.fade.num_squares_width = std::stoi(v); }},
|
||||
{"fade.num_squares_height", [](const std::string& v) { param.fade.num_squares_height = std::stoi(v); }},
|
||||
{"fade.random_squares_duration_ms", [](const std::string& v) { param.fade.random_squares_duration_ms = std::stoi(v); }},
|
||||
@@ -165,7 +164,6 @@ auto setParams(const std::string& var, const std::string& value) -> bool {
|
||||
{"player.outline_color[1]", [](const std::string& v) { param.player.outline_color[1] = Color::fromHex(v); }}};
|
||||
|
||||
static const std::unordered_map<std::string, std::function<void(const std::string&)>> BOOL_PARAMS = {
|
||||
{"game.hit_stop", [](const std::string& v) { param.game.hit_stop = stringToBool(v); }},
|
||||
{"scoreboard.separator_autocolor", [](const std::string& v) { param.scoreboard.separator_autocolor = stringToBool(v); }},
|
||||
{"scoreboard.text_autocolor", [](const std::string& v) { param.scoreboard.text_autocolor = stringToBool(v); }},
|
||||
{"balloon.bouncing_sound", [](const std::string& v) { param.balloon.bouncing_sound = stringToBool(v); }},
|
||||
|
||||
@@ -18,9 +18,6 @@ struct ParamGame {
|
||||
Zone game_area{}; // Se inicializa en el constructor de Param
|
||||
int name_entry_idle_time = GameDefaults::Game::NAME_ENTRY_IDLE_TIME;
|
||||
int name_entry_total_time = GameDefaults::Game::NAME_ENTRY_TOTAL_TIME;
|
||||
Uint32 speed = 15; // Este valor no estaba en el archivo de configuración
|
||||
bool hit_stop = GameDefaults::Game::HIT_STOP;
|
||||
Uint32 hit_stop_ms = GameDefaults::Game::HIT_STOP_MS;
|
||||
Color item_text_outline_color;
|
||||
};
|
||||
|
||||
|
||||
@@ -187,6 +187,9 @@ class Player {
|
||||
[[nodiscard]] auto getName() const -> const std::string& { return name_; }
|
||||
[[nodiscard]] auto getPlayingState() const -> State { return playing_state_; }
|
||||
auto getCollider() -> Circle& { return collider_; }
|
||||
[[nodiscard]] auto getZOrder() const -> size_t { return z_order_; }
|
||||
void setZOrder(size_t z_order) { z_order_ = z_order; }
|
||||
|
||||
|
||||
// Puntuación y juego
|
||||
[[nodiscard]] auto getScore() const -> int { return score_; }
|
||||
@@ -309,6 +312,7 @@ class Player {
|
||||
int continue_counter_ = 10; // Contador para poder continuar
|
||||
int controller_index_ = 0; // Índice del array de mandos que utilizará para moverse
|
||||
size_t demo_file_ = 0; // Indice del fichero de datos para el modo demo
|
||||
size_t z_order_ = 0; // Orden de dibujado en la pantalla
|
||||
float name_entry_idle_time_accumulator_ = 0.0F; // Tiempo idle acumulado para poner nombre (milisegundos)
|
||||
float name_entry_total_time_accumulator_ = 0.0F; // Tiempo total acumulado poniendo nombre (milisegundos)
|
||||
int step_counter_ = 0; // Cuenta los pasos para los estados en los que camina automáticamente
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "fade.hpp" // Para Fade
|
||||
#include "global_events.hpp" // Para handle
|
||||
#include "global_inputs.hpp" // Para check
|
||||
#include "hit.hpp" // Para Hit
|
||||
#include "input.hpp" // Para Input
|
||||
#include "input_types.hpp" // Para InputAction
|
||||
#include "item.hpp" // Para Item, ItemType
|
||||
@@ -65,8 +64,7 @@ Game::Game(Player::Id player_id, int current_stage, bool demo_enabled)
|
||||
background_(std::make_unique<Background>(stage_manager_->getPowerNeededToReachStage(stage_manager_->getTotalStages() - 1))),
|
||||
fade_in_(std::make_unique<Fade>()),
|
||||
fade_out_(std::make_unique<Fade>()),
|
||||
tabe_(std::make_unique<Tabe>()),
|
||||
hit_(Hit(Resource::get()->getTexture("hit.png"))) {
|
||||
tabe_(std::make_unique<Tabe>()) {
|
||||
// Pasa variables
|
||||
demo_.enabled = demo_enabled;
|
||||
|
||||
@@ -275,14 +273,12 @@ void Game::updatePlayers(float delta_time) {
|
||||
}
|
||||
|
||||
// Organiza la lista de jugadores
|
||||
//sortPlayersByZOrder();
|
||||
// sortPlayersByZOrder();
|
||||
}
|
||||
|
||||
// Dibuja a los jugadores
|
||||
void Game::renderPlayers() {
|
||||
for (auto& player : players_) {
|
||||
player->render();
|
||||
}
|
||||
renderPlayerDrawList(players_draw_list_);
|
||||
}
|
||||
|
||||
// Comprueba si hay cambio de fase y actualiza las variables
|
||||
@@ -812,15 +808,10 @@ void Game::handlePlayerCollision(std::shared_ptr<Player>& player, std::shared_pt
|
||||
} else {
|
||||
// Si no tiene cafes, muere
|
||||
playSound("player_collision.wav");
|
||||
if (param.game.hit_stop) {
|
||||
pauseMusic();
|
||||
SDL_Delay(param.game.hit_stop_ms);
|
||||
resumeMusic();
|
||||
}
|
||||
screen_->shake();
|
||||
playSound("voice_no.wav");
|
||||
player->setPlayingState(Player::State::ROLLING);
|
||||
sendPlayerToTheBack(player);
|
||||
sendPlayerToBack(players_, player, players_draw_list_);
|
||||
if (allPlayersAreNotPlaying()) {
|
||||
stage_manager_->disablePowerCollection();
|
||||
}
|
||||
@@ -1137,11 +1128,11 @@ void Game::handleEvents() {
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_WINDOW_FOCUS_LOST: {
|
||||
//pause_manager_->setFocusLossPause(!demo_.enabled);
|
||||
pause_manager_->setFocusLossPause(!demo_.enabled);
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED: {
|
||||
//pause_manager_->setFocusLossPause(false);
|
||||
pause_manager_->setFocusLossPause(false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -1416,7 +1407,7 @@ void Game::handlePlayerContinueInput(const std::shared_ptr<Player>& player) {
|
||||
if (input_->checkAction(Input::Action::START, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad())) {
|
||||
player->setPlayingState(Player::State::RECOVER);
|
||||
player->addCredit();
|
||||
sendPlayerToTheFront(player);
|
||||
bringPlayerToFront(players_, player, players_draw_list_);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1435,7 +1426,7 @@ void Game::handlePlayerWaitingInput(const std::shared_ptr<Player>& player) {
|
||||
if (input_->checkAction(Input::Action::START, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad())) {
|
||||
player->setPlayingState(Player::State::ENTERING_SCREEN);
|
||||
player->addCredit();
|
||||
sendPlayerToTheFront(player);
|
||||
bringPlayerToFront(players_, player, players_draw_list_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1634,6 +1625,7 @@ void Game::initPlayers(Player::Id player_id) {
|
||||
player1->setName(Lang::getText("[SCOREBOARD] 1"));
|
||||
player1->setGamepad(Options::gamepad_manager.getGamepad(Player::Id::PLAYER1).instance);
|
||||
player1->setUsesKeyboard(Player::Id::PLAYER1 == Options::keyboard.player_id);
|
||||
player1->setZOrder(0);
|
||||
#ifdef RECORDING
|
||||
player1->setPlayingState(Player::State::PLAYING);
|
||||
#else
|
||||
@@ -1661,6 +1653,7 @@ void Game::initPlayers(Player::Id player_id) {
|
||||
player2->setGamepad(Options::gamepad_manager.getGamepad(Player::Id::PLAYER2).instance);
|
||||
player2->setUsesKeyboard(Player::Id::PLAYER2 == Options::keyboard.player_id);
|
||||
player2->setPlayingState((player_id == Player::Id::BOTH_PLAYERS || player_id == Player::Id::PLAYER2) ? STATE : Player::State::WAITING);
|
||||
player2->setZOrder(1);
|
||||
|
||||
// Añade los jugadores al vector de forma que el jugador 1 se pinte por delante del jugador 2
|
||||
players_.push_back(std::move(player2));
|
||||
@@ -1671,6 +1664,9 @@ void Game::initPlayers(Player::Id player_id) {
|
||||
Options::keyboard.addPlayer(player);
|
||||
Options::gamepad_manager.addPlayer(player);
|
||||
}
|
||||
|
||||
// Construye la lista de dibujado de los jugadores
|
||||
buildPlayerDrawList(players_, players_draw_list_);
|
||||
}
|
||||
|
||||
// Hace sonar la música
|
||||
@@ -1908,45 +1904,6 @@ void Game::playSound(const std::string& name) const {
|
||||
audio_->playSound(name);
|
||||
}
|
||||
|
||||
// Organiza los jugadores para que los vivos se pinten sobre los muertos
|
||||
void Game::sortPlayersByZOrder() {
|
||||
// Procesar jugadores que van al fondo (se dibujan primero)
|
||||
if (!players_to_put_at_back_.empty()) {
|
||||
for (auto& player : players_to_put_at_back_) {
|
||||
auto it = std::ranges::find(players_, player);
|
||||
if (it != players_.end() && it != players_.begin()) {
|
||||
const std::shared_ptr<Player>& dying_player = *it;
|
||||
players_.erase(it);
|
||||
players_.insert(players_.begin(), dying_player);
|
||||
}
|
||||
}
|
||||
players_to_put_at_back_.clear();
|
||||
}
|
||||
|
||||
// Procesar jugadores que van al frente (se dibujan últimos)
|
||||
if (!players_to_put_at_front_.empty()) {
|
||||
for (auto& player : players_to_put_at_front_) {
|
||||
auto it = std::ranges::find(players_, player);
|
||||
if (it != players_.end() && it != players_.end() - 1) {
|
||||
const std::shared_ptr<Player>& front_player = *it;
|
||||
players_.erase(it);
|
||||
players_.push_back(front_player);
|
||||
}
|
||||
}
|
||||
players_to_put_at_front_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Mueve el jugador para pintarlo al fondo de la lista de jugadores
|
||||
void Game::sendPlayerToTheBack(const std::shared_ptr<Player>& player) {
|
||||
players_to_put_at_back_.push_back(player);
|
||||
}
|
||||
|
||||
// Mueve el jugador para pintarlo el primero de la lista de jugadores
|
||||
void Game::sendPlayerToTheFront(const std::shared_ptr<Player>& player) {
|
||||
players_to_put_at_front_.push_back(player);
|
||||
}
|
||||
|
||||
void Game::onPauseStateChanged(bool is_paused) {
|
||||
screen_->attenuate(is_paused);
|
||||
tabe_->pauseTimer(is_paused);
|
||||
@@ -2013,6 +1970,70 @@ void Game::handleGameOverEvents() {
|
||||
}
|
||||
}
|
||||
|
||||
// Construye (una vez) el drawList a partir del vector principal
|
||||
// drawList almacena punteros a los elementos y queda reservado
|
||||
void Game::buildPlayerDrawList(const Players& elements, Players& drawList) {
|
||||
drawList.clear();
|
||||
drawList.reserve(elements.size());
|
||||
for (const auto& e : elements) drawList.push_back(e); // copia el shared_ptr
|
||||
std::stable_sort(drawList.begin(), drawList.end(), [](const std::shared_ptr<Player>& a, const std::shared_ptr<Player>& b) {
|
||||
return a->getZOrder() < b->getZOrder();
|
||||
});
|
||||
}
|
||||
|
||||
// Actualiza drawList tras cambios en los z_order. Implementación simple:
|
||||
// reordena drawList según los z_order actuales. Llamar cuando cambian z_order
|
||||
void Game::updatePlayerDrawList(const Players& elements, Players& drawList) {
|
||||
// Si drawList está vacío o su tamaño no coincide, reconstruirlo.
|
||||
if (drawList.size() != elements.size()) {
|
||||
buildPlayerDrawList(elements, drawList);
|
||||
return;
|
||||
}
|
||||
// Dado que apuntan a los mismos elementos, basta ordenar por los z_order actuales.
|
||||
std::stable_sort(drawList.begin(), drawList.end(), [](const std::shared_ptr<Player>& a, const std::shared_ptr<Player>& b) {
|
||||
return a->getZOrder() < b->getZOrder();
|
||||
});
|
||||
}
|
||||
|
||||
// Dibuja en el orden definido por drawList
|
||||
void Game::renderPlayerDrawList(const Players& drawList) {
|
||||
for (const auto& e : drawList) e->render();
|
||||
}
|
||||
|
||||
// Operaciones sobre z_order que mantienen la invariante y actualizan drawList.
|
||||
auto Game::findPlayerIndex(const Players& elems, const std::shared_ptr<Player>& who) -> size_t {
|
||||
for (size_t i = 0; i < elems.size(); ++i)
|
||||
if (elems[i] == who) return static_cast<int>(i); // compara shared_ptr directamente
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Game::sendPlayerToBack(Players& elements, const std::shared_ptr<Player>& who, Players& drawList) {
|
||||
int idx = findPlayerIndex(elements, who);
|
||||
if (idx < 0) return; // no encontrado
|
||||
const int oldZ = elements[idx]->getZOrder();
|
||||
if (oldZ <= 0) return;
|
||||
for (auto& p : elements) {
|
||||
int z = p->getZOrder();
|
||||
if (z < oldZ) p->setZOrder(z + 1);
|
||||
}
|
||||
elements[idx]->setZOrder(0);
|
||||
updatePlayerDrawList(elements, drawList);
|
||||
}
|
||||
|
||||
void Game::bringPlayerToFront(Players& elements, const std::shared_ptr<Player>& who, Players& drawList) {
|
||||
int idx = findPlayerIndex(elements, who);
|
||||
if (idx < 0) return; // no encontrado
|
||||
const int oldZ = elements[idx]->getZOrder();
|
||||
const int N = static_cast<int>(elements.size());
|
||||
if (oldZ >= N - 1) return;
|
||||
for (auto& p : elements) {
|
||||
int z = p->getZOrder();
|
||||
if (z > oldZ) p->setZOrder(z - 1);
|
||||
}
|
||||
elements[idx]->setZOrder(N - 1);
|
||||
updatePlayerDrawList(elements, drawList);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
// Comprueba los eventos en el modo DEBUG
|
||||
void Game::handleDebugEvents(const SDL_Event& event) {
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
|
||||
#include <SDL3/SDL.h> // Para SDL_Event, SDL_Renderer, SDL_Texture, Uint64
|
||||
|
||||
#include <list> // Para list
|
||||
#include <memory> // Para shared_ptr, unique_ptr
|
||||
#include <string> // Para string
|
||||
#include <vector> // Para vector
|
||||
#include <list> // Para list
|
||||
|
||||
#include "bullet.hpp" // for Bullet
|
||||
#include "demo.hpp" // for Demo
|
||||
#include "hit.hpp" // for Hit
|
||||
#include "item.hpp" // for Item (ptr only), ItemType
|
||||
#include "manage_hiscore_table.hpp" // for HiScoreEntry
|
||||
#include "options.hpp" // for Settings, settings
|
||||
@@ -65,6 +64,8 @@ class Game {
|
||||
void run(); // Ejecuta el bucle principal del juego
|
||||
|
||||
private:
|
||||
using Players = std::vector<std::shared_ptr<Player>>;
|
||||
|
||||
// --- Enums ---
|
||||
enum class State {
|
||||
FADE_IN, // Transición de entrada
|
||||
@@ -121,7 +122,8 @@ class Game {
|
||||
|
||||
SDL_Texture* canvas_; // Textura para dibujar la zona de juego
|
||||
|
||||
std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
|
||||
Players players_; // Vector con los jugadores
|
||||
Players players_draw_list_; // Vector con los jugadores ordenados para ser renderizados
|
||||
std::list<std::unique_ptr<Item>> items_; // Vector con los items
|
||||
std::list<std::unique_ptr<SmartSprite>> smart_sprites_; // Vector con los smartsprites
|
||||
std::list<std::unique_ptr<PathSprite>> path_sprites_; // Vector con los pathsprites
|
||||
@@ -163,9 +165,6 @@ class Game {
|
||||
int menace_ = 0; // Nivel de amenaza actual
|
||||
int menace_threshold_ = 0; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos
|
||||
State state_ = State::FADE_IN; // Estado
|
||||
std::vector<std::shared_ptr<Player>> players_to_put_at_back_;
|
||||
std::vector<std::shared_ptr<Player>> players_to_put_at_front_;
|
||||
Hit hit_; // Para representar colisiones en pantalla
|
||||
|
||||
// Estructuras para gestionar flags de eventos basados en tiempo
|
||||
struct GameOverFlags {
|
||||
@@ -226,7 +225,6 @@ class Game {
|
||||
void initPlayers(Player::Id player_id); // Inicializa los datos de los jugadores
|
||||
void updatePlayers(float delta_time); // Actualiza las variables y estados de los jugadores
|
||||
void renderPlayers(); // Renderiza todos los jugadores en pantalla
|
||||
void sortPlayersByZOrder(); // Reorganiza el orden de dibujado de jugadores
|
||||
auto getPlayer(Player::Id id) -> std::shared_ptr<Player>; // Obtiene un jugador por su identificador
|
||||
static auto getController(Player::Id player_id) -> int; // Obtiene el controlador asignado a un jugador
|
||||
|
||||
@@ -260,9 +258,6 @@ class Game {
|
||||
void demoHandlePassInput(); // Permite saltar la demostración
|
||||
void demoHandlePlayerInput(const std::shared_ptr<Player>& player, int index); // Procesa entrada de jugador en demo
|
||||
|
||||
// --- Sistema de balas y proyectiles ---
|
||||
void checkBulletCollision(); // Verifica colisiones de todas las balas (delegado a BulletManager)
|
||||
|
||||
// --- Colisiones específicas de balas ---
|
||||
auto checkBulletTabeCollision(const std::shared_ptr<Bullet>& bullet) -> bool; // Detecta colisión bala-Tabe
|
||||
auto checkBulletBalloonCollision(const std::shared_ptr<Bullet>& bullet) -> bool; // Detecta colisión bala-globo
|
||||
@@ -338,8 +333,15 @@ class Game {
|
||||
static void resumeMusic(); // Retoma la música que eestaba pausada
|
||||
void playSound(const std::string& name) const; // Reproduce un efecto de sonido específico
|
||||
|
||||
void sendPlayerToTheBack(const std::shared_ptr<Player>& player); // Mueve el jugador para pintarlo al fondo de la lista de jugadores
|
||||
void sendPlayerToTheFront(const std::shared_ptr<Player>& player); // Mueve el jugador para pintarlo el primero de la lista de jugadores
|
||||
// --- Gestion y dibujado de jugadores en z-order ---
|
||||
void buildPlayerDrawList(const Players& elements, Players& drawList); // Construye el drawList a partir del vector principal
|
||||
void updatePlayerDrawList(const Players& elements, Players& drawList); // Actualiza drawList tras cambios en los z_order
|
||||
void renderPlayerDrawList(const Players& drawList); // Dibuja en el orden definido
|
||||
static auto findPlayerIndex(const Players& elems, const std::shared_ptr<Player>& who) -> size_t;
|
||||
void sendPlayerToBack(Players& elements, const std::shared_ptr<Player>& who, Players& drawList); // Envia al jugador al fondo de la pantalla
|
||||
void bringPlayerToFront(Players& elements, const std::shared_ptr<Player>& who, Players& drawList); // Envia al jugador al frente de la pantalla
|
||||
|
||||
// --- Varios ---
|
||||
void onPauseStateChanged(bool is_paused);
|
||||
|
||||
// SISTEMA DE GRABACIÓN (CONDICIONAL)
|
||||
|
||||
Reference in New Issue
Block a user