drag'n drop del jugador
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,12 +37,32 @@ class MapEditor {
|
|||||||
MapEditor(); // Constructor
|
MapEditor(); // Constructor
|
||||||
~MapEditor(); // Destructor
|
~MapEditor(); // Destructor
|
||||||
|
|
||||||
|
// Tipos para drag & drop
|
||||||
|
enum class DragTarget { NONE, PLAYER, ENEMY_INITIAL, ENEMY_BOUND1, ENEMY_BOUND2, ITEM };
|
||||||
|
|
||||||
|
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 updateMousePosition(); // Convierte coordenadas de ventana a coordenadas de juego y tile
|
||||||
void renderEnemyBoundaries(); // Dibuja marcadores de boundaries y líneas de ruta
|
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 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_;
|
||||||
|
|||||||
Reference in New Issue
Block a user