primera versió del editor de tiles

This commit is contained in:
2026-04-02 16:55:56 +02:00
parent 0d12591925
commit 44b6f6830d
7 changed files with 148 additions and 2 deletions

View File

@@ -81,6 +81,9 @@ void MapEditor::enter(std::shared_ptr<Room> room, std::shared_ptr<Player> player
// Resetear estado // Resetear estado
drag_ = {}; drag_ = {};
selected_enemy_ = -1; selected_enemy_ = -1;
selected_item_ = -1;
brush_tile_ = NO_BRUSH;
painting_ = false;
active_ = true; active_ = true;
std::cout << "MapEditor: ON (room " << room_path_ << ")\n"; std::cout << "MapEditor: ON (room " << room_path_ << ")\n";
@@ -135,7 +138,14 @@ auto MapEditor::revert() -> std::string {
room_->setBgColor(room_data_.bg_color); room_->setBgColor(room_data_.bg_color);
Screen::get()->setBorderColor(stringToColor(room_data_.border_color)); Screen::get()->setBorderColor(stringToColor(room_data_.border_color));
// Restaurar el tilemap completo
for (int i = 0; i < static_cast<int>(room_data_.tile_map.size()); ++i) {
room_->setTile(i, room_data_.tile_map[i]);
}
selected_enemy_ = -1; selected_enemy_ = -1;
selected_item_ = -1;
brush_tile_ = NO_BRUSH;
return "Reverted to original"; return "Reverted to original";
} }
@@ -171,6 +181,17 @@ void MapEditor::update(float delta_time) {
updateDrag(); updateDrag();
} }
// Si estamos pintando tiles, pintar en la posición actual del ratón
if (painting_ && brush_tile_ != NO_BRUSH) {
int tile_index = mouse_tile_y_ * 32 + mouse_tile_x_;
if (tile_index >= 0 && tile_index < static_cast<int>(room_data_.tile_map.size())) {
if (room_data_.tile_map[tile_index] != brush_tile_) {
room_data_.tile_map[tile_index] = brush_tile_;
room_->setTile(tile_index, brush_tile_);
}
}
}
// Actualizar la barra de estado // Actualizar la barra de estado
updateStatusBarInfo(); updateStatusBarInfo();
if (statusbar_) { if (statusbar_) {
@@ -212,10 +233,79 @@ void MapEditor::handleEvent(const SDL_Event& event) {
return; return;
} }
// ESC: desactivar brush
if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_ESCAPE && brush_tile_ != NO_BRUSH) {
brush_tile_ = NO_BRUSH;
return;
}
// E: toggle borrador
if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_E && static_cast<int>(event.key.repeat) == 0) {
brush_tile_ = (brush_tile_ == ERASER_BRUSH) ? NO_BRUSH : ERASER_BRUSH;
return;
}
// Click derecho: abrir TilePicker del mapa
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN && event.button.button == SDL_BUTTON_RIGHT) {
// Deseleccionar entidades
selected_enemy_ = -1;
selected_item_ = -1;
// Tile bajo el cursor como tile actual del picker
int tile_index = mouse_tile_y_ * 32 + mouse_tile_x_;
int current = (tile_index >= 0 && tile_index < static_cast<int>(room_data_.tile_map.size()))
? room_data_.tile_map[tile_index]
: -1;
tile_picker_.on_select = [this](int tile) {
brush_tile_ = tile;
};
tile_picker_.open(room_->getTileSetFile(), current,
stringToColor(room_data_.bg_color));
return;
}
// Click izquierdo
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN && event.button.button == SDL_BUTTON_LEFT) { if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN && event.button.button == SDL_BUTTON_LEFT) {
// Si hay brush activo y no hacemos hit en ninguna entidad → pintar
if (brush_tile_ != NO_BRUSH) {
// Comprobar si hay hit en alguna entidad primero
bool hit_entity = false;
SDL_FRect player_rect = player_->getRect();
if (pointInRect(mouse_game_x_, mouse_game_y_, player_rect)) { hit_entity = true; }
if (!hit_entity) {
auto* enemy_mgr = room_->getEnemyManager();
for (int i = 0; i < enemy_mgr->getCount() && !hit_entity; ++i) {
if (pointInRect(mouse_game_x_, mouse_game_y_, enemy_mgr->getEnemy(i)->getRect())) { hit_entity = true; }
}
}
if (!hit_entity) {
auto* item_mgr = room_->getItemManager();
for (int i = 0; i < item_mgr->getCount() && !hit_entity; ++i) {
if (pointInRect(mouse_game_x_, mouse_game_y_, item_mgr->getItem(i)->getCollider())) { hit_entity = true; }
}
}
if (!hit_entity) {
// Pintar tile y entrar en modo painting
painting_ = true;
int tile_index = mouse_tile_y_ * 32 + mouse_tile_x_;
if (tile_index >= 0 && tile_index < static_cast<int>(room_data_.tile_map.size())) {
room_data_.tile_map[tile_index] = brush_tile_;
room_->setTile(tile_index, brush_tile_);
}
return;
}
}
handleMouseDown(mouse_game_x_, mouse_game_y_); handleMouseDown(mouse_game_x_, mouse_game_y_);
} else if (event.type == SDL_EVENT_MOUSE_BUTTON_UP && event.button.button == SDL_BUTTON_LEFT) { } else if (event.type == SDL_EVENT_MOUSE_BUTTON_UP && event.button.button == SDL_BUTTON_LEFT) {
handleMouseUp(); if (painting_) {
painting_ = false;
autosave();
} else {
handleMouseUp();
}
} }
} }
@@ -640,9 +730,17 @@ void MapEditor::updateStatusBarInfo() {
" itm:" + room_data_.item_color1 + "/" + room_data_.item_color2; " itm:" + room_data_.item_color1 + "/" + room_data_.item_color2;
} }
// Línea 4: brush activo
std::string line4;
if (brush_tile_ == ERASER_BRUSH) {
line4 = "brush: eraser (e)";
} else if (brush_tile_ != NO_BRUSH) {
line4 = "brush: tile " + std::to_string(brush_tile_);
}
statusbar_->setLine2(line2); statusbar_->setLine2(line2);
statusbar_->setLine3(line3); statusbar_->setLine3(line3);
statusbar_->setLine4(""); statusbar_->setLine4(line4);
statusbar_->setLine5(line5); statusbar_->setLine5(line5);
// Actualizar el prompt de la consola según la selección // Actualizar el prompt de la consola según la selección

View File

@@ -93,6 +93,10 @@ class MapEditor {
DragState drag_; DragState drag_;
int selected_enemy_{-1}; // Índice del enemigo seleccionado (-1 = ninguno) int selected_enemy_{-1}; // Índice del enemigo seleccionado (-1 = ninguno)
int selected_item_{-1}; // Índice del item seleccionado (-1 = ninguno) int selected_item_{-1}; // Índice del item seleccionado (-1 = ninguno)
static constexpr int NO_BRUSH = -2; // Sin brush activo
static constexpr int ERASER_BRUSH = -1; // Brush borrador (pinta tile vacío = -1)
int brush_tile_{NO_BRUSH}; // Tile activo para pintar
bool painting_{false}; // true mientras se está pintando con click izquierdo mantenido
// Datos de la habitación // Datos de la habitación
Room::Data room_data_; Room::Data room_data_;

View File

@@ -113,6 +113,7 @@ void TilePicker::open(const std::string& tileset_name, int current_tile,
} }
open_ = true; open_ = true;
updateMousePosition();
} }
// Cierra el picker // Cierra el picker

View File

@@ -134,6 +134,14 @@ void Room::resetEnemyPositions(const std::vector<Enemy::Data>& enemy_data) {
enemy_manager_->resetPositions(enemy_data); enemy_manager_->resetPositions(enemy_data);
} }
// Cambia un tile y repinta la celda (para editor)
void Room::setTile(int index, int tile_value) {
if (index >= 0 && index < static_cast<int>(tile_map_.size())) {
tile_map_[index] = tile_value;
tilemap_renderer_->setTile(index, tile_value);
}
}
// Cambia color de fondo y redibuja el mapa (para editor) // Cambia color de fondo y redibuja el mapa (para editor)
void Room::setBgColor(const std::string& color) { void Room::setBgColor(const std::string& color) {
bg_color_ = color; bg_color_ = color;

View File

@@ -76,6 +76,9 @@ class Room {
auto getItemManager() -> ItemManager* { return item_manager_.get(); } // Acceso al gestor de items (para editor) auto getItemManager() -> ItemManager* { return item_manager_.get(); } // Acceso al gestor de items (para editor)
void setBgColor(const std::string& color); // Cambia color de fondo y redibuja (para editor) void setBgColor(const std::string& color); // Cambia color de fondo y redibuja (para editor)
void setItemColors(const std::string& color1, const std::string& color2); // Cambia colores de items (para editor) void setItemColors(const std::string& color1, const std::string& color2); // Cambia colores de items (para editor)
void setTile(int index, int tile_value); // Cambia un tile y redibuja (para editor)
[[nodiscard]] auto getTileSetFile() const -> const std::string& { return tile_set_file_; }
[[nodiscard]] auto getTileSetWidth() const -> int { return tile_set_width_; }
#endif #endif
void update(float delta_time); // Actualiza las variables y objetos de la habitación 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 auto getRoom(Border border) -> std::string; // Devuelve la cadena del fichero de la habitación contigua segun el borde

View File

@@ -100,6 +100,37 @@ static void renderDebugCollisionSurfaces(const CollisionMap* collision_map) {
void TilemapRenderer::redrawMap(const CollisionMap* collision_map) { void TilemapRenderer::redrawMap(const CollisionMap* collision_map) {
fillMapTexture(collision_map); fillMapTexture(collision_map);
} }
// Cambia un tile y repinta solo esa celda en la map_surface
void TilemapRenderer::setTile(int index, int tile_value) {
if (index < 0 || index >= static_cast<int>(tile_map_.size())) { return; }
tile_map_[index] = tile_value;
int col = index % MAP_WIDTH;
int row = index / MAP_WIDTH;
auto previous_renderer = Screen::get()->getRendererSurface();
Screen::get()->setRendererSurface(map_surface_);
// Borrar la celda con el color de fondo
SDL_FRect cell = {.x = static_cast<float>(col * TILE_SIZE), .y = static_cast<float>(row * TILE_SIZE),
.w = static_cast<float>(TILE_SIZE), .h = static_cast<float>(TILE_SIZE)};
map_surface_->fillRect(&cell, stringToColor(bg_color_));
// Dibujar el nuevo tile (si no es vacío ni animado)
if (tile_value > -1) {
const bool IS_ANIMATED = (tile_value >= 18 * tile_set_width_) && (tile_value < 19 * tile_set_width_);
if (!IS_ANIMATED) {
SDL_FRect clip = {.x = static_cast<float>((tile_value % tile_set_width_) * TILE_SIZE),
.y = static_cast<float>((tile_value / tile_set_width_) * TILE_SIZE),
.w = static_cast<float>(TILE_SIZE), .h = static_cast<float>(TILE_SIZE)};
tileset_surface_->render(col * TILE_SIZE, row * TILE_SIZE, &clip);
}
}
Screen::get()->setRendererSurface(previous_renderer);
}
#endif #endif
// Pinta el mapa estático y debug lines // Pinta el mapa estático y debug lines

View File

@@ -70,6 +70,7 @@ class TilemapRenderer {
*/ */
void redrawMap(const CollisionMap* collision_map); void redrawMap(const CollisionMap* collision_map);
void setBgColor(const std::string& color) { bg_color_ = color; } void setBgColor(const std::string& color) { bg_color_ = color; }
void setTile(int index, int tile_value); // Cambia un tile y repinta esa celda
#endif #endif
/** /**