From 94502e61041b1b19ea4b084541d23bb33e5b4704 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Fri, 16 Jan 2026 17:56:41 +0800 Subject: [PATCH] perf: optimize texture caching --- src/graphics/game/BoardRenderer.cpp | 26 +++++++++++++++++---- src/graphics/texture/TextureManager.cpp | 31 +++++++++++++++---------- src/graphics/texture/TextureManager.h | 8 +++---- 3 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/graphics/game/BoardRenderer.cpp b/src/graphics/game/BoardRenderer.cpp index f3a8604..2555853 100644 --- a/src/graphics/game/BoardRenderer.cpp +++ b/src/graphics/game/BoardRenderer.cpp @@ -81,7 +81,7 @@ void BoardRenderer::drawPiece(std::optional> selectedPiece) // 确定棋子颜色 SDL_Color color; if (selectedPiece && selectedPiece->first == row && selectedPiece->second == col) { - // 选中状态的棋子 + // 选中状态的棋子,暂时不渲染黄色的选中状态 color = m_colors.selected; isSelected = true; } else { @@ -102,7 +102,7 @@ void BoardRenderer::drawPiece(std::optional> selectedPiece) //SDL_RenderFillRect(m_renderer, &rect); bool isRenderered = false; - auto texture = m_textureManager->createTextureFromRect(rect.x, rect.y, rect, color); + auto texture = m_textureManager->createTextureFromRect(rect, color); //SDL_FRect srect = {0, 0, rect.w, rect.h}; if (isSelected) { // 如果被选择 @@ -286,15 +286,31 @@ void BoardRenderer::renderBlackOverlay() { void BoardRenderer::handleGamePieceEvent(GamePieceEvent event, int row, int col) { auto area = getBoardArea(); + + // 计算棋子中心位置 float x = area.x + col * area.cellSize; float y = area.y + row * area.cellSize; + float pieceRadius = m_cellSize * m_pieceRadiusRatio / 2.0f; + + SDL_FRect rect{ + x + (area.cellSize - pieceRadius * 2) / 2.0f, + y + (area.cellSize - pieceRadius * 2) / 2.0f, + pieceRadius * 2, + pieceRadius * 2 + }; + + const Piece* piece = m_board->getPieceAt(row, col); + if (!piece) { + SDL_Log("BoardRenderer: piece is null\n"); + return; + } + SDL_Color color = (piece->getPieceOwner() == PlayerID::P1) ? + m_colors.P1 : m_colors.P2; switch (event) { case (GamePieceEvent::REMOVE_PIECE): //SDL_Log("BoardRenderer: try to destory texture\n"); - m_textureManager->destoryTexture( - x + (area.cellSize - pieceRadius * 2) / 2.0f, - y + (area.cellSize - pieceRadius * 2) / 2.0f); + m_textureManager->destoryTexture(rect, color); break; case (GamePieceEvent::PLACE_PIECE): break; diff --git a/src/graphics/texture/TextureManager.cpp b/src/graphics/texture/TextureManager.cpp index 219d2fc..2213888 100644 --- a/src/graphics/texture/TextureManager.cpp +++ b/src/graphics/texture/TextureManager.cpp @@ -24,10 +24,10 @@ void TextureManager::cleanupAllTexture() { -SDL_Texture* TextureManager::createTextureFromRect(int x, int y, SDL_FRect& rect, SDL_Color& color) { +SDL_Texture* TextureManager::createTextureFromRect(SDL_FRect& rect, SDL_Color& color) { // 先在缓存中查找是否存在 - auto it = getTexture(x, y); + auto it = getTexture(rect, color); if(it) { return it; } @@ -53,37 +53,44 @@ SDL_Texture* TextureManager::createTextureFromRect(int x, int y, SDL_FRect& rect SDL_FRect renderRect = {0, 0, rect.w, rect.h}; SDL_RenderFillRect(m_renderer, &renderRect); // 缓存 - m_cacheTexture.emplace(makeHash(x, y), newTexture); + m_cacheTexture.emplace(makeHash(rect, color), newTexture); // 恢复渲染目标 SDL_SetRenderTarget(m_renderer, currentTexture); return newTexture; } -size_t TextureManager::makeHash(int x, int y) { +size_t TextureManager::makeHash(SDL_FRect& rect, SDL_Color& color) { // 分别计算字体名称和大小的哈希值 - size_t h1 = std::hash{}(x); - size_t h2 = std::hash{}(y); + size_t h1 = std::hash{}(rect.x); + size_t h2 = std::hash{}(rect.y); + size_t h3 = std::hash{}(rect.w); + size_t h4 = std::hash{}(rect.h); + + size_t h5 = std::hash{}(color.r); + size_t h6 = std::hash{}(color.g); + size_t h7 = std::hash{}(color.b); + size_t h8 = std::hash{}(color.a); // 组合两个哈希值:使用XOR运算和位左移组合两个独立的哈希值 // 这样可以确保不同的fontID或ptSize组合都会产生不同的哈希值 - return h1 ^ (h2 << 1); + return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3) ^ (h5 << 4) ^ (h6 << 5) ^ (h7 << 6) ^ (h8 << 7); } -SDL_Texture* TextureManager::getTexture(int x, int y) { - auto key = makeHash(x, y); +SDL_Texture* TextureManager::getTexture(SDL_FRect& rect, SDL_Color& color) { + auto key = makeHash(rect, color); auto it = m_cacheTexture.find(key); if (it != m_cacheTexture.end()) { return it->second; } else { - SDL_Log("TextureManager: texture %d %d not exist!", x, y); + SDL_Log("TextureManager: texture not exist!"); return nullptr; } } -bool TextureManager::destoryTexture(int x, int y) { - int key = makeHash(x, y); +bool TextureManager::destoryTexture(SDL_FRect& rect, SDL_Color& color) { + int key = makeHash(rect, color); auto it = m_cacheTexture.find(key); if (it == m_cacheTexture.end()) { SDL_Log("can't find the texture\n"); diff --git a/src/graphics/texture/TextureManager.h b/src/graphics/texture/TextureManager.h index 5893f64..ab62f3a 100644 --- a/src/graphics/texture/TextureManager.h +++ b/src/graphics/texture/TextureManager.h @@ -10,13 +10,13 @@ public: ~TextureManager(); - SDL_Texture* createTextureFromRect(int x, int y, SDL_FRect& rect, SDL_Color& coler); + SDL_Texture* createTextureFromRect(SDL_FRect& rect, SDL_Color& coler); void cleanupAllTexture(); - SDL_Texture* getTexture(int x, int y); + SDL_Texture* getTexture(SDL_FRect& rect, SDL_Color& color); - bool destoryTexture(int x, int y); + bool destoryTexture(SDL_FRect& rect, SDL_Color& color); private: @@ -24,6 +24,6 @@ private: std::unordered_map m_cacheTexture; - size_t makeHash(int x, int y); + size_t makeHash(SDL_FRect& rect, SDL_Color& color); }; \ No newline at end of file