From 27ff62df1414b02fe9eea996d30e6c52b763554e Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Sat, 13 Dec 2025 19:53:02 +0800 Subject: [PATCH] Added drawMovementRange function --- src/graphics/game/BoardRenderer.cpp | 117 ++++++++++++++++++++++++---- src/graphics/game/BoardRenderer.h | 8 +- src/scenes/gameplay/GameScene.cpp | 2 + 3 files changed, 111 insertions(+), 16 deletions(-) diff --git a/src/graphics/game/BoardRenderer.cpp b/src/graphics/game/BoardRenderer.cpp index b75a9c6..0983f29 100644 --- a/src/graphics/game/BoardRenderer.cpp +++ b/src/graphics/game/BoardRenderer.cpp @@ -30,7 +30,7 @@ void BoardRenderer::drawBoard() { auto area = getBoardArea(); -// 绘制棋盘格子(交替颜色) +// 绘制棋盘格子 for (int row = 0; row < area.rows; ++row) { for (int col = 0; col < area.cols; ++col) { // 使用 SDL_FRect(浮点数) @@ -68,8 +68,8 @@ void BoardRenderer::drawPiece(std::optional> selectedPiece) if (!piece) continue; // 没有棋子则跳过 // 计算棋子中心位置 - float centerX = area.x + col * area.cellSize + area.cellSize / 2.0f; - float centerY = area.y + row * area.cellSize + area.cellSize / 2.0f; + float x = area.x + col * area.cellSize; + float y = area.y + row * area.cellSize; // 确定棋子颜色 SDL_Color color; @@ -82,23 +82,112 @@ void BoardRenderer::drawPiece(std::optional> selectedPiece) m_colors.P1 : m_colors.P2; } - // 绘制棋子(圆形) + SDL_SetRenderDrawColor(m_renderer, color.r, color.g, color.b, color.a); - // 绘制实心圆(使用多个同心圆来近似) - for (float r = pieceRadius; r > 0; r -= 1.0f) { - SDL_FRect rect = { - centerX - r, - centerY - r, - r * 2.0f, - r * 2.0f - }; - SDL_RenderFillRect(m_renderer, &rect); - } + SDL_FRect rect{ + x + (area.cellSize - pieceRadius * 2) / 2.0f, + y + (area.cellSize - pieceRadius * 2) / 2.0f, + pieceRadius * 2, + pieceRadius * 2 + }; + + SDL_RenderFillRect(m_renderer, &rect); + } } } +void BoardRenderer::updateMovementRange(std::optional> selectedPiece, ActionType tpye) { + // 清空当前范围以便下次更新 + m_currentDrawRange.clear(); + if (!m_board || !m_renderer || !selectedPiece) return; + if (selectedPiece == std::nullopt) return; + auto selectedComponent = m_board->getComponentByPieceID(m_board->getPieceID(selectedPiece->first, selectedPiece->second)); + + auto currentPlayer = m_board->getPieceAt(selectedPiece->first, selectedPiece->second)->getPieceOwner(); + switch (tpye) { + case ActionType::GROW: + // 绘制生长范围的逻辑 + for (auto PieceID : selectedComponent) { + auto Neighbors = m_board->getOrthogonalNeighbors(PieceID); + for (auto neighborID : Neighbors) { + auto pieceCoord = m_board->getCoordFromID(neighborID); + const Piece* piece = m_board->getPieceAt(pieceCoord.first, pieceCoord.second); + if (piece == nullptr) { + m_currentDrawRange.insert(neighborID); + } + } + } + break; + case ActionType::MOVE: + // 绘制移动范围的逻辑 + for (auto PieceID : selectedComponent) { + auto Neighbors = m_board->getOrthogonalNeighbors(PieceID); + for (auto neighborID : Neighbors) { + auto pieceCoord = m_board->getCoordFromID(neighborID); + const Piece* piece = m_board->getPieceAt(pieceCoord.first, pieceCoord.second); + if (piece == nullptr) { + m_currentDrawRange.insert(neighborID); + } else if (piece->getPieceOwner() != currentPlayer) { + m_currentDrawRange.insert(neighborID); + } + } + } + break; + case ActionType::SPORE: { + // 绘制孢子范围的逻辑 + auto SporeRange = m_board->getSporeRange(m_board->getPieceID(selectedPiece->first, selectedPiece->second)); + for (auto neighborID : SporeRange) { + auto pieceCoord = m_board->getCoordFromID(neighborID); + const Piece* piece = m_board->getPieceAt(pieceCoord.first, pieceCoord.second); + if (piece == nullptr) { + m_currentDrawRange.insert(neighborID); + } + } + } + break; + default: + break; + } + +} + +void BoardRenderer::drawMovementRange() { + + if (!m_board || !m_renderer) return; + + // 开启混合模式(重要!) + SDL_SetRenderDrawBlendMode(m_renderer, SDL_BLENDMODE_BLEND); + + auto area = getBoardArea(); + float pieceRadius = m_cellSize * m_pieceRadiusRatio / 4.0f; + for (auto PieceID : m_currentDrawRange) { + auto [row, col] = m_board->getCoordFromID(PieceID); + + // 计算棋子中心位置 + float x = area.x + col * area.cellSize; + float y = area.y + row * area.cellSize; + + SDL_FRect rect{ + x + (area.cellSize - pieceRadius * 2) / 2.0f, + y + (area.cellSize - pieceRadius * 2) / 2.0f, + pieceRadius * 2, + pieceRadius * 2 + }; + + SDL_SetRenderDrawColor(m_renderer, + 0, + 255, + 0, + 100); // 半透明绿色 + + SDL_RenderFillRect(m_renderer, &rect); + } + // 如果需要,绘制完可以恢复原来的混合模式 + SDL_SetRenderDrawBlendMode(m_renderer, SDL_BLENDMODE_NONE); +} + BoardArea BoardRenderer::getBoardArea() const { return { (m_Width - m_cellSize * m_boardCOL) / 2, diff --git a/src/graphics/game/BoardRenderer.h b/src/graphics/game/BoardRenderer.h index 33e7032..23422de 100644 --- a/src/graphics/game/BoardRenderer.h +++ b/src/graphics/game/BoardRenderer.h @@ -1,9 +1,10 @@ #pragma once #include "utils/Config.h" +#include "game/GameTypes.h" #include #include #include - +#include struct PlayerColors { SDL_Color P1 = {255, 0, 0, 255}; // 红色 @@ -29,6 +30,7 @@ private: // 棋子绘制相关 float m_pieceRadiusRatio = 0.8f; // 棋子半径相对于格子大小的比例 PlayerColors m_colors; + std::unordered_set m_currentDrawRange; public: BoardRenderer(int WIDTH, int HEIGHT, SDL_Renderer* renderer); @@ -48,7 +50,9 @@ public: // 绘制棋子 void drawPiece(std::optional> selectedPiece = std::nullopt); - + void updateMovementRange(std::optional> selectedPiece = std::nullopt, ActionType type = ActionType::GROW); + + void drawMovementRange(); BoardArea getBoardArea() const; diff --git a/src/scenes/gameplay/GameScene.cpp b/src/scenes/gameplay/GameScene.cpp index 5329b15..1c01e44 100644 --- a/src/scenes/gameplay/GameScene.cpp +++ b/src/scenes/gameplay/GameScene.cpp @@ -35,6 +35,7 @@ void GameScene::render() { m_boardRenderer->drawBoard(); m_boardRenderer->drawPiece(m_gameSession->getSelectedPiece()); + m_boardRenderer->drawMovementRange(); m_uiRenderer->renderUI(m_gameUIManager->getUIRenderData()); endFrame(); } @@ -46,6 +47,7 @@ void GameScene::handleClick(float screenX, float screenY) { m_gameSession->handleCoordinateInput(row, col); m_gameSession->printBoard(); m_gameUIManager->updateActionType( m_gameSession->getCurrentActionType()); + m_boardRenderer->updateMovementRange(m_gameSession->getSelectedPiece(), m_gameSession->getCurrentActionType()); } else { SDL_Log("invail cilck aera!"); }