primera versió del editor de tiles
This commit is contained in:
@@ -81,6 +81,9 @@ void MapEditor::enter(std::shared_ptr<Room> room, std::shared_ptr<Player> player
|
||||
// Resetear estado
|
||||
drag_ = {};
|
||||
selected_enemy_ = -1;
|
||||
selected_item_ = -1;
|
||||
brush_tile_ = NO_BRUSH;
|
||||
painting_ = false;
|
||||
|
||||
active_ = true;
|
||||
std::cout << "MapEditor: ON (room " << room_path_ << ")\n";
|
||||
@@ -135,7 +138,14 @@ auto MapEditor::revert() -> std::string {
|
||||
room_->setBgColor(room_data_.bg_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_item_ = -1;
|
||||
brush_tile_ = NO_BRUSH;
|
||||
return "Reverted to original";
|
||||
}
|
||||
|
||||
@@ -171,6 +181,17 @@ void MapEditor::update(float delta_time) {
|
||||
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
|
||||
updateStatusBarInfo();
|
||||
if (statusbar_) {
|
||||
@@ -212,12 +233,81 @@ void MapEditor::handleEvent(const SDL_Event& event) {
|
||||
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) {
|
||||
// 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_);
|
||||
} else if (event.type == SDL_EVENT_MOUSE_BUTTON_UP && event.button.button == SDL_BUTTON_LEFT) {
|
||||
if (painting_) {
|
||||
painting_ = false;
|
||||
autosave();
|
||||
} else {
|
||||
handleMouseUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Procesa click del ratón: hit test + inicio de drag
|
||||
void MapEditor::handleMouseDown(float game_x, float game_y) {
|
||||
@@ -640,9 +730,17 @@ void MapEditor::updateStatusBarInfo() {
|
||||
" 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_->setLine3(line3);
|
||||
statusbar_->setLine4("");
|
||||
statusbar_->setLine4(line4);
|
||||
statusbar_->setLine5(line5);
|
||||
|
||||
// Actualizar el prompt de la consola según la selección
|
||||
|
||||
@@ -93,6 +93,10 @@ class MapEditor {
|
||||
DragState drag_;
|
||||
int selected_enemy_{-1}; // Índice del enemigo 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
|
||||
Room::Data room_data_;
|
||||
|
||||
@@ -113,6 +113,7 @@ void TilePicker::open(const std::string& tileset_name, int current_tile,
|
||||
}
|
||||
|
||||
open_ = true;
|
||||
updateMousePosition();
|
||||
}
|
||||
|
||||
// Cierra el picker
|
||||
|
||||
@@ -134,6 +134,14 @@ void Room::resetEnemyPositions(const std::vector<Enemy::Data>& 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)
|
||||
void Room::setBgColor(const std::string& color) {
|
||||
bg_color_ = color;
|
||||
|
||||
@@ -76,6 +76,9 @@ class Room {
|
||||
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 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
|
||||
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
|
||||
|
||||
@@ -100,6 +100,37 @@ static void renderDebugCollisionSurfaces(const CollisionMap* collision_map) {
|
||||
void TilemapRenderer::redrawMap(const CollisionMap* 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
|
||||
|
||||
// Pinta el mapa estático y debug lines
|
||||
|
||||
@@ -70,6 +70,7 @@ class TilemapRenderer {
|
||||
*/
|
||||
void redrawMap(const CollisionMap* collision_map);
|
||||
void setBgColor(const std::string& color) { bg_color_ = color; }
|
||||
void setTile(int index, int tile_value); // Cambia un tile y repinta esa celda
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user