diff --git a/source/core/system/director.cpp b/source/core/system/director.cpp index 9064d77..0cbd572 100644 --- a/source/core/system/director.cpp +++ b/source/core/system/director.cpp @@ -36,8 +36,8 @@ #include "utils/defines.hpp" // Para WINDOW_CAPTION #ifdef _DEBUG -#include "core/system/debug.hpp" // Para Debug -#include "game/editor/map_editor.hpp" // Para MapEditor +#include "core/system/debug.hpp" // Para Debug +#include "game/editor/map_editor.hpp" // Para MapEditor #endif #ifndef _WIN32 diff --git a/source/game/editor/editor_statusbar.cpp b/source/game/editor/editor_statusbar.cpp index a250a80..1bd70ac 100644 --- a/source/game/editor/editor_statusbar.cpp +++ b/source/game/editor/editor_statusbar.cpp @@ -4,13 +4,13 @@ #include // Para to_string -#include "core/rendering/screen.hpp" // Para Screen -#include "core/rendering/surface.hpp" // Para Surface -#include "core/rendering/text.hpp" // Para Text +#include "core/rendering/screen.hpp" // Para Screen +#include "core/rendering/surface.hpp" // Para Surface +#include "core/rendering/text.hpp" // Para Text #include "core/resources/resource_cache.hpp" // Para Resource::Cache -#include "game/options.hpp" // Para Options::game -#include "utils/defines.hpp" // Para Tile::SIZE -#include "utils/utils.hpp" // Para stringToColor +#include "game/options.hpp" // Para Options::game +#include "utils/defines.hpp" // Para Tile::SIZE +#include "utils/utils.hpp" // Para stringToColor // Constructor EditorStatusBar::EditorStatusBar(const std::string& room_number, const std::string& room_name) @@ -39,6 +39,11 @@ void EditorStatusBar::setMouseTile(int tile_x, int tile_y) { mouse_tile_y_ = tile_y; } +// Establece la información de la entidad seleccionada +void EditorStatusBar::setSelectionInfo(const std::string& info) { + selection_info_ = info; +} + // Dibuja los elementos en la surface void EditorStatusBar::fillTexture() { auto previous_renderer = Screen::get()->getRendererSurface(); @@ -60,8 +65,12 @@ void EditorStatusBar::fillTexture() { text->writeColored(LEFT_X, LINE2_Y, "TILE:", LABEL_COLOR); text->writeColored(LEFT_X + 48, LINE2_Y, TILE_X_STR + "," + TILE_Y_STR, VALUE_COLOR); - // Indicador de modo editor - text->writeColored(176, LINE2_Y, "EDITOR", stringToColor("bright_green")); + // Info de selección o indicador de modo editor + if (!selection_info_.empty()) { + text->writeColored(LEFT_X + 112, LINE2_Y, selection_info_, stringToColor("bright_yellow")); + } else { + text->writeColored(176, LINE2_Y, "EDITOR", stringToColor("bright_green")); + } Screen::get()->setRendererSurface(previous_renderer); } diff --git a/source/game/editor/editor_statusbar.hpp b/source/game/editor/editor_statusbar.hpp index 48d4051..c9dbb0d 100644 --- a/source/game/editor/editor_statusbar.hpp +++ b/source/game/editor/editor_statusbar.hpp @@ -17,6 +17,7 @@ class EditorStatusBar { void render(); void update(float delta_time); void setMouseTile(int tile_x, int tile_y); + void setSelectionInfo(const std::string& info); private: void fillTexture(); // Dibuja los elementos en la surface @@ -31,10 +32,11 @@ class EditorStatusBar { SDL_FRect surface_dest_{}; // Rectángulo destino en pantalla // Variables - std::string room_number_; // Número de la habitación - std::string room_name_; // Nombre de la habitación - int mouse_tile_x_{0}; // Coordenada X del ratón en tiles - int mouse_tile_y_{0}; // Coordenada Y del ratón en tiles + std::string room_number_; // Número de la habitación + std::string room_name_; // Nombre de la habitación + int mouse_tile_x_{0}; // Coordenada X del ratón en tiles + int mouse_tile_y_{0}; // Coordenada Y del ratón en tiles + std::string selection_info_; // Información de la entidad seleccionada }; #endif // _DEBUG diff --git a/source/game/editor/map_editor.cpp b/source/game/editor/map_editor.cpp index ec14216..d83d5a4 100644 --- a/source/game/editor/map_editor.cpp +++ b/source/game/editor/map_editor.cpp @@ -7,16 +7,18 @@ #include // Para std::round #include // Para cout -#include "core/input/mouse.hpp" // Para Mouse -#include "core/rendering/screen.hpp" // Para Screen -#include "core/rendering/surface.hpp" // Para Surface +#include "core/input/mouse.hpp" // Para Mouse +#include "core/rendering/screen.hpp" // Para Screen +#include "core/rendering/surface.hpp" // Para Surface #include "core/resources/resource_cache.hpp" // Para Resource::Cache -#include "game/editor/editor_statusbar.hpp" // Para EditorStatusBar -#include "game/entities/player.hpp" // Para Player -#include "game/gameplay/room.hpp" // Para Room -#include "game/options.hpp" // Para Options -#include "utils/defines.hpp" // Para Tile::SIZE, PlayArea -#include "utils/utils.hpp" // Para stringToColor +#include "game/editor/editor_statusbar.hpp" // Para EditorStatusBar +#include "game/entities/player.hpp" // Para Player +#include "game/gameplay/enemy_manager.hpp" // Para EnemyManager +#include "game/gameplay/item_manager.hpp" // Para ItemManager +#include "game/gameplay/room.hpp" // Para Room +#include "game/options.hpp" // Para Options +#include "utils/defines.hpp" // Para Tile::SIZE, PlayArea +#include "utils/utils.hpp" // Para stringToColor // Singleton MapEditor* MapEditor::instance_ = nullptr; @@ -41,8 +43,7 @@ MapEditor::MapEditor() = default; MapEditor::~MapEditor() = default; // Entra en modo editor -void MapEditor::enter(std::shared_ptr room, std::shared_ptr player, - const std::string& room_path, std::shared_ptr scoreboard_data) { +void MapEditor::enter(std::shared_ptr room, std::shared_ptr player, const std::string& room_path, std::shared_ptr scoreboard_data) { if (active_) { return; } room_ = std::move(room); @@ -61,6 +62,9 @@ void MapEditor::enter(std::shared_ptr room, std::shared_ptr player Options::cheats.invincible = Options::Cheat::State::ENABLED; player_->setColor(); + // Resetear enemigos a su posición inicial (pueden haberse movido durante el gameplay) + room_->resetEnemyPositions(room_data_.enemies); + // Crear la barra de estado statusbar_ = std::make_unique(room_->getNumber(), room_->getName()); @@ -108,9 +112,34 @@ void MapEditor::update(float delta_time) { updateDrag(); } - // Actualizar la barra de estado con las coordenadas del ratón + // Actualizar la barra de estado con las coordenadas del ratón y la selección if (statusbar_) { statusbar_->setMouseTile(mouse_tile_x_, mouse_tile_y_); + + // Construir info de selección + std::string sel_info; + if (drag_.target != DragTarget::NONE) { + switch (drag_.target) { + case DragTarget::PLAYER: + sel_info = "PLAYER"; + break; + case DragTarget::ENEMY_INITIAL: + sel_info = "ENEMY " + std::to_string(drag_.index); + break; + case DragTarget::ENEMY_BOUND1: + sel_info = "E" + std::to_string(drag_.index) + " BOUND1"; + break; + case DragTarget::ENEMY_BOUND2: + sel_info = "E" + std::to_string(drag_.index) + " BOUND2"; + break; + case DragTarget::ITEM: + sel_info = "ITEM " + std::to_string(drag_.index); + break; + case DragTarget::NONE: + break; + } + } + statusbar_->setSelectionInfo(sel_info); statusbar_->update(delta_time); } } @@ -147,34 +176,108 @@ void MapEditor::handleEvent(const SDL_Event& event) { // Procesa click del ratón: hit test + inicio de drag void MapEditor::handleMouseDown(float game_x, float game_y) { - // Prioridad de hit test: jugador → enemigos → items + // Prioridad de hit test: jugador → enemigos (initial) → enemigos (boundaries) → items - // 1. Hit test sobre el jugador + // Helper para iniciar drag + auto startDrag = [&](DragTarget target, int index, float entity_x, float entity_y) { + drag_.target = target; + drag_.index = index; + drag_.offset_x = game_x - entity_x; + drag_.offset_y = game_y - entity_y; + drag_.snap_x = entity_x; + drag_.snap_y = entity_y; + }; + + // 1. Hit test sobre el jugador (8x16) SDL_FRect player_rect = player_->getRect(); if (pointInRect(game_x, game_y, player_rect)) { - drag_.target = DragTarget::PLAYER; - drag_.index = -1; - drag_.offset_x = game_x - player_rect.x; - drag_.offset_y = game_y - player_rect.y; - drag_.snap_x = player_rect.x; - drag_.snap_y = player_rect.y; + startDrag(DragTarget::PLAYER, -1, player_rect.x, player_rect.y); return; } - // (Fases 4+: hit test sobre enemigos e items) + // 2. Hit test sobre enemigos: posición inicial (usan el rect del sprite vivo) + auto* enemy_mgr = room_->getEnemyManager(); + for (int i = 0; i < enemy_mgr->getCount(); ++i) { + SDL_FRect enemy_rect = enemy_mgr->getEnemy(i)->getRect(); + if (pointInRect(game_x, game_y, enemy_rect)) { + startDrag(DragTarget::ENEMY_INITIAL, i, enemy_rect.x, enemy_rect.y); + return; + } + } + + // 3. Hit test sobre boundaries de enemigos (rectángulos 8x8 en las posiciones de room_data_) + for (int i = 0; i < static_cast(room_data_.enemies.size()); ++i) { + const auto& ed = room_data_.enemies[i]; + constexpr float SZ = static_cast(Tile::SIZE); + + SDL_FRect b1_rect = {.x = static_cast(ed.x1), .y = static_cast(ed.y1), .w = SZ, .h = SZ}; + if (pointInRect(game_x, game_y, b1_rect)) { + startDrag(DragTarget::ENEMY_BOUND1, i, b1_rect.x, b1_rect.y); + return; + } + + SDL_FRect b2_rect = {.x = static_cast(ed.x2), .y = static_cast(ed.y2), .w = SZ, .h = SZ}; + if (pointInRect(game_x, game_y, b2_rect)) { + startDrag(DragTarget::ENEMY_BOUND2, i, b2_rect.x, b2_rect.y); + return; + } + } + + // 4. Hit test sobre items (8x8) + auto* item_mgr = room_->getItemManager(); + for (int i = 0; i < item_mgr->getCount(); ++i) { + SDL_FRect item_rect = item_mgr->getItem(i)->getCollider(); + if (pointInRect(game_x, game_y, item_rect)) { + startDrag(DragTarget::ITEM, i, item_rect.x, item_rect.y); + return; + } + } } // Procesa soltar el ratón: commit del drag void MapEditor::handleMouseUp() { if (drag_.target == DragTarget::NONE) { return; } + const int IDX = drag_.index; + const int SNAP_X = static_cast(drag_.snap_x); + const int SNAP_Y = static_cast(drag_.snap_y); + switch (drag_.target) { case DragTarget::PLAYER: - // Mover el jugador a la posición snapped player_->setDebugPosition(drag_.snap_x, drag_.snap_y); player_->finalizeDebugTeleport(); break; - default: + + case DragTarget::ENEMY_INITIAL: + // Actualizar datos mutables y posición del sprite vivo + if (IDX >= 0 && IDX < static_cast(room_data_.enemies.size())) { + room_data_.enemies[IDX].x = drag_.snap_x; + room_data_.enemies[IDX].y = drag_.snap_y; + room_->getEnemyManager()->getEnemy(IDX)->resetToInitialPosition(room_data_.enemies[IDX]); + } + break; + + case DragTarget::ENEMY_BOUND1: + if (IDX >= 0 && IDX < static_cast(room_data_.enemies.size())) { + room_data_.enemies[IDX].x1 = SNAP_X; + room_data_.enemies[IDX].y1 = SNAP_Y; + } + break; + + case DragTarget::ENEMY_BOUND2: + if (IDX >= 0 && IDX < static_cast(room_data_.enemies.size())) { + room_data_.enemies[IDX].x2 = SNAP_X; + room_data_.enemies[IDX].y2 = SNAP_Y; + } + break; + + case DragTarget::ITEM: + if (IDX >= 0 && IDX < room_->getItemManager()->getCount()) { + room_->getItemManager()->getItem(IDX)->setPosition(drag_.snap_x, drag_.snap_y); + } + break; + + case DragTarget::NONE: break; } @@ -191,8 +294,37 @@ void MapEditor::updateDrag() { drag_.snap_y = snapToGrid(raw_y); // Mientras arrastramos, mover la entidad visualmente a la posición snapped - if (drag_.target == DragTarget::PLAYER) { - player_->setDebugPosition(drag_.snap_x, drag_.snap_y); + switch (drag_.target) { + case DragTarget::PLAYER: + player_->setDebugPosition(drag_.snap_x, drag_.snap_y); + break; + + case DragTarget::ENEMY_INITIAL: + if (drag_.index >= 0 && drag_.index < room_->getEnemyManager()->getCount()) { + // Mover el sprite vivo del enemigo durante el arrastre + auto& enemy = room_->getEnemyManager()->getEnemy(drag_.index); + Enemy::Data temp_data = room_data_.enemies[drag_.index]; + temp_data.x = drag_.snap_x; + temp_data.y = drag_.snap_y; + enemy->resetToInitialPosition(temp_data); + } + break; + + case DragTarget::ENEMY_BOUND1: + // Los boundaries se actualizan visualmente en renderEnemyBoundaries() via drag_.snap + break; + + case DragTarget::ENEMY_BOUND2: + break; + + case DragTarget::ITEM: + if (drag_.index >= 0 && drag_.index < room_->getItemManager()->getCount()) { + room_->getItemManager()->getItem(drag_.index)->setPosition(drag_.snap_x, drag_.snap_y); + } + break; + + case DragTarget::NONE: + break; } } @@ -204,13 +336,32 @@ void MapEditor::renderSelectionHighlight() { if (!game_surface) { return; } const Uint8 HIGHLIGHT_COLOR = stringToColor("bright_white"); + constexpr float SZ = static_cast(Tile::SIZE); SDL_FRect highlight_rect{}; switch (drag_.target) { case DragTarget::PLAYER: highlight_rect = player_->getRect(); break; - default: + + case DragTarget::ENEMY_INITIAL: + if (drag_.index >= 0 && drag_.index < room_->getEnemyManager()->getCount()) { + highlight_rect = room_->getEnemyManager()->getEnemy(drag_.index)->getRect(); + } + break; + + case DragTarget::ENEMY_BOUND1: + case DragTarget::ENEMY_BOUND2: + highlight_rect = {.x = drag_.snap_x, .y = drag_.snap_y, .w = SZ, .h = SZ}; + break; + + case DragTarget::ITEM: + if (drag_.index >= 0 && drag_.index < room_->getItemManager()->getCount()) { + highlight_rect = room_->getItemManager()->getItem(drag_.index)->getCollider(); + } + break; + + case DragTarget::NONE: return; } @@ -219,8 +370,7 @@ void MapEditor::renderSelectionHighlight() { .x = highlight_rect.x - 1, .y = highlight_rect.y - 1, .w = highlight_rect.w + 2, - .h = highlight_rect.h + 2 - }; + .h = highlight_rect.h + 2}; game_surface->drawRectBorder(&border, HIGHLIGHT_COLOR); } @@ -243,25 +393,39 @@ void MapEditor::renderEnemyBoundaries() { const Uint8 COLOR_BOUND2 = stringToColor("bright_yellow"); const Uint8 COLOR_ROUTE = stringToColor("bright_white"); - for (const auto& enemy : room_data_.enemies) { - // Dibujar línea de ruta: boundary1 → posición inicial → boundary2 + for (int i = 0; i < static_cast(room_data_.enemies.size()); ++i) { + const auto& enemy = room_data_.enemies[i]; constexpr float HALF = Tile::SIZE / 2.0F; - float init_cx = enemy.x + HALF; - float init_cy = enemy.y + HALF; - float b1_cx = static_cast(enemy.x1) + HALF; - float b1_cy = static_cast(enemy.y1) + HALF; - float b2_cx = static_cast(enemy.x2) + HALF; - float b2_cy = static_cast(enemy.y2) + HALF; + // Posiciones base (pueden estar siendo arrastradas) + float init_x = enemy.x; + float init_y = enemy.y; + float b1_x = static_cast(enemy.x1); + float b1_y = static_cast(enemy.y1); + float b2_x = static_cast(enemy.x2); + float b2_y = static_cast(enemy.y2); - // Línea de boundary1 a posición inicial - game_surface->drawLine(b1_cx, b1_cy, init_cx, init_cy, COLOR_ROUTE); - // Línea de posición inicial a boundary2 - game_surface->drawLine(init_cx, init_cy, b2_cx, b2_cy, COLOR_ROUTE); + // Si estamos arrastrando una boundary de este enemigo, usar la posición snapped + if (drag_.index == i) { + if (drag_.target == DragTarget::ENEMY_BOUND1) { + b1_x = drag_.snap_x; + b1_y = drag_.snap_y; + } else if (drag_.target == DragTarget::ENEMY_BOUND2) { + b2_x = drag_.snap_x; + b2_y = drag_.snap_y; + } else if (drag_.target == DragTarget::ENEMY_INITIAL) { + init_x = drag_.snap_x; + init_y = drag_.snap_y; + } + } + + // Dibujar líneas de ruta + game_surface->drawLine(b1_x + HALF, b1_y + HALF, init_x + HALF, init_y + HALF, COLOR_ROUTE); + game_surface->drawLine(init_x + HALF, init_y + HALF, b2_x + HALF, b2_y + HALF, COLOR_ROUTE); // Marcadores en las boundaries - renderBoundaryMarker(static_cast(enemy.x1), static_cast(enemy.y1), COLOR_BOUND1); - renderBoundaryMarker(static_cast(enemy.x2), static_cast(enemy.y2), COLOR_BOUND2); + renderBoundaryMarker(b1_x, b1_y, COLOR_BOUND1); + renderBoundaryMarker(b2_x, b2_y, COLOR_BOUND2); } } diff --git a/source/game/editor/map_editor.hpp b/source/game/editor/map_editor.hpp index 4cb5726..187d2a7 100644 --- a/source/game/editor/map_editor.hpp +++ b/source/game/editor/map_editor.hpp @@ -18,12 +18,11 @@ class EditorStatusBar; class MapEditor { public: - static void init(); // [SINGLETON] Crea el objeto - static void destroy(); // [SINGLETON] Destruye el objeto - static auto get() -> MapEditor*; // [SINGLETON] Obtiene el objeto + static void init(); // [SINGLETON] Crea el objeto + static void destroy(); // [SINGLETON] Destruye el objeto + static auto get() -> MapEditor*; // [SINGLETON] Obtiene el objeto - void enter(std::shared_ptr room, std::shared_ptr player, - const std::string& room_path, std::shared_ptr scoreboard_data); + void enter(std::shared_ptr room, std::shared_ptr player, const std::string& room_path, std::shared_ptr scoreboard_data); void exit(); [[nodiscard]] auto isActive() const -> bool { return active_; } @@ -38,26 +37,31 @@ class MapEditor { ~MapEditor(); // Destructor // Tipos para drag & drop - enum class DragTarget { NONE, PLAYER, ENEMY_INITIAL, ENEMY_BOUND1, ENEMY_BOUND2, ITEM }; + enum class DragTarget { NONE, + PLAYER, + ENEMY_INITIAL, + ENEMY_BOUND1, + ENEMY_BOUND2, + ITEM }; struct DragState { DragTarget target{DragTarget::NONE}; - int index{-1}; // Índice del enemigo o item en room_data_ - float offset_x{0.0F}; // Offset entre el cursor y el origen de la entidad al inicio del drag + int index{-1}; // Índice del enemigo o item en room_data_ + float offset_x{0.0F}; // Offset entre el cursor y el origen de la entidad al inicio del drag float offset_y{0.0F}; - float snap_x{0.0F}; // Posición snapped actual (para preview) + float snap_x{0.0F}; // Posición snapped actual (para preview) float snap_y{0.0F}; }; // Métodos internos - void updateMousePosition(); // Convierte coordenadas de ventana a coordenadas de juego y tile - void renderEnemyBoundaries(); // Dibuja marcadores de boundaries y líneas de ruta - void renderBoundaryMarker(float x, float y, Uint8 color); // Dibuja un marcador de boundary en una posición - void renderSelectionHighlight(); // Dibuja highlight del elemento seleccionado/arrastrado - void handleMouseDown(float game_x, float game_y); // Procesa click del ratón (hit test + inicio de drag) - void handleMouseUp(); // Procesa soltar el ratón (commit del drag) - void updateDrag(); // Actualiza la posición snapped durante el drag - static auto snapToGrid(float value) -> float; // Alinea un valor a la cuadrícula de 8x8 + void updateMousePosition(); // Convierte coordenadas de ventana a coordenadas de juego y tile + void renderEnemyBoundaries(); // Dibuja marcadores de boundaries y líneas de ruta + void renderBoundaryMarker(float x, float y, Uint8 color); // Dibuja un marcador de boundary en una posición + void renderSelectionHighlight(); // Dibuja highlight del elemento seleccionado/arrastrado + void handleMouseDown(float game_x, float game_y); // Procesa click del ratón (hit test + inicio de drag) + void handleMouseUp(); // Procesa soltar el ratón (commit del drag) + void updateDrag(); // Actualiza la posición snapped durante el drag + static auto snapToGrid(float value) -> float; // Alinea un valor a la cuadrícula de 8x8 static auto pointInRect(float px, float py, const SDL_FRect& rect) -> bool; // Hit test punto en rectángulo // Estado del editor diff --git a/source/game/entities/enemy.cpp b/source/game/entities/enemy.cpp index 2deef6a..7c2b8b8 100644 --- a/source/game/entities/enemy.cpp +++ b/source/game/entities/enemy.cpp @@ -53,6 +53,20 @@ void Enemy::update(float delta_time) { void Enemy::updateAnimation(float delta_time) { sprite_->animate(delta_time); } + +// Resetea el enemigo a su posición inicial (para editor) +void Enemy::resetToInitialPosition(const Data& data) { + sprite_->setPosX(data.x); + sprite_->setPosY(data.y); + sprite_->setVelX(data.vx); + sprite_->setVelY(data.vy); + + const int FLIP = (should_flip_ && data.vx < 0.0F) ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE; + const int MIRROR = should_mirror_ ? SDL_FLIP_VERTICAL : SDL_FLIP_NONE; + sprite_->setFlip(static_cast(FLIP | MIRROR)); + + collider_ = getRect(); +} #endif // Comprueba si ha llegado al limite del recorrido para darse media vuelta diff --git a/source/game/entities/enemy.hpp b/source/game/entities/enemy.hpp index 34ff91f..8a9a5a1 100644 --- a/source/game/entities/enemy.hpp +++ b/source/game/entities/enemy.hpp @@ -30,7 +30,8 @@ class Enemy { void render(); // Pinta el enemigo en pantalla void update(float delta_time); // Actualiza las variables del objeto #ifdef _DEBUG - void updateAnimation(float delta_time); // Solo actualiza la animación sin mover al enemigo + void updateAnimation(float delta_time); // Solo actualiza la animación sin mover al enemigo + void resetToInitialPosition(const Data& data); // Resetea el enemigo a su posición inicial (para editor) #endif auto getRect() -> SDL_FRect; // Devuelve el rectangulo que contiene al enemigo diff --git a/source/game/entities/item.cpp b/source/game/entities/item.cpp index 642a2ba..b7b5c67 100644 --- a/source/game/entities/item.cpp +++ b/source/game/entities/item.cpp @@ -41,6 +41,14 @@ auto Item::getPos() -> SDL_FPoint { // NOLINT(readability-convert-member-functi return P; } +#ifdef _DEBUG +// Establece la posición del item (para editor) +void Item::setPosition(float x, float y) { + sprite_->setPosition(x, y); + collider_ = sprite_->getRect(); +} +#endif + // Asigna los colores del objeto void Item::setColors(Uint8 col1, Uint8 col2) { // Reinicializa el vector de colores diff --git a/source/game/entities/item.hpp b/source/game/entities/item.hpp index 43ecf6c..804fb4f 100644 --- a/source/game/entities/item.hpp +++ b/source/game/entities/item.hpp @@ -29,6 +29,9 @@ class Item { auto getCollider() -> SDL_FRect& { return collider_; } // Obtiene el rectangulo de colision del objeto auto getPos() -> SDL_FPoint; // Obtiene su ubicación void setColors(Uint8 col1, Uint8 col2); // Asigna los colores del objeto +#ifdef _DEBUG + void setPosition(float x, float y); // Establece la posición del item (para editor) +#endif private: static constexpr float ITEM_SIZE = 8.0F; // Tamaño del item en pixels diff --git a/source/game/gameplay/enemy_manager.cpp b/source/game/gameplay/enemy_manager.cpp index d4e1b8b..a5c1dbe 100644 --- a/source/game/gameplay/enemy_manager.cpp +++ b/source/game/gameplay/enemy_manager.cpp @@ -48,6 +48,24 @@ void EnemyManager::updateAnimations(float delta_time) { enemy->updateAnimation(delta_time); } } + +// Resetea todos los enemigos a su posición inicial +void EnemyManager::resetPositions(const std::vector& enemy_data) { + const int COUNT = std::min(static_cast(enemies_.size()), static_cast(enemy_data.size())); + for (int i = 0; i < COUNT; ++i) { + enemies_[i]->resetToInitialPosition(enemy_data[i]); + } +} + +// Número de enemigos +auto EnemyManager::getCount() const -> int { + return static_cast(enemies_.size()); +} + +// Acceso a un enemigo por índice +auto EnemyManager::getEnemy(int index) -> std::shared_ptr& { + return enemies_.at(index); +} #endif // Comprueba si hay colisión con algún enemigo diff --git a/source/game/gameplay/enemy_manager.hpp b/source/game/gameplay/enemy_manager.hpp index f4b2bc7..3cc4399 100644 --- a/source/game/gameplay/enemy_manager.hpp +++ b/source/game/gameplay/enemy_manager.hpp @@ -5,7 +5,7 @@ #include // Para shared_ptr #include // Para vector -class Enemy; +#include "game/entities/enemy.hpp" // Para Enemy, Enemy::Data /** * @brief Gestor de enemigos de una habitación @@ -41,7 +41,10 @@ class EnemyManager { auto checkCollision(SDL_FRect& rect) -> bool; // Comprueba si hay colisión con algún enemigo #ifdef _DEBUG - void updateAnimations(float delta_time); // Solo actualiza animaciones sin mover enemigos + void updateAnimations(float delta_time); // Solo actualiza animaciones sin mover enemigos + void resetPositions(const std::vector& enemy_data); // Resetea todos los enemigos a su posición inicial + [[nodiscard]] auto getCount() const -> int; // Número de enemigos + auto getEnemy(int index) -> std::shared_ptr&; // Acceso a un enemigo por índice #endif private: diff --git a/source/game/gameplay/item_manager.hpp b/source/game/gameplay/item_manager.hpp index 567bc7e..0fd41bf 100644 --- a/source/game/gameplay/item_manager.hpp +++ b/source/game/gameplay/item_manager.hpp @@ -6,9 +6,8 @@ #include // Para string #include // Para vector -#include "scoreboard.hpp" // Para Scoreboard::Data - -class Item; +#include "game/entities/item.hpp" // Para Item, Item::Data +#include "scoreboard.hpp" // Para Scoreboard::Data /** * @brief Gestor de items de una habitación @@ -47,6 +46,11 @@ class ItemManager { // Estado void setPaused(bool paused); // Pausa/despausa todos los items +#ifdef _DEBUG + [[nodiscard]] auto getCount() const -> int { return static_cast(items_.size()); } // Número de items + auto getItem(int index) -> std::shared_ptr& { return items_.at(index); } // Acceso a un item por índice +#endif + // Detección de colisiones /** * @brief Comprueba si hay colisión con algún item diff --git a/source/game/gameplay/room.cpp b/source/game/gameplay/room.cpp index 1e52e12..a1fa827 100644 --- a/source/game/gameplay/room.cpp +++ b/source/game/gameplay/room.cpp @@ -128,6 +128,11 @@ void Room::updateEditorMode(float delta_time) { enemy_manager_->updateAnimations(delta_time); item_manager_->update(delta_time); } + +// Resetea enemigos a posiciones iniciales (para editor de mapas) +void Room::resetEnemyPositions(const std::vector& enemy_data) { + enemy_manager_->resetPositions(enemy_data); +} #endif // Actualiza las variables y objetos de la habitación diff --git a/source/game/gameplay/room.hpp b/source/game/gameplay/room.hpp index 241adbb..06531ac 100644 --- a/source/game/gameplay/room.hpp +++ b/source/game/gameplay/room.hpp @@ -69,8 +69,11 @@ class Room { void renderEnemies(); // Dibuja los enemigos en pantalla void renderItems(); // Dibuja los objetos en pantalla #ifdef _DEBUG - void redrawMap(); // Redibuja el mapa (para actualizar modo debug) - void updateEditorMode(float delta_time); // Actualiza animaciones sin mover enemigos (para editor) + void redrawMap(); // Redibuja el mapa (para actualizar modo debug) + void updateEditorMode(float delta_time); // Actualiza animaciones sin mover enemigos (para editor) + void resetEnemyPositions(const std::vector& enemy_data); // Resetea enemigos a posiciones iniciales + auto getEnemyManager() -> EnemyManager* { return enemy_manager_.get(); } // Acceso al gestor de enemigos (para editor) + auto getItemManager() -> ItemManager* { return item_manager_.get(); } // Acceso al gestor de items (para editor) #endif void update(float delta_time); // Actualiza las variables y objetos de la habitación auto getRoom(Border border) -> std::string; // Devuelve la cadena del fichero de la habitación contigua segun el borde diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index 3093864..976d49e 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -32,8 +32,8 @@ #include "utils/utils.hpp" // Para PaletteColor, stringToColor #ifdef _DEBUG -#include "core/system/debug.hpp" // Para Debug -#include "game/editor/map_editor.hpp" // Para MapEditor +#include "core/system/debug.hpp" // Para Debug +#include "game/editor/map_editor.hpp" // Para MapEditor #endif // Constructor