mirror of
https://github.com/zhenyan121/SporeBG-Conid.git
synced 2026-04-10 06:14:08 +08:00
feat: improve action animations
This commit is contained in:
@@ -110,7 +110,9 @@ bool GameSession::executeAction(int toRow, int toCol) {
|
|||||||
|
|
||||||
m_board->changeHP(toRow, toCol, -fromPiece->getATK());
|
m_board->changeHP(toRow, toCol, -fromPiece->getATK());
|
||||||
m_board->changeHP(fromRow, fromCol, -toPiece->getATK() * 0.5);
|
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) {
|
if (fromPiece->getHP() <= 0) {
|
||||||
m_gamePieceEventCallback(GamePieceEvent::REMOVE_PIECE, fromRow, fromCol, -1, -1);
|
m_gamePieceEventCallback(GamePieceEvent::REMOVE_PIECE, fromRow, fromCol, -1, -1);
|
||||||
m_board->removePieceAt(fromRow, fromCol);
|
m_board->removePieceAt(fromRow, fromCol);
|
||||||
@@ -121,6 +123,7 @@ bool GameSession::executeAction(int toRow, int toCol) {
|
|||||||
|
|
||||||
if (fromPiece->getHP() > 0) {
|
if (fromPiece->getHP() > 0) {
|
||||||
m_gamePieceEventCallback(GamePieceEvent::MOVE_PIECE, fromRow, fromCol, toRow, toCol);
|
m_gamePieceEventCallback(GamePieceEvent::MOVE_PIECE, fromRow, fromCol, toRow, toCol);
|
||||||
|
|
||||||
auto fromInfo = fromPiece->getPieceInfo();
|
auto fromInfo = fromPiece->getPieceInfo();
|
||||||
m_board->removePieceAt(fromRow, fromCol);
|
m_board->removePieceAt(fromRow, fromCol);
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ enum class GamePieceEvent {
|
|||||||
PLACE_PIECE,
|
PLACE_PIECE,
|
||||||
MOVE_PIECE,
|
MOVE_PIECE,
|
||||||
GROW_PIECE,
|
GROW_PIECE,
|
||||||
SPORE_PIECE
|
SPORE_PIECE,
|
||||||
|
FIGHT_PIECE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PieceInfo {
|
struct PieceInfo {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "BoardRenderer.h"
|
#include "BoardRenderer.h"
|
||||||
#include "game/Board.h"
|
#include "game/Board.h"
|
||||||
#include "core/Time.h"
|
#include "core/Time.h"
|
||||||
|
#include "utils/Tools.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
BoardRenderer::BoardRenderer(int WIDTH, int HEIGHT, SDL_Renderer* renderer, TextureManager* textureManager) :
|
BoardRenderer::BoardRenderer(int WIDTH, int HEIGHT, SDL_Renderer* renderer, TextureManager* textureManager) :
|
||||||
m_Width(WIDTH),
|
m_Width(WIDTH),
|
||||||
@@ -114,7 +115,8 @@ void BoardRenderer::drawPiece(std::optional<std::pair<int, int>> selectedPiece)
|
|||||||
float progess = m_pieceGrowStatus.currentTime / m_pieceGrowStatus.animationDuration;
|
float progess = m_pieceGrowStatus.currentTime / m_pieceGrowStatus.animationDuration;
|
||||||
m_textureManager->destoryTexture(rect, color);
|
m_textureManager->destoryTexture(rect, color);
|
||||||
auto renderColor = color;
|
auto renderColor = color;
|
||||||
renderColor.a = 255 * progess;
|
|
||||||
|
renderColor.a = Tools::smoothMove(progess, 0, 255);
|
||||||
auto texture = m_textureManager->createTextureFromRect(rect, renderColor);
|
auto texture = m_textureManager->createTextureFromRect(rect, renderColor);
|
||||||
SDL_RenderTexture(m_renderer, texture, nullptr, &rect);
|
SDL_RenderTexture(m_renderer, texture, nullptr, &rect);
|
||||||
continue;
|
continue;
|
||||||
@@ -167,21 +169,42 @@ void BoardRenderer::drawPiece(std::optional<std::pair<int, int>> selectedPiece)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pieceMoveStatus.isAnimating && col == m_pieceMoveStatus.toCol && row == m_pieceMoveStatus.toRow) {
|
if (m_pieceMoveStatus.isAnimating && col == m_pieceMoveStatus.toCol && row == m_pieceMoveStatus.toRow) {
|
||||||
//SDL_Log("rendering..\n");
|
//SDL_Log("rendering..\n");
|
||||||
m_pieceMoveStatus.currentTime += Time::deltaTime();
|
m_pieceMoveStatus.currentTime += Time::deltaTime();
|
||||||
if (m_pieceMoveStatus.currentTime > m_pieceMoveStatus.animationDuration) {
|
if (m_pieceMoveStatus.currentTime > m_pieceMoveStatus.animationDuration) {
|
||||||
m_pieceMoveStatus.currentTime = m_pieceMoveStatus.animationDuration;
|
m_pieceMoveStatus.currentTime = m_pieceMoveStatus.animationDuration;
|
||||||
m_pieceMoveStatus.isAnimating = false;
|
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);
|
|
||||||
}
|
}
|
||||||
|
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
|
1.0f
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
case (GamePieceEvent::FIGHT_PIECE):
|
||||||
|
m_pieceFightStatus = {
|
||||||
|
fromRow, fromCol,
|
||||||
|
toRow, toCol,
|
||||||
|
toY - fromY,
|
||||||
|
toX - fromX,
|
||||||
|
0.0f,
|
||||||
|
true,
|
||||||
|
rect,
|
||||||
|
1.0f
|
||||||
|
};
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 Board;
|
||||||
|
|
||||||
class BoardRenderer
|
class BoardRenderer
|
||||||
@@ -64,6 +77,8 @@ private:
|
|||||||
|
|
||||||
PieceGrowStatue m_pieceGrowStatus;
|
PieceGrowStatue m_pieceGrowStatus;
|
||||||
|
|
||||||
|
PieceFightStatue m_pieceFightStatus;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BoardRenderer(int WIDTH, int HEIGHT, SDL_Renderer* renderer, TextureManager* textureManager);
|
BoardRenderer(int WIDTH, int HEIGHT, SDL_Renderer* renderer, TextureManager* textureManager);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include <cmath>
|
||||||
|
static inline float easeInOutSine(float t) {
|
||||||
|
return -(cos(M_PI * t) - 1) / 2.0f;
|
||||||
|
}
|
||||||
namespace Tools {
|
namespace Tools {
|
||||||
inline std::pair<int, int> physicalToLogical(float physicalX, float physicalY, const Viewport& viewport) {
|
inline std::pair<int, int> physicalToLogical(float physicalX, float physicalY, const Viewport& viewport) {
|
||||||
std::pair<int, int> logicalPoint = {0 , 0};
|
std::pair<int, int> logicalPoint = {0 , 0};
|
||||||
@@ -16,4 +19,34 @@ namespace Tools {
|
|||||||
|
|
||||||
return logicalPoint;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user