diff --git a/CMakeLists.txt b/CMakeLists.txt index 951cae3..66ae38a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ set(SOURCE_FILES src/core/Piece.cpp src/core/Rule.cpp src/core/ComponentManager.cpp + src/input/InputManager.cpp ) # 添加可执行文件 diff --git a/src/input/InputManager.cpp b/src/input/InputManager.cpp index e69de29..37b5153 100644 --- a/src/input/InputManager.cpp +++ b/src/input/InputManager.cpp @@ -0,0 +1,54 @@ +#include "InputManager.h" +#include "ui/Render.h" +#include "core/Game.h" +SDL_AppResult InputManager::handleInputEvent(const SDL_Event* event, const Renderer* g_renderer, Game* g_game) { + + switch (event->type) { + // 如果检测到退出 + case SDL_EVENT_QUIT: + return SDL_APP_SUCCESS; + case SDL_EVENT_MOUSE_BUTTON_DOWN: + if (event->button.button == SDL_BUTTON_LEFT) { + // 将窗口坐标转为逻辑坐标 + float logicalX, logicalY; + SDL_RenderCoordinatesFromWindow( + g_renderer->getSDLRenderer(), + static_cast(event->button.x), + static_cast(event->button.y), + &logicalX, + &logicalY + ); + auto boardArea = g_renderer->getBoardArea(); + auto click = handleMouseClick(static_cast(logicalX), static_cast(logicalY), boardArea); + if (click) { + auto [row, col] = click.value(); + SDL_Log("click on (%d, %d)", row, col); + g_game->handleCoordinateInput(row, col); + g_game->printBoard(); + } else { + SDL_Log("invail cilck aera!"); + } + return SDL_APP_CONTINUE; + } + } + return SDL_APP_CONTINUE; +} + +std::optional> +InputManager::handleMouseClick(int mouseX, int mouseY, const ui::BoardArea& area) { + // 判断是否点击在棋盘区域内 + if (mouseX < area.x || mouseX >= area.x + area.cellSize * area.cols || + mouseY < area.y || mouseY >= area.y + area.cellSize * area.rows) { + return std::nullopt; // 点击在棋盘外 + } + + // 转换为逻辑坐标 + int col = (mouseX - area.x) / area.cellSize; + int row = (mouseY - area.y) / area.cellSize; + + // 安全检查(通常不需要,但保险) + if (row >= 0 && row < area.rows && col >= 0 && col < area.cols) { + return std::pair{row, col}; + } + return std::nullopt; +} \ No newline at end of file diff --git a/src/input/InputManager.h b/src/input/InputManager.h index e69de29..104262f 100644 --- a/src/input/InputManager.h +++ b/src/input/InputManager.h @@ -0,0 +1,14 @@ +#pragma once +#include +#include +#include +#include "ui/UIType.h" +class Renderer; +class Game; +class InputManager { +public: + + SDL_AppResult handleInputEvent(const SDL_Event* event, const Renderer* g_renderer, Game* g_game); + // 调用前需传入当前棋盘渲染区域(来自 Renderer) + std::optional> handleMouseClick(int mouseX, int mouseY, const ui::BoardArea& boardArea); +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index a5d5bc2..98eac95 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,11 +3,13 @@ #include #include "core/Game.h" #include "ui/Render.h" +#include "input/InputManager.h" //使用SDL3的appstate进行隔离,避免全局变量 struct AppState { std::unique_ptr g_game; std::unique_ptr g_renderer; + std::unique_ptr g_input; }; @@ -31,7 +33,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) { auto state = new AppState(); state->g_game = std::make_unique(); state->g_renderer = std::make_unique(WIDTH, HEIGHT); - + state->g_input = std::make_unique(); if (!state->g_game->initialize() || !state->g_renderer->initialize()) { SDL_Log("游戏初始化失败!"); @@ -46,13 +48,10 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) { // 2. 事件处理回调 SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { auto s = static_cast(appstate); - if (event->type == SDL_EVENT_KEY_DOWN || - event->type == SDL_EVENT_QUIT) { - return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ - } + auto result = s->g_input->handleInputEvent(event, s->g_renderer.get(), s->g_game.get()); - return SDL_APP_CONTINUE; + return result; } // 3. 主循环迭代回调(每帧调用) diff --git a/src/ui/Render.cpp b/src/ui/Render.cpp index f94a47c..706842f 100644 --- a/src/ui/Render.cpp +++ b/src/ui/Render.cpp @@ -1,12 +1,10 @@ #include "Render.h" Renderer::Renderer(int WIDTH, int HEIGHT) : m_Width(WIDTH), m_Height(HEIGHT) { - + m_cellSize = HEIGHT / m_boardRow; } -Renderer::Renderer() : m_Width(1600), m_Height(900) { -} Renderer::~Renderer() { if (m_renderer) SDL_DestroyRenderer(m_renderer); @@ -45,14 +43,70 @@ bool Renderer::initialize() { return true; } -void Renderer::Renderhello() { - SDL_SetRenderDrawColor(m_renderer, 0, 0, 0, 255); - SDL_RenderClear(m_renderer); - SDL_SetRenderDrawColor(m_renderer, 255, 255, 255, 255); - SDL_RenderPresent(m_renderer); -} + void Renderer::render() { - Renderhello(); + clear(); + + drawBoard(); + + present(); + + +} + +void Renderer::clear() { + // 设置画笔颜色 + SDL_SetRenderDrawColor(m_renderer, 255, 255, 255, 255); + // 使用画笔颜色填充整个屏幕 + SDL_RenderClear(m_renderer); +} + +void Renderer::present() { + SDL_RenderPresent(m_renderer); +} + +void Renderer::drawBoard() { + auto area = getBoardArea(); + + +// 绘制棋盘格子(交替颜色) +for (int row = 0; row < area.rows; ++row) { + for (int col = 0; col < area.cols; ++col) { + // 使用 SDL_FRect(浮点数) + SDL_FRect rect{ + static_cast(area.x + col * area.cellSize), + static_cast(area.y + row * area.cellSize), + static_cast(area.cellSize), + static_cast(area.cellSize) + }; + + bool isLight = (row + col) % 2 == 0; + SDL_SetRenderDrawColor(m_renderer, + isLight ? 240 : 180, + isLight ? 220 : 160, + isLight ? 180 : 120, + 255); + + // SDL3: RenderFillRect 接受 const SDL_FRect* + SDL_RenderFillRect(m_renderer, &rect); + } +} + + +} + +ui::BoardArea Renderer::getBoardArea() const { + return { + (m_Width - m_cellSize * m_boardCOL) / 2, + (m_Height - m_cellSize * m_boardRow) / 2, + m_cellSize, + m_boardRow, + m_boardCOL + }; +} + +SDL_Renderer* Renderer::getSDLRenderer() const { + return m_renderer; } \ No newline at end of file diff --git a/src/ui/Render.h b/src/ui/Render.h index 24ea5bf..2e44c89 100644 --- a/src/ui/Render.h +++ b/src/ui/Render.h @@ -1,5 +1,5 @@ #pragma once - +#include "UIType.h" #include class Renderer @@ -9,13 +9,30 @@ private: SDL_Renderer* m_renderer = nullptr; int m_Width; int m_Height; + int m_cellSize; + int m_boardRow = 7; + int m_boardCOL = 7; public: Renderer(int WIDTH, int HEIGHT); - Renderer(); + ~Renderer(); + // 渲染画面 void render(); bool initialize(); - void Renderhello(); + // 清除上一帧的渲染 + void clear(); + // 展现画面 + void present(); + + + + // 绘制棋盘 + void drawBoard(); + + + ui::BoardArea getBoardArea() const; + + SDL_Renderer* getSDLRenderer() const; }; diff --git a/src/ui/UIType.h b/src/ui/UIType.h new file mode 100644 index 0000000..31a7b60 --- /dev/null +++ b/src/ui/UIType.h @@ -0,0 +1,10 @@ +#pragma once + +namespace ui { + // 获取棋盘渲染区域信息(用于坐标转换) + struct BoardArea { + int x, y; // 左上角像素坐标 + int cellSize; // 每格像素大小 + int rows, cols; // 行列数 + }; +} \ No newline at end of file