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:
2025-10-21 09:30:31 +02:00
parent d7836eedd7
commit bf12c1664a
10 changed files with 95 additions and 130 deletions

View File

@@ -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) {

View File

@@ -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)