feat: add selection animation for piece

This commit is contained in:
2026-01-15 20:05:09 +08:00
parent d65d4241f4
commit 4ae99a44a3
3 changed files with 59 additions and 6 deletions

View File

@@ -1,5 +1,6 @@
#include "BoardRenderer.h"
#include "game/Board.h"
#include "core/Time.h"
#include <iostream>
BoardRenderer::BoardRenderer(int WIDTH, int HEIGHT, SDL_Renderer* renderer, TextureManager* textureManager) :
m_Width(WIDTH),
@@ -76,12 +77,13 @@ void BoardRenderer::drawPiece(std::optional<std::pair<int, int>> selectedPiece)
// 计算棋子中心位置
float x = area.x + col * area.cellSize;
float y = area.y + row * area.cellSize;
bool isSelected = false;
// 确定棋子颜色
SDL_Color color;
if (selectedPiece && selectedPiece->first == row && selectedPiece->second == col) {
// 选中状态的棋子
color = m_colors.selected;
isSelected = true;
} else {
// 根据玩家设置颜色
color = (piece->getPieceOwner() == PlayerID::P1) ?
@@ -99,10 +101,57 @@ void BoardRenderer::drawPiece(std::optional<std::pair<int, int>> selectedPiece)
};
//SDL_RenderFillRect(m_renderer, &rect);
bool isRenderered = false;
auto texture = m_textureManager->createTextureFromRect(rect.x, rect.y, rect, color);
SDL_FRect srect = {0, 0, rect.w, rect.h};
SDL_RenderTexture(m_renderer, texture, &srect, &rect);
//SDL_FRect srect = {0, 0, rect.w, rect.h};
if (isSelected) {
// 如果被选择
static float animationDuration = 1.0f; // 动画总时长(秒)
static float currentTime = 0.0f; // 当前已进行时间
//static bool isAnimating = true; // 动画状态
static bool isBigger = true;
// 累加时间,限制不超过总时长
currentTime += Time::deltaTime();
if (currentTime > animationDuration) {
currentTime = 0;
isBigger = !isBigger;
}
static SDL_FRect renderRect = {
rect.x,
rect.y,
rect.w,
rect.h
};
if (m_lastSelected != selectedPiece) {
renderRect = rect;
m_lastSelected = selectedPiece;
currentTime = 0;
isBigger = true;
}
float progess = currentTime / animationDuration;
double rotatedAngel = 360 * static_cast<double>(progess);
float scale = 0.1 * progess;
if (isBigger) {
renderRect.w += scale;
renderRect.h += scale;
} else {
renderRect.w -= scale;
renderRect.h -= scale;
}
SDL_RenderTextureRotated(m_renderer, texture, nullptr, &renderRect, rotatedAngel, nullptr, SDL_FLIP_NONE);
isRenderered = true;
//return;
}
if (!isRenderered) {
SDL_RenderTexture(m_renderer, texture, nullptr, &rect);
}
}
}

View File

@@ -36,6 +36,8 @@ private:
TextureManager* m_textureManager;
std::optional<std::pair<int, int>> m_lastSelected = std::nullopt;
public:
BoardRenderer(int WIDTH, int HEIGHT, SDL_Renderer* renderer, TextureManager* textureManager);

View File

@@ -35,6 +35,7 @@ SDL_Texture* TextureManager::createTextureFromRect(int x, int y, SDL_FRect& rect
SDL_Log("TextureManager renderer is null\n");
return nullptr;
}
auto newTexture = SDL_CreateTexture(
m_renderer,
SDL_PIXELFORMAT_RGBA8888,
@@ -44,13 +45,14 @@ SDL_Texture* TextureManager::createTextureFromRect(int x, int y, SDL_FRect& rect
);
// 保存当前的渲染目标
auto currentTexture = SDL_GetRenderTarget(m_renderer);
SDL_SetRenderTarget(m_renderer, newTexture);
SDL_SetTextureScaleMode(currentTexture, SDL_SCALEMODE_NEAREST);
SDL_SetRenderDrawColor(m_renderer, color.r, color.g, color.b, color.a);
// 因为修改了渲染目标,所以坐标系不一样了
SDL_FRect renderRect = {0, 0, rect.w, rect.h};
SDL_RenderFillRect(m_renderer, &renderRect);
// 缓存
m_cacheTexture.emplace(makeHash(x, y), newTexture);
// 恢复渲染目标