diff --git a/src/game/GameSession.cpp b/src/game/GameSession.cpp index 550f649..ee14a57 100644 --- a/src/game/GameSession.cpp +++ b/src/game/GameSession.cpp @@ -110,7 +110,9 @@ bool GameSession::executeAction(int toRow, int toCol) { m_board->changeHP(toRow, toCol, -fromPiece->getATK()); m_board->changeHP(fromRow, fromCol, -toPiece->getATK() * 0.5); - + if (fromPiece->getHP() > 0 && toPiece->getHP() > 0) { + m_gamePieceEventCallback(GamePieceEvent::FIGHT_PIECE, fromRow, fromCol, toRow, toCol); + } if (fromPiece->getHP() <= 0) { m_gamePieceEventCallback(GamePieceEvent::REMOVE_PIECE, fromRow, fromCol, -1, -1); m_board->removePieceAt(fromRow, fromCol); @@ -121,6 +123,7 @@ bool GameSession::executeAction(int toRow, int toCol) { if (fromPiece->getHP() > 0) { m_gamePieceEventCallback(GamePieceEvent::MOVE_PIECE, fromRow, fromCol, toRow, toCol); + auto fromInfo = fromPiece->getPieceInfo(); m_board->removePieceAt(fromRow, fromCol); diff --git a/src/game/GameTypes.h b/src/game/GameTypes.h index 8ff8e97..fda7dfb 100644 --- a/src/game/GameTypes.h +++ b/src/game/GameTypes.h @@ -34,7 +34,8 @@ enum class GamePieceEvent { PLACE_PIECE, MOVE_PIECE, GROW_PIECE, - SPORE_PIECE + SPORE_PIECE, + FIGHT_PIECE }; struct PieceInfo { diff --git a/src/graphics/game/BoardRenderer.cpp b/src/graphics/game/BoardRenderer.cpp index edb9d75..43b4897 100644 --- a/src/graphics/game/BoardRenderer.cpp +++ b/src/graphics/game/BoardRenderer.cpp @@ -1,6 +1,7 @@ #include "BoardRenderer.h" #include "game/Board.h" #include "core/Time.h" +#include "utils/Tools.h" #include BoardRenderer::BoardRenderer(int WIDTH, int HEIGHT, SDL_Renderer* renderer, TextureManager* textureManager) : m_Width(WIDTH), @@ -114,7 +115,8 @@ void BoardRenderer::drawPiece(std::optional> selectedPiece) float progess = m_pieceGrowStatus.currentTime / m_pieceGrowStatus.animationDuration; m_textureManager->destoryTexture(rect, color); auto renderColor = color; - renderColor.a = 255 * progess; + + renderColor.a = Tools::smoothMove(progess, 0, 255); auto texture = m_textureManager->createTextureFromRect(rect, renderColor); SDL_RenderTexture(m_renderer, texture, nullptr, &rect); continue; @@ -167,21 +169,42 @@ void BoardRenderer::drawPiece(std::optional> selectedPiece) continue; } - if (m_pieceMoveStatus.isAnimating && col == m_pieceMoveStatus.toCol && row == m_pieceMoveStatus.toRow) { - //SDL_Log("rendering..\n"); - m_pieceMoveStatus.currentTime += Time::deltaTime(); - if (m_pieceMoveStatus.currentTime > m_pieceMoveStatus.animationDuration) { - m_pieceMoveStatus.currentTime = m_pieceMoveStatus.animationDuration; - m_pieceMoveStatus.isAnimating = false; - } - float progess = m_pieceMoveStatus.currentTime / m_pieceMoveStatus.animationDuration; - auto renderRect = m_pieceMoveStatus.fromPieceRect; - renderRect.x += m_pieceMoveStatus.distanceCol * progess; - renderRect.y += m_pieceMoveStatus.distanceRow * progess; - SDL_RenderTexture(m_renderer, texture, nullptr, &renderRect); - } else { - SDL_RenderTexture(m_renderer, texture, nullptr, &rect); + if (m_pieceMoveStatus.isAnimating && col == m_pieceMoveStatus.toCol && row == m_pieceMoveStatus.toRow) { + //SDL_Log("rendering..\n"); + m_pieceMoveStatus.currentTime += Time::deltaTime(); + if (m_pieceMoveStatus.currentTime > m_pieceMoveStatus.animationDuration) { + m_pieceMoveStatus.currentTime = m_pieceMoveStatus.animationDuration; + m_pieceMoveStatus.isAnimating = false; } + float progess = m_pieceMoveStatus.currentTime / m_pieceMoveStatus.animationDuration; + auto renderRect = m_pieceMoveStatus.fromPieceRect; + renderRect.x += Tools::smoothMove(progess, 0, m_pieceMoveStatus.distanceCol); + renderRect.y += Tools::smoothMove(progess, 0, m_pieceMoveStatus.distanceRow); + SDL_RenderTexture(m_renderer, texture, nullptr, &renderRect); + continue; + } + + if (m_pieceFightStatus.isAnimating && col == m_pieceFightStatus.fromCol && row == m_pieceFightStatus.fromRow) { + m_pieceFightStatus.currentTime += Time::deltaTime(); + if (m_pieceFightStatus.currentTime > m_pieceFightStatus.animationDuration) { + m_pieceFightStatus.currentTime = m_pieceFightStatus.animationDuration; + m_pieceFightStatus.isAnimating = false; + } + float progess = m_pieceFightStatus.currentTime / m_pieceFightStatus.animationDuration; + auto renderRect = m_pieceFightStatus.fromPieceRect; + float cX = m_pieceFightStatus.distanceCol * 0.5f; + float cY = m_pieceFightStatus.distanceRow * 0.5f; + renderRect.x = Tools::pingPongSpring(progess, renderRect.x, cX); + renderRect.y = Tools::pingPongSpring(progess, renderRect.y, cY); + + + SDL_RenderTexture(m_renderer, texture, nullptr, &renderRect); + continue; + + } + + SDL_RenderTexture(m_renderer, texture, nullptr, &rect); + @@ -378,6 +401,18 @@ void BoardRenderer::handleGamePieceEvent(GamePieceEvent event, int fromRow, int 1.0f }; break; + case (GamePieceEvent::FIGHT_PIECE): + m_pieceFightStatus = { + fromRow, fromCol, + toRow, toCol, + toY - fromY, + toX - fromX, + 0.0f, + true, + rect, + 1.0f + }; + break; default: break; } diff --git a/src/graphics/game/BoardRenderer.h b/src/graphics/game/BoardRenderer.h index 0c355a3..7dea013 100644 --- a/src/graphics/game/BoardRenderer.h +++ b/src/graphics/game/BoardRenderer.h @@ -35,6 +35,19 @@ struct PieceGrowStatue { }; +struct PieceFightStatue { + int fromRow = -1; + int fromCol = -1; + int toRow = -1; + int toCol = -1; + float distanceRow; + float distanceCol; + float currentTime = 0.0f; // 当前已进行时间 + bool isAnimating = false; + SDL_FRect fromPieceRect; + float animationDuration = 1.0f; // 动画总时长(秒) +}; + class Board; class BoardRenderer @@ -64,6 +77,8 @@ private: PieceGrowStatue m_pieceGrowStatus; + PieceFightStatue m_pieceFightStatus; + public: BoardRenderer(int WIDTH, int HEIGHT, SDL_Renderer* renderer, TextureManager* textureManager); diff --git a/src/utils/Tools.h b/src/utils/Tools.h index c45d47e..f97b057 100644 --- a/src/utils/Tools.h +++ b/src/utils/Tools.h @@ -1,7 +1,10 @@ #pragma once #include #include "Config.h" - +#include +static inline float easeInOutSine(float t) { + return -(cos(M_PI * t) - 1) / 2.0f; +} namespace Tools { inline std::pair physicalToLogical(float physicalX, float physicalY, const Viewport& viewport) { std::pair logicalPoint = {0 , 0}; @@ -16,4 +19,34 @@ namespace Tools { return logicalPoint; } + + + // t ∈ [0, 1]:0=开始,0.5=最远点,1=回到原点(带震荡) + // b = 起始值(原位置) + // c = 偏移量(最大偏移距离) + inline float pingPongSpring(float t, float b, float c) { + if (t <= 0.0f) return b; + if (t >= 1.0f) return b; // 最终回到原点! + float overshoot = 1.70158f; + if (t < 0.5f) { + // 前半段:从 0 → 1(冲到最远点) + t *= 2.0f; // 映射到 [0,1] + float val = t * t * ((overshoot + 1) * t - overshoot); + return b + c * val; + } else { + // 后半段:从 1 → 0(从最远点弹回原点,带过冲) + t = (t - 0.5f) * 2.0f; // 映射到 [0,1] + t -= 1; + float val = t * t * ((overshoot + 1) * t + overshoot) + 1; + return b + c * (1.0f - val); // 从 c 往回减到 0 + } + } + + // 通用插值函数 + inline float smoothMove(float t, float start, float end) { + float progress = easeInOutSine(t); // t ∈ [0,1] + return start + (end - start) * progress; + } + + } \ No newline at end of file