drag'n drop del jugador
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <cmath> // Para std::round
|
||||
#include <iostream> // Para cout
|
||||
|
||||
#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
|
||||
statusbar_ = std::make_unique<EditorStatusBar>(room_->getNumber(), room_->getName());
|
||||
|
||||
// Resetear estado de drag
|
||||
drag_ = {};
|
||||
|
||||
active_ = true;
|
||||
std::cout << "MapEditor: ON (room " << room_path_ << ")\n";
|
||||
}
|
||||
@@ -78,6 +82,7 @@ void MapEditor::exit() {
|
||||
player_->setColor();
|
||||
|
||||
// Liberar recursos
|
||||
drag_ = {};
|
||||
statusbar_.reset();
|
||||
room_.reset();
|
||||
player_.reset();
|
||||
@@ -98,6 +103,11 @@ void MapEditor::update(float delta_time) {
|
||||
// Actualizar posición del ratón
|
||||
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
|
||||
if (statusbar_) {
|
||||
statusbar_->setMouseTile(mouse_tile_x_, mouse_tile_y_);
|
||||
@@ -117,6 +127,9 @@ void MapEditor::render() {
|
||||
room_->renderItems();
|
||||
player_->render();
|
||||
|
||||
// Renderizar highlight de selección (encima de los sprites)
|
||||
renderSelectionHighlight();
|
||||
|
||||
// Renderizar barra de estado del editor (reemplaza al scoreboard)
|
||||
if (statusbar_) {
|
||||
statusbar_->render();
|
||||
@@ -124,9 +137,101 @@ void MapEditor::render() {
|
||||
}
|
||||
|
||||
// Maneja eventos del editor
|
||||
void MapEditor::handleEvent([[maybe_unused]] const SDL_Event& event) {
|
||||
// Por ahora no procesamos eventos específicos del editor
|
||||
// En fases posteriores: drag & drop
|
||||
void MapEditor::handleEvent(const SDL_Event& event) {
|
||||
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN && event.button.button == SDL_BUTTON_LEFT) {
|
||||
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
|
||||
@@ -140,7 +245,6 @@ void MapEditor::renderEnemyBoundaries() {
|
||||
|
||||
for (const auto& enemy : room_data_.enemies) {
|
||||
// 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;
|
||||
|
||||
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();
|
||||
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)};
|
||||
game_surface->drawRectBorder(&marker, color);
|
||||
}
|
||||
|
||||
@@ -37,12 +37,32 @@ class MapEditor {
|
||||
MapEditor(); // Constructor
|
||||
~MapEditor(); // Destructor
|
||||
|
||||
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
|
||||
// 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 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
|
||||
bool active_{false};
|
||||
DragState drag_;
|
||||
|
||||
// Copia mutable de los datos de la habitación (para edición futura)
|
||||
Room::Data room_data_;
|
||||
|
||||
Reference in New Issue
Block a user