mes retocs a minimap. arreglat el calcul dels minipixels en els tiles amb transparent
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include "game/editor/mini_map.hpp"
|
||||
|
||||
#include <algorithm> // Para std::max, std::min
|
||||
#include <cmath> // Para std::floor
|
||||
#include <array> // Para std::array
|
||||
#include <iostream> // Para cout
|
||||
#include <map> // Para std::map
|
||||
@@ -37,6 +38,7 @@ void MiniMap::buildTileColorTable(const std::string& tileset_name) {
|
||||
if (!tileset) { return; }
|
||||
|
||||
tileset_width_ = static_cast<int>(tileset->getWidth()) / Tile::SIZE;
|
||||
tileset_transparent_ = tileset->getTransparentColor();
|
||||
int tileset_height = static_cast<int>(tileset->getHeight()) / Tile::SIZE;
|
||||
int total_tiles = tileset_width_ * tileset_height;
|
||||
|
||||
@@ -46,21 +48,23 @@ void MiniMap::buildTileColorTable(const std::string& tileset_name) {
|
||||
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)
|
||||
// Contar frecuencia de cada color en el tile (ignorar el color transparente del tileset)
|
||||
Uint8 transparent = tileset->getTransparentColor();
|
||||
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) {
|
||||
if (pixel != transparent) {
|
||||
freq[pixel]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Encontrar el color más frecuente
|
||||
Uint8 best_color = 0;
|
||||
// Encontrar el color más frecuente (transparent = tile vacío, no se pinta)
|
||||
Uint8 best_color = transparent;
|
||||
int best_count = 0;
|
||||
for (int c = 1; c < 256; ++c) {
|
||||
for (int c = 0; c < 256; ++c) {
|
||||
if (c == transparent) { continue; }
|
||||
if (freq[c] > best_count) {
|
||||
best_count = freq[c];
|
||||
best_color = static_cast<Uint8>(c);
|
||||
@@ -182,7 +186,7 @@ auto MiniMap::getRoomMiniSurface(const std::string& room_name) -> std::shared_pt
|
||||
if (tile < 0 || tile >= static_cast<int>(tile_colors_.size())) { continue; }
|
||||
|
||||
Uint8 color = tile_colors_[tile];
|
||||
if (color != 0) {
|
||||
if (color != tileset_transparent_) {
|
||||
surface->putPixel(x, y, color);
|
||||
}
|
||||
}
|
||||
@@ -267,35 +271,125 @@ void MiniMap::drawConnections() {
|
||||
}
|
||||
}
|
||||
|
||||
// Renderiza el minimapa centrado en la room actual
|
||||
// Centra el viewport en una room
|
||||
void MiniMap::centerOnRoom(const std::string& room_name) {
|
||||
auto it = room_positions_.find(room_name);
|
||||
if (it == room_positions_.end()) { return; }
|
||||
const auto& pos = it->second.pos;
|
||||
|
||||
float room_cx = static_cast<float>(cellPixelX(pos.x) + CELL_W / 2);
|
||||
float room_cy = static_cast<float>(cellPixelY(pos.y) + CELL_H / 2);
|
||||
view_x_ = static_cast<float>(PlayArea::WIDTH) / 2.0F - room_cx;
|
||||
view_y_ = static_cast<float>(PlayArea::HEIGHT) / 2.0F - room_cy;
|
||||
}
|
||||
|
||||
// Devuelve el nombre de la room en una posición de pantalla, o vacío si no hay ninguna
|
||||
auto MiniMap::roomAtScreen(float screen_x, float screen_y) -> std::string {
|
||||
// Convertir coordenada de pantalla a coordenada dentro del minimapa
|
||||
float map_x = screen_x - view_x_;
|
||||
float map_y = screen_y - view_y_;
|
||||
|
||||
for (const auto& [name, mini] : room_positions_) {
|
||||
float rx = static_cast<float>(cellPixelX(mini.pos.x));
|
||||
float ry = static_cast<float>(cellPixelY(mini.pos.y));
|
||||
if (map_x >= rx && map_x < rx + CELL_W && map_y >= ry && map_y < ry + CELL_H) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// Renderiza el minimapa
|
||||
void MiniMap::render(const std::string& current_room) {
|
||||
if (!map_surface_) { return; }
|
||||
|
||||
auto game_surface = Screen::get()->getRendererSurface();
|
||||
if (!game_surface) { return; }
|
||||
|
||||
// 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),
|
||||
// Renderizar la surface del minimapa con el viewport actual (alineado a pixel)
|
||||
float vx = std::floor(view_x_);
|
||||
float vy = std::floor(view_y_);
|
||||
SDL_FRect dst = {.x = vx, .y = vy,
|
||||
.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"));
|
||||
// Highlight de la room actual (solo si está completamente visible en el play area)
|
||||
auto it = room_positions_.find(current_room);
|
||||
if (it != room_positions_.end()) {
|
||||
float cur_x = vx + static_cast<float>(cellPixelX(it->second.pos.x)) - 1;
|
||||
float cur_y = vy + static_cast<float>(cellPixelY(it->second.pos.y)) - 1;
|
||||
float cur_w = static_cast<float>(CELL_W + 2);
|
||||
float cur_h = static_cast<float>(CELL_H + 2);
|
||||
if (cur_x >= 0 && cur_y >= 0 && cur_x + cur_w <= PlayArea::WIDTH && cur_y + cur_h <= PlayArea::HEIGHT) {
|
||||
SDL_FRect highlight = {.x = cur_x, .y = cur_y, .w = cur_w, .h = cur_h};
|
||||
game_surface->drawRectBorder(&highlight, stringToColor("bright_white"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Maneja eventos del minimapa (drag para explorar, click para navegar)
|
||||
void MiniMap::handleEvent(const SDL_Event& event, const std::string& current_room) {
|
||||
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN && event.button.button == SDL_BUTTON_LEFT) {
|
||||
// Guardar posición inicial para detectar si es click o drag
|
||||
float mouse_x = 0.0F;
|
||||
float mouse_y = 0.0F;
|
||||
SDL_GetMouseState(&mouse_x, &mouse_y);
|
||||
float render_x = 0.0F;
|
||||
float render_y = 0.0F;
|
||||
SDL_RenderCoordinatesFromWindow(Screen::get()->getRenderer(), mouse_x, mouse_y, &render_x, &render_y);
|
||||
SDL_FRect dst_rect = Screen::get()->getGameSurfaceDstRect();
|
||||
|
||||
dragging_ = true;
|
||||
drag_start_x_ = render_x - dst_rect.x;
|
||||
drag_start_y_ = render_y - dst_rect.y;
|
||||
view_start_x_ = view_x_;
|
||||
view_start_y_ = view_y_;
|
||||
}
|
||||
|
||||
if (event.type == SDL_EVENT_MOUSE_MOTION && dragging_) {
|
||||
float mouse_x = 0.0F;
|
||||
float mouse_y = 0.0F;
|
||||
SDL_GetMouseState(&mouse_x, &mouse_y);
|
||||
float render_x = 0.0F;
|
||||
float render_y = 0.0F;
|
||||
SDL_RenderCoordinatesFromWindow(Screen::get()->getRenderer(), mouse_x, mouse_y, &render_x, &render_y);
|
||||
SDL_FRect dst_rect = Screen::get()->getGameSurfaceDstRect();
|
||||
|
||||
float game_x = render_x - dst_rect.x;
|
||||
float game_y = render_y - dst_rect.y;
|
||||
view_x_ = view_start_x_ + (game_x - drag_start_x_);
|
||||
view_y_ = view_start_y_ + (game_y - drag_start_y_);
|
||||
}
|
||||
|
||||
if (event.type == SDL_EVENT_MOUSE_BUTTON_UP && event.button.button == SDL_BUTTON_LEFT) {
|
||||
if (dragging_) {
|
||||
// Comprobar si fue click (sin mover) o drag
|
||||
float mouse_x = 0.0F;
|
||||
float mouse_y = 0.0F;
|
||||
SDL_GetMouseState(&mouse_x, &mouse_y);
|
||||
float render_x = 0.0F;
|
||||
float render_y = 0.0F;
|
||||
SDL_RenderCoordinatesFromWindow(Screen::get()->getRenderer(), mouse_x, mouse_y, &render_x, &render_y);
|
||||
SDL_FRect dst_rect = Screen::get()->getGameSurfaceDstRect();
|
||||
|
||||
float game_x = render_x - dst_rect.x;
|
||||
float game_y = render_y - dst_rect.y;
|
||||
|
||||
float dx = game_x - drag_start_x_;
|
||||
float dy = game_y - drag_start_y_;
|
||||
bool was_click = (dx * dx + dy * dy) < 4.0F; // Menos de 2px de movimiento = click
|
||||
|
||||
if (was_click) {
|
||||
// Click: navegar a la room bajo el cursor
|
||||
std::string room = roomAtScreen(game_x, game_y);
|
||||
if (!room.empty() && room != current_room && on_navigate) {
|
||||
on_navigate(room);
|
||||
}
|
||||
}
|
||||
|
||||
dragging_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _DEBUG
|
||||
|
||||
Reference in New Issue
Block a user