drag'n drop del jugador

This commit is contained in:
2026-04-02 10:39:57 +02:00
parent 606388227c
commit b6fec3eba7
2 changed files with 131 additions and 8 deletions

View File

@@ -4,6 +4,7 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <cmath> // Para std::round
#include <iostream> // Para cout #include <iostream> // Para cout
#include "core/input/mouse.hpp" // Para Mouse #include "core/input/mouse.hpp" // Para Mouse
@@ -63,6 +64,9 @@ void MapEditor::enter(std::shared_ptr<Room> room, std::shared_ptr<Player> player
// Crear la barra de estado // Crear la barra de estado
statusbar_ = std::make_unique<EditorStatusBar>(room_->getNumber(), room_->getName()); statusbar_ = std::make_unique<EditorStatusBar>(room_->getNumber(), room_->getName());
// Resetear estado de drag
drag_ = {};
active_ = true; active_ = true;
std::cout << "MapEditor: ON (room " << room_path_ << ")\n"; std::cout << "MapEditor: ON (room " << room_path_ << ")\n";
} }
@@ -78,6 +82,7 @@ void MapEditor::exit() {
player_->setColor(); player_->setColor();
// Liberar recursos // Liberar recursos
drag_ = {};
statusbar_.reset(); statusbar_.reset();
room_.reset(); room_.reset();
player_.reset(); player_.reset();
@@ -98,6 +103,11 @@ void MapEditor::update(float delta_time) {
// Actualizar posición del ratón // Actualizar posición del ratón
updateMousePosition(); updateMousePosition();
// Si estamos arrastrando, actualizar la posición snapped
if (drag_.target != DragTarget::NONE) {
updateDrag();
}
// Actualizar la barra de estado con las coordenadas del ratón // Actualizar la barra de estado con las coordenadas del ratón
if (statusbar_) { if (statusbar_) {
statusbar_->setMouseTile(mouse_tile_x_, mouse_tile_y_); statusbar_->setMouseTile(mouse_tile_x_, mouse_tile_y_);
@@ -117,6 +127,9 @@ void MapEditor::render() {
room_->renderItems(); room_->renderItems();
player_->render(); player_->render();
// Renderizar highlight de selección (encima de los sprites)
renderSelectionHighlight();
// Renderizar barra de estado del editor (reemplaza al scoreboard) // Renderizar barra de estado del editor (reemplaza al scoreboard)
if (statusbar_) { if (statusbar_) {
statusbar_->render(); statusbar_->render();
@@ -124,9 +137,101 @@ void MapEditor::render() {
} }
// Maneja eventos del editor // Maneja eventos del editor
void MapEditor::handleEvent([[maybe_unused]] const SDL_Event& event) { void MapEditor::handleEvent(const SDL_Event& event) {
// Por ahora no procesamos eventos específicos del editor if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN && event.button.button == SDL_BUTTON_LEFT) {
// En fases posteriores: drag & drop handleMouseDown(mouse_game_x_, mouse_game_y_);
} else if (event.type == SDL_EVENT_MOUSE_BUTTON_UP && event.button.button == SDL_BUTTON_LEFT) {
handleMouseUp();
}
}
// 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
// 1. Hit test sobre el jugador
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;
return;
}
// (Fases 4+: hit test sobre enemigos e items)
}
// Procesa soltar el ratón: commit del drag
void MapEditor::handleMouseUp() {
if (drag_.target == DragTarget::NONE) { return; }
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:
break;
}
// Resetear estado de drag
drag_ = {};
}
// Actualiza la posición snapped durante el drag
void MapEditor::updateDrag() {
float raw_x = mouse_game_x_ - drag_.offset_x;
float raw_y = mouse_game_y_ - drag_.offset_y;
drag_.snap_x = snapToGrid(raw_x);
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);
}
}
// Dibuja highlight del elemento seleccionado/arrastrado
void MapEditor::renderSelectionHighlight() {
if (drag_.target == DragTarget::NONE) { return; }
auto game_surface = Screen::get()->getRendererSurface();
if (!game_surface) { return; }
const Uint8 HIGHLIGHT_COLOR = stringToColor("bright_white");
SDL_FRect highlight_rect{};
switch (drag_.target) {
case DragTarget::PLAYER:
highlight_rect = player_->getRect();
break;
default:
return;
}
// Dibujar rectángulo de highlight alrededor de la entidad
SDL_FRect border = {
.x = highlight_rect.x - 1,
.y = highlight_rect.y - 1,
.w = highlight_rect.w + 2,
.h = highlight_rect.h + 2
};
game_surface->drawRectBorder(&border, HIGHLIGHT_COLOR);
}
// Alinea un valor a la cuadrícula de 8x8
auto MapEditor::snapToGrid(float value) -> float {
return std::round(value / static_cast<float>(Tile::SIZE)) * static_cast<float>(Tile::SIZE);
}
// Hit test: punto dentro de rectángulo
auto MapEditor::pointInRect(float px, float py, const SDL_FRect& rect) -> bool {
return px >= rect.x && px < rect.x + rect.w && py >= rect.y && py < rect.y + rect.h;
} }
// Dibuja marcadores de boundaries y líneas de ruta para los enemigos // Dibuja marcadores de boundaries y líneas de ruta para los enemigos
@@ -140,7 +245,6 @@ void MapEditor::renderEnemyBoundaries() {
for (const auto& enemy : room_data_.enemies) { for (const auto& enemy : room_data_.enemies) {
// Dibujar línea de ruta: boundary1 → posición inicial → boundary2 // Dibujar línea de ruta: boundary1 → posición inicial → boundary2
// Usamos el centro del tile como punto de referencia para las líneas
constexpr float HALF = Tile::SIZE / 2.0F; constexpr float HALF = Tile::SIZE / 2.0F;
float init_cx = enemy.x + HALF; float init_cx = enemy.x + HALF;
@@ -166,7 +270,6 @@ void MapEditor::renderBoundaryMarker(float x, float y, Uint8 color) {
auto game_surface = Screen::get()->getRendererSurface(); auto game_surface = Screen::get()->getRendererSurface();
if (!game_surface) { return; } if (!game_surface) { return; }
// Dibujar un rectángulo de 8x8 como marcador
SDL_FRect marker = {.x = x, .y = y, .w = static_cast<float>(Tile::SIZE), .h = static_cast<float>(Tile::SIZE)}; SDL_FRect marker = {.x = x, .y = y, .w = static_cast<float>(Tile::SIZE), .h = static_cast<float>(Tile::SIZE)};
game_surface->drawRectBorder(&marker, color); game_surface->drawRectBorder(&marker, color);
} }

View File

@@ -37,12 +37,32 @@ class MapEditor {
MapEditor(); // Constructor MapEditor(); // Constructor
~MapEditor(); // Destructor ~MapEditor(); // Destructor
void updateMousePosition(); // Convierte coordenadas de ventana a coordenadas de juego y tile // Tipos para drag & drop
void renderEnemyBoundaries(); // Dibuja marcadores de boundaries y líneas de ruta enum class DragTarget { NONE, PLAYER, ENEMY_INITIAL, ENEMY_BOUND1, ENEMY_BOUND2, ITEM };
void renderBoundaryMarker(float x, float y, Uint8 color); // Dibuja un marcador de boundary en una posición
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
float offset_y{0.0F};
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
static auto pointInRect(float px, float py, const SDL_FRect& rect) -> bool; // Hit test punto en rectángulo
// Estado del editor // Estado del editor
bool active_{false}; bool active_{false};
DragState drag_;
// Copia mutable de los datos de la habitación (para edición futura) // Copia mutable de los datos de la habitación (para edición futura)
Room::Data room_data_; Room::Data room_data_;