treballant en el minimapa
This commit is contained in:
@@ -101,6 +101,7 @@ set(APP_SOURCES
|
|||||||
source/game/editor/editor_statusbar.cpp
|
source/game/editor/editor_statusbar.cpp
|
||||||
source/game/editor/room_saver.cpp
|
source/game/editor/room_saver.cpp
|
||||||
source/game/editor/tile_picker.cpp
|
source/game/editor/tile_picker.cpp
|
||||||
|
source/game/editor/mini_map.cpp
|
||||||
|
|
||||||
# Game - UI
|
# Game - UI
|
||||||
source/game/ui/console.cpp
|
source/game/ui/console.cpp
|
||||||
|
|||||||
@@ -100,6 +100,13 @@ auto MapEditor::showGrid(bool show) -> std::string {
|
|||||||
return show ? "Grid ON" : "Grid OFF";
|
return show ? "Grid ON" : "Grid OFF";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MapEditor::toggleMiniMap() {
|
||||||
|
if (!mini_map_) {
|
||||||
|
mini_map_ = std::make_unique<MiniMap>();
|
||||||
|
}
|
||||||
|
mini_map_visible_ = !mini_map_visible_;
|
||||||
|
}
|
||||||
|
|
||||||
// Entra en modo editor
|
// Entra en modo editor
|
||||||
void MapEditor::enter(std::shared_ptr<Room> room, std::shared_ptr<Player> player, const std::string& room_path, std::shared_ptr<Scoreboard::Data> scoreboard_data) {
|
void MapEditor::enter(std::shared_ptr<Room> room, std::shared_ptr<Player> player, const std::string& room_path, std::shared_ptr<Scoreboard::Data> scoreboard_data) {
|
||||||
if (active_) { return; }
|
if (active_) { return; }
|
||||||
@@ -285,9 +292,11 @@ void MapEditor::render() {
|
|||||||
// Renderizar highlight de selección (encima de los sprites)
|
// Renderizar highlight de selección (encima de los sprites)
|
||||||
renderSelectionHighlight();
|
renderSelectionHighlight();
|
||||||
|
|
||||||
// Tile picker (encima de todo en el play area)
|
// Tile picker o mini mapa (encima de todo en el play area)
|
||||||
if (tile_picker_.isOpen()) {
|
if (tile_picker_.isOpen()) {
|
||||||
tile_picker_.render();
|
tile_picker_.render();
|
||||||
|
} else if (mini_map_visible_ && mini_map_) {
|
||||||
|
mini_map_->render(room_path_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renderizar barra de estado del editor (reemplaza al scoreboard)
|
// Renderizar barra de estado del editor (reemplaza al scoreboard)
|
||||||
@@ -304,6 +313,20 @@ void MapEditor::handleEvent(const SDL_Event& event) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Si el mini mapa está visible, cerrarlo con click o ESC
|
||||||
|
if (mini_map_visible_) {
|
||||||
|
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN ||
|
||||||
|
(event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_ESCAPE)) {
|
||||||
|
mini_map_visible_ = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_M) {
|
||||||
|
mini_map_visible_ = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return; // Bloquear otros eventos mientras el minimapa está visible
|
||||||
|
}
|
||||||
|
|
||||||
// ESC: desactivar brush
|
// ESC: desactivar brush
|
||||||
if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_ESCAPE && brush_tile_ != NO_BRUSH) {
|
if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_ESCAPE && brush_tile_ != NO_BRUSH) {
|
||||||
brush_tile_ = NO_BRUSH;
|
brush_tile_ = NO_BRUSH;
|
||||||
@@ -316,6 +339,12 @@ void MapEditor::handleEvent(const SDL_Event& event) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// M: toggle mini mapa
|
||||||
|
if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_M && static_cast<int>(event.key.repeat) == 0) {
|
||||||
|
toggleMiniMap();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Click derecho: abrir TilePicker del mapa
|
// Click derecho: abrir TilePicker del mapa
|
||||||
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN && event.button.button == SDL_BUTTON_RIGHT) {
|
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN && event.button.button == SDL_BUTTON_RIGHT) {
|
||||||
// Deseleccionar entidades
|
// Deseleccionar entidades
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
|
|
||||||
#include "external/fkyaml_node.hpp" // Para fkyaml::node
|
#include "external/fkyaml_node.hpp" // Para fkyaml::node
|
||||||
|
#include "game/editor/mini_map.hpp" // Para MiniMap
|
||||||
#include "game/editor/tile_picker.hpp" // Para TilePicker
|
#include "game/editor/tile_picker.hpp" // Para TilePicker
|
||||||
#include "game/entities/enemy.hpp" // Para Enemy::Data
|
#include "game/entities/enemy.hpp" // Para Enemy::Data
|
||||||
#include "game/entities/item.hpp" // Para Item::Data
|
#include "game/entities/item.hpp" // Para Item::Data
|
||||||
@@ -47,6 +48,7 @@ class MapEditor {
|
|||||||
auto showInfo(bool show) -> std::string;
|
auto showInfo(bool show) -> std::string;
|
||||||
auto showGrid(bool show) -> std::string;
|
auto showGrid(bool show) -> std::string;
|
||||||
[[nodiscard]] auto isGridEnabled() const -> bool { return settings_.grid; }
|
[[nodiscard]] auto isGridEnabled() const -> bool { return settings_.grid; }
|
||||||
|
void toggleMiniMap();
|
||||||
|
|
||||||
// Comandos para items
|
// Comandos para items
|
||||||
auto setItemProperty(const std::string& property, const std::string& value) -> std::string;
|
auto setItemProperty(const std::string& property, const std::string& value) -> std::string;
|
||||||
@@ -130,8 +132,10 @@ class MapEditor {
|
|||||||
// Barra de estado del editor
|
// Barra de estado del editor
|
||||||
std::unique_ptr<EditorStatusBar> statusbar_;
|
std::unique_ptr<EditorStatusBar> statusbar_;
|
||||||
|
|
||||||
// Tile picker (para seleccionar tiles de un tileset)
|
// Tile picker y mini mapa
|
||||||
TilePicker tile_picker_;
|
TilePicker tile_picker_;
|
||||||
|
std::unique_ptr<MiniMap> mini_map_;
|
||||||
|
bool mini_map_visible_{false};
|
||||||
|
|
||||||
// Estado del ratón
|
// Estado del ratón
|
||||||
float mouse_game_x_{0.0F};
|
float mouse_game_x_{0.0F};
|
||||||
|
|||||||
298
source/game/editor/mini_map.cpp
Normal file
298
source/game/editor/mini_map.cpp
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
#ifdef _DEBUG
|
||||||
|
|
||||||
|
#include "game/editor/mini_map.hpp"
|
||||||
|
|
||||||
|
#include <algorithm> // Para std::max, std::min
|
||||||
|
#include <array> // Para std::array
|
||||||
|
#include <iostream> // Para cout
|
||||||
|
#include <map> // Para std::map
|
||||||
|
#include <queue> // Para queue (BFS)
|
||||||
|
#include <set> // Para set
|
||||||
|
|
||||||
|
#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/gameplay/room.hpp" // Para Room::Data
|
||||||
|
#include "utils/defines.hpp" // Para Tile::SIZE, PlayArea
|
||||||
|
#include "utils/utils.hpp" // Para stringToColor
|
||||||
|
|
||||||
|
// Constructor: construye todo el minimapa
|
||||||
|
MiniMap::MiniMap() {
|
||||||
|
buildTileColorTable("standard.gif");
|
||||||
|
layoutRooms();
|
||||||
|
buildRoomSurfaces();
|
||||||
|
composeFinalSurface();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Analiza el tileset y crea tabla: tile_index → color predominante
|
||||||
|
void MiniMap::buildTileColorTable(const std::string& tileset_name) {
|
||||||
|
auto tileset = Resource::Cache::get()->getSurface(tileset_name);
|
||||||
|
if (!tileset) { return; }
|
||||||
|
|
||||||
|
tileset_width_ = static_cast<int>(tileset->getWidth()) / Tile::SIZE;
|
||||||
|
int tileset_height = static_cast<int>(tileset->getHeight()) / Tile::SIZE;
|
||||||
|
int total_tiles = tileset_width_ * tileset_height;
|
||||||
|
|
||||||
|
tile_colors_.resize(total_tiles, 0);
|
||||||
|
|
||||||
|
for (int tile = 0; tile < total_tiles; ++tile) {
|
||||||
|
int tile_x = (tile % tileset_width_) * Tile::SIZE;
|
||||||
|
int tile_y = (tile / tileset_width_) * Tile::SIZE;
|
||||||
|
|
||||||
|
// Contar frecuencia de cada color en el tile (ignorar transparente=255 y negro=0)
|
||||||
|
std::array<int, 256> freq{};
|
||||||
|
for (int y = 0; y < Tile::SIZE; ++y) {
|
||||||
|
for (int x = 0; x < Tile::SIZE; ++x) {
|
||||||
|
Uint8 pixel = tileset->getPixel(tile_x + x, tile_y + y);
|
||||||
|
if (pixel != 0 && pixel != 255) {
|
||||||
|
freq[pixel]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encontrar el color más frecuente
|
||||||
|
Uint8 best_color = 0;
|
||||||
|
int best_count = 0;
|
||||||
|
for (int c = 1; c < 256; ++c) {
|
||||||
|
if (freq[c] > best_count) {
|
||||||
|
best_count = freq[c];
|
||||||
|
best_color = static_cast<Uint8>(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tile_colors_[tile] = best_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Posiciona las rooms en un grid usando BFS desde las conexiones
|
||||||
|
void MiniMap::layoutRooms() {
|
||||||
|
auto& rooms = Resource::Cache::get()->getRooms();
|
||||||
|
if (rooms.empty()) { return; }
|
||||||
|
|
||||||
|
// Mapa de nombre → Room::Data
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<Room::Data>> room_map;
|
||||||
|
for (const auto& r : rooms) {
|
||||||
|
room_map[r.name] = r.room;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BFS para posicionar rooms
|
||||||
|
std::set<std::string> visited;
|
||||||
|
std::queue<std::pair<std::string, GridPos>> bfs;
|
||||||
|
|
||||||
|
// Empezar por la primera room
|
||||||
|
const std::string& start = rooms[0].name;
|
||||||
|
bfs.push({start, {0, 0}});
|
||||||
|
visited.insert(start);
|
||||||
|
|
||||||
|
// Grid ocupado: posición → nombre de room
|
||||||
|
std::map<std::pair<int, int>, std::string> grid_occupied;
|
||||||
|
|
||||||
|
while (!bfs.empty()) {
|
||||||
|
auto [name, pos] = bfs.front();
|
||||||
|
bfs.pop();
|
||||||
|
|
||||||
|
auto key = std::make_pair(pos.x, pos.y);
|
||||||
|
if (grid_occupied.contains(key)) { continue; }
|
||||||
|
|
||||||
|
grid_occupied[key] = name;
|
||||||
|
room_positions_[name] = RoomMini{.surface = nullptr, .pos = pos};
|
||||||
|
|
||||||
|
auto it = room_map.find(name);
|
||||||
|
if (it == room_map.end()) { continue; }
|
||||||
|
const auto& data = it->second;
|
||||||
|
|
||||||
|
// Vecinos: up, down, left, right
|
||||||
|
struct Neighbor {
|
||||||
|
std::string room;
|
||||||
|
int dx, dy;
|
||||||
|
};
|
||||||
|
std::array<Neighbor, 4> neighbors = {{
|
||||||
|
{data->upper_room, 0, -1},
|
||||||
|
{data->lower_room, 0, 1},
|
||||||
|
{data->left_room, -1, 0},
|
||||||
|
{data->right_room, 1, 0},
|
||||||
|
}};
|
||||||
|
|
||||||
|
for (const auto& [neighbor_name, dx, dy] : neighbors) {
|
||||||
|
if (neighbor_name == "0" || neighbor_name.empty()) { continue; }
|
||||||
|
if (visited.contains(neighbor_name)) { continue; }
|
||||||
|
|
||||||
|
GridPos neighbor_pos = {pos.x + dx, pos.y + dy};
|
||||||
|
auto nkey = std::make_pair(neighbor_pos.x, neighbor_pos.y);
|
||||||
|
if (!grid_occupied.contains(nkey)) {
|
||||||
|
visited.insert(neighbor_name);
|
||||||
|
bfs.push({neighbor_name, neighbor_pos});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calcular bounds del grid
|
||||||
|
min_grid_x_ = 0;
|
||||||
|
min_grid_y_ = 0;
|
||||||
|
int max_grid_x = 0;
|
||||||
|
int max_grid_y = 0;
|
||||||
|
for (const auto& [name, mini] : room_positions_) {
|
||||||
|
min_grid_x_ = std::min(min_grid_x_, mini.pos.x);
|
||||||
|
min_grid_y_ = std::min(min_grid_y_, mini.pos.y);
|
||||||
|
max_grid_x = std::max(max_grid_x, mini.pos.x);
|
||||||
|
max_grid_y = std::max(max_grid_y, mini.pos.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cols = max_grid_x - min_grid_x_ + 1;
|
||||||
|
int rows = max_grid_y - min_grid_y_ + 1;
|
||||||
|
map_width_ = cols * (CELL_W + GAP) - GAP + PADDING * 2;
|
||||||
|
map_height_ = rows * (CELL_H + GAP) - GAP + PADDING * 2;
|
||||||
|
|
||||||
|
std::cout << "MiniMap: " << room_positions_.size() << " rooms, grid " << cols << "x" << rows
|
||||||
|
<< " → " << map_width_ << "x" << map_height_ << " px\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Genera una mini-surface de 32x16 por room
|
||||||
|
void MiniMap::buildRoomSurfaces() {
|
||||||
|
for (auto& [name, mini] : room_positions_) {
|
||||||
|
mini.surface = getRoomMiniSurface(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Genera la mini-surface de una room: 1 pixel por tile, color predominante
|
||||||
|
auto MiniMap::getRoomMiniSurface(const std::string& room_name) -> std::shared_ptr<Surface> {
|
||||||
|
auto room_data = Resource::Cache::get()->getRoom(room_name);
|
||||||
|
if (!room_data) { return nullptr; }
|
||||||
|
|
||||||
|
auto surface = std::make_shared<Surface>(ROOM_W, ROOM_H);
|
||||||
|
|
||||||
|
auto prev = Screen::get()->getRendererSurface();
|
||||||
|
Screen::get()->setRendererSurface(surface);
|
||||||
|
surface->clear(stringToColor(room_data->bg_color));
|
||||||
|
|
||||||
|
const auto& tile_map = room_data->tile_map;
|
||||||
|
for (int y = 0; y < ROOM_H; ++y) {
|
||||||
|
for (int x = 0; x < ROOM_W; ++x) {
|
||||||
|
int index = y * ROOM_W + x;
|
||||||
|
if (index >= static_cast<int>(tile_map.size())) { continue; }
|
||||||
|
|
||||||
|
int tile = tile_map[index];
|
||||||
|
if (tile < 0 || tile >= static_cast<int>(tile_colors_.size())) { continue; }
|
||||||
|
|
||||||
|
Uint8 color = tile_colors_[tile];
|
||||||
|
if (color != 0) {
|
||||||
|
surface->putPixel(x, y, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Screen::get()->setRendererSurface(prev);
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compone la surface final con todas las rooms posicionadas
|
||||||
|
void MiniMap::composeFinalSurface() {
|
||||||
|
if (map_width_ <= 0 || map_height_ <= 0) { return; }
|
||||||
|
|
||||||
|
// Surface un poco más grande para la sombra del borde inferior/derecho
|
||||||
|
map_surface_ = std::make_shared<Surface>(map_width_ + SHADOW_OFFSET, map_height_ + SHADOW_OFFSET);
|
||||||
|
|
||||||
|
auto prev = Screen::get()->getRendererSurface();
|
||||||
|
Screen::get()->setRendererSurface(map_surface_);
|
||||||
|
|
||||||
|
// 1. Fondo general
|
||||||
|
map_surface_->clear(COLOR_BACKGROUND);
|
||||||
|
|
||||||
|
// 2. Líneas de conexión entre rooms (debajo de todo)
|
||||||
|
drawConnections();
|
||||||
|
|
||||||
|
// 3. Sombras de las rooms (desplazadas 1px abajo-derecha)
|
||||||
|
for (const auto& [name, mini] : room_positions_) {
|
||||||
|
if (!mini.surface) { continue; }
|
||||||
|
int px = cellPixelX(mini.pos.x) + SHADOW_OFFSET;
|
||||||
|
int py = cellPixelY(mini.pos.y) + SHADOW_OFFSET;
|
||||||
|
SDL_FRect shadow = {.x = static_cast<float>(px), .y = static_cast<float>(py),
|
||||||
|
.w = static_cast<float>(CELL_W), .h = static_cast<float>(CELL_H)};
|
||||||
|
map_surface_->fillRect(&shadow, COLOR_SHADOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Borde negro de cada room + contenido de la room
|
||||||
|
for (const auto& [name, mini] : room_positions_) {
|
||||||
|
if (!mini.surface) { continue; }
|
||||||
|
int px = cellPixelX(mini.pos.x);
|
||||||
|
int py = cellPixelY(mini.pos.y);
|
||||||
|
|
||||||
|
// Borde negro (la celda entera)
|
||||||
|
SDL_FRect cell = {.x = static_cast<float>(px), .y = static_cast<float>(py),
|
||||||
|
.w = static_cast<float>(CELL_W), .h = static_cast<float>(CELL_H)};
|
||||||
|
map_surface_->fillRect(&cell, COLOR_ROOM_BORDER);
|
||||||
|
|
||||||
|
// Miniroom dentro del borde
|
||||||
|
SDL_FRect dst = {.x = static_cast<float>(px + BORDER), .y = static_cast<float>(py + BORDER),
|
||||||
|
.w = static_cast<float>(ROOM_W), .h = static_cast<float>(ROOM_H)};
|
||||||
|
mini.surface->render(nullptr, &dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
Screen::get()->setRendererSurface(prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dibuja las líneas de conexión entre rooms vecinas
|
||||||
|
void MiniMap::drawConnections() {
|
||||||
|
for (const auto& [name, mini] : room_positions_) {
|
||||||
|
auto room_data = Resource::Cache::get()->getRoom(name);
|
||||||
|
if (!room_data) { continue; }
|
||||||
|
|
||||||
|
int px = cellPixelX(mini.pos.x);
|
||||||
|
int py = cellPixelY(mini.pos.y);
|
||||||
|
|
||||||
|
// Conexión derecha: línea horizontal desde el borde derecho de esta room hasta el borde izquierdo de la vecina
|
||||||
|
if (room_data->right_room != "0" && !room_data->right_room.empty() && room_positions_.contains(room_data->right_room)) {
|
||||||
|
int x1 = px + CELL_W;
|
||||||
|
int y_mid = py + CELL_H / 2;
|
||||||
|
SDL_FRect line = {.x = static_cast<float>(x1), .y = static_cast<float>(y_mid),
|
||||||
|
.w = static_cast<float>(GAP), .h = 1.0F};
|
||||||
|
map_surface_->fillRect(&line, COLOR_CONNECTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conexión abajo: línea vertical desde el borde inferior de esta room hasta el borde superior de la vecina
|
||||||
|
if (room_data->lower_room != "0" && !room_data->lower_room.empty() && room_positions_.contains(room_data->lower_room)) {
|
||||||
|
int x_mid = px + CELL_W / 2;
|
||||||
|
int y1 = py + CELL_H;
|
||||||
|
SDL_FRect line = {.x = static_cast<float>(x_mid), .y = static_cast<float>(y1),
|
||||||
|
.w = 1.0F, .h = static_cast<float>(GAP)};
|
||||||
|
map_surface_->fillRect(&line, COLOR_CONNECTION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renderiza el minimapa centrado en la room actual
|
||||||
|
void MiniMap::render(const std::string& current_room) {
|
||||||
|
if (!map_surface_) { return; }
|
||||||
|
|
||||||
|
auto game_surface = Screen::get()->getRendererSurface();
|
||||||
|
if (!game_surface) { return; }
|
||||||
|
|
||||||
|
// Fondo negro en el play area
|
||||||
|
SDL_FRect bg = {.x = 0, .y = 0, .w = static_cast<float>(PlayArea::WIDTH), .h = static_cast<float>(PlayArea::HEIGHT)};
|
||||||
|
game_surface->fillRect(&bg, 0);
|
||||||
|
|
||||||
|
// Centrar el minimapa en el play area, centrado en la room actual
|
||||||
|
auto it = room_positions_.find(current_room);
|
||||||
|
if (it == room_positions_.end()) { return; }
|
||||||
|
const auto& current_pos = it->second.pos;
|
||||||
|
|
||||||
|
int room_cx = cellPixelX(current_pos.x) + CELL_W / 2;
|
||||||
|
int room_cy = cellPixelY(current_pos.y) + CELL_H / 2;
|
||||||
|
|
||||||
|
int offset_x = PlayArea::WIDTH / 2 - room_cx;
|
||||||
|
int offset_y = PlayArea::HEIGHT / 2 - room_cy;
|
||||||
|
|
||||||
|
// Renderizar la surface del minimapa con offset
|
||||||
|
SDL_FRect dst = {.x = static_cast<float>(offset_x), .y = static_cast<float>(offset_y),
|
||||||
|
.w = static_cast<float>(map_width_ + SHADOW_OFFSET), .h = static_cast<float>(map_height_ + SHADOW_OFFSET)};
|
||||||
|
map_surface_->render(nullptr, &dst);
|
||||||
|
|
||||||
|
// Highlight de la room actual (borde bright_white alrededor de la celda)
|
||||||
|
float cur_x = static_cast<float>(offset_x + cellPixelX(current_pos.x));
|
||||||
|
float cur_y = static_cast<float>(offset_y + cellPixelY(current_pos.y));
|
||||||
|
SDL_FRect highlight = {.x = cur_x - 1, .y = cur_y - 1,
|
||||||
|
.w = static_cast<float>(CELL_W + 2), .h = static_cast<float>(CELL_H + 2)};
|
||||||
|
game_surface->drawRectBorder(&highlight, stringToColor("bright_white"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _DEBUG
|
||||||
85
source/game/editor/mini_map.hpp
Normal file
85
source/game/editor/mini_map.hpp
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
#include <memory> // Para shared_ptr
|
||||||
|
#include <string> // Para string
|
||||||
|
#include <unordered_map> // Para unordered_map
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
|
class Surface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Minimapa global del juego para el editor
|
||||||
|
*
|
||||||
|
* Genera una vista en miniatura de todas las habitaciones del juego,
|
||||||
|
* posicionadas según sus conexiones.
|
||||||
|
* Cada tile del mapa se representa como 1 pixel del color predominante de ese tile.
|
||||||
|
* Resultado: cada room = 32x16 pixels.
|
||||||
|
*/
|
||||||
|
class MiniMap {
|
||||||
|
public:
|
||||||
|
MiniMap();
|
||||||
|
~MiniMap() = default;
|
||||||
|
|
||||||
|
void render(const std::string& current_room); // Dibuja el minimapa centrado en la room actual
|
||||||
|
[[nodiscard]] auto isReady() const -> bool { return !room_positions_.empty(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Posición de una room en el grid del minimapa
|
||||||
|
struct GridPos {
|
||||||
|
int x{0};
|
||||||
|
int y{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Una room renderizada
|
||||||
|
struct RoomMini {
|
||||||
|
std::shared_ptr<Surface> surface; // 32x16 pixels
|
||||||
|
GridPos pos; // Posición en el grid
|
||||||
|
};
|
||||||
|
|
||||||
|
void buildTileColorTable(const std::string& tileset_name);
|
||||||
|
void buildRoomSurfaces();
|
||||||
|
void layoutRooms();
|
||||||
|
void composeFinalSurface();
|
||||||
|
auto getRoomMiniSurface(const std::string& room_name) -> std::shared_ptr<Surface>;
|
||||||
|
void drawConnections();
|
||||||
|
auto cellPixelX(int grid_x) const -> int { return PADDING + (grid_x - min_grid_x_) * (CELL_W + GAP); }
|
||||||
|
auto cellPixelY(int grid_y) const -> int { return PADDING + (grid_y - min_grid_y_) * (CELL_H + GAP); }
|
||||||
|
|
||||||
|
// Tabla de color predominante por tile index
|
||||||
|
std::vector<Uint8> tile_colors_; // tile_index → palette color index
|
||||||
|
int tileset_width_{0}; // Ancho del tileset en tiles
|
||||||
|
|
||||||
|
// Rooms renderizadas y posicionadas
|
||||||
|
std::unordered_map<std::string, RoomMini> room_positions_;
|
||||||
|
|
||||||
|
// Surface final compuesta
|
||||||
|
std::shared_ptr<Surface> map_surface_;
|
||||||
|
int map_width_{0}; // Ancho en pixels
|
||||||
|
int map_height_{0}; // Alto en pixels
|
||||||
|
|
||||||
|
// Offset para normalizar coordenadas
|
||||||
|
int min_grid_x_{0};
|
||||||
|
int min_grid_y_{0};
|
||||||
|
|
||||||
|
// Constantes
|
||||||
|
static constexpr int ROOM_W = 32; // Ancho de una room en pixels del minimapa
|
||||||
|
static constexpr int ROOM_H = 16; // Alto de una room en pixels del minimapa
|
||||||
|
static constexpr int BORDER = 1; // Borde alrededor de cada room
|
||||||
|
static constexpr int CELL_W = ROOM_W + BORDER * 2; // Room + borde
|
||||||
|
static constexpr int CELL_H = ROOM_H + BORDER * 2;
|
||||||
|
static constexpr int GAP = 4; // Separación entre celdas
|
||||||
|
static constexpr int SHADOW_OFFSET = 1; // Desplazamiento de la sombra
|
||||||
|
static constexpr int PADDING = 4; // Padding alrededor del minimapa
|
||||||
|
|
||||||
|
// Colores del minimapa (índices de paleta)
|
||||||
|
static constexpr Uint8 COLOR_BACKGROUND = 2; // Fondo general (blue, si border es 0 usamos 2)
|
||||||
|
static constexpr Uint8 COLOR_ROOM_BORDER = 0; // Borde de cada miniroom
|
||||||
|
static constexpr Uint8 COLOR_SHADOW = 1; // Sombra de cada miniroom
|
||||||
|
static constexpr Uint8 COLOR_CONNECTION = 14; // Líneas de conexión entre rooms
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _DEBUG
|
||||||
Reference in New Issue
Block a user