From 8e68d9c71299437710db6394d86359a9d4382285 Mon Sep 17 00:00:00 2001 From: Qi-huanye <2728290997@qq.com> Date: Sun, 26 Apr 2026 17:59:24 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AA=81=E5=87=BA=E7=89=B9=E6=AE=8A=E6=96=B9?= =?UTF-8?q?=E5=9D=97=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/Tetris.h | 11 ++++++++ src/source/TetrisLogic.cpp | 1 + src/source/TetrisLogicInnovation.cpp | 42 ++++++++++++++++++++++++++++ src/source/TetrisRender.cpp | 41 +++++++++++++++++++++++++++ src/source/TetrisRogue.cpp | 6 ++-- 5 files changed, 98 insertions(+), 3 deletions(-) diff --git a/src/include/Tetris.h b/src/include/Tetris.h index 8410b98..79a0a09 100644 --- a/src/include/Tetris.h +++ b/src/include/Tetris.h @@ -182,6 +182,15 @@ struct ParticleEffect COLORREF color; }; +struct CellFlashEffect +{ + int ticks; + int totalTicks; + int x; + int y; + COLORREF color; +}; + enum ScreenState { SCREEN_MENU = 0, @@ -224,6 +233,7 @@ extern FeedbackState feedbackState; extern ClearEffectState clearEffectState; extern FloatingTextEffect floatingTextEffects[8]; extern ParticleEffect particleEffects[96]; +extern CellFlashEffect cellFlashEffects[64]; extern int currentScreen; extern int currentMode; extern int currentFallInterval; @@ -267,6 +277,7 @@ bool TickVisualEffects(); void TriggerLineClearEffect(const int* rows, int rowCount, int linesCleared); void PlayPendingLineClearEffect(); void TriggerCellClearEffect(const Point* cells, int cellCount, bool strongBurst); +void TriggerColoredCellClearEffect(const Point* cells, int cellCount, COLORREF flashColor, bool strongBurst); void AwardRogueSkillClearRewards(int clearedCells, int& scoreGain, int& expGain, bool allowLevelProgress); void CheckRogueLevelProgress(); void ApplyBoardGravity(); diff --git a/src/source/TetrisLogic.cpp b/src/source/TetrisLogic.cpp index 8bfc35c..b6a067e 100644 --- a/src/source/TetrisLogic.cpp +++ b/src/source/TetrisLogic.cpp @@ -22,6 +22,7 @@ FeedbackState feedbackState = { 0, _T(""), _T("") }; ClearEffectState clearEffectState = { 0, 0, 0, {} }; FloatingTextEffect floatingTextEffects[8] = {}; ParticleEffect particleEffects[96] = {}; +CellFlashEffect cellFlashEffects[64] = {}; int currentScreen = SCREEN_MENU; int currentMode = MODE_CLASSIC; int currentFallInterval = 500; diff --git a/src/source/TetrisLogicInnovation.cpp b/src/source/TetrisLogicInnovation.cpp index e532149..e8fddf9 100644 --- a/src/source/TetrisLogicInnovation.cpp +++ b/src/source/TetrisLogicInnovation.cpp @@ -111,6 +111,11 @@ void ResetVisualEffects() { particleEffects[i].ticks = 0; } + + for (int i = 0; i < 64; i++) + { + cellFlashEffects[i].ticks = 0; + } } /** @@ -144,6 +149,15 @@ bool TickVisualEffects() } } + for (int i = 0; i < 64; i++) + { + if (cellFlashEffects[i].ticks > 0) + { + cellFlashEffects[i].ticks--; + active = true; + } + } + return active; } @@ -252,6 +266,25 @@ static void AddBurstParticles(int boardX, int boardY, COLORREF baseColor, bool s } } +/** + * @brief 添加一个被清除格子的短时高亮效果。 + */ +static void AddCellFlash(int x, int y, COLORREF color, bool strongFlash) +{ + for (int i = 0; i < 64; i++) + { + if (cellFlashEffects[i].ticks <= 0) + { + cellFlashEffects[i].ticks = strongFlash ? 18 : 14; + cellFlashEffects[i].totalTicks = cellFlashEffects[i].ticks; + cellFlashEffects[i].x = x; + cellFlashEffects[i].y = y; + cellFlashEffects[i].color = color; + return; + } + } +} + /** * @brief 暂存消行动画,等待升级选择结束后再播放。 */ @@ -355,6 +388,14 @@ void TriggerLineClearEffect(const int* rows, int rowCount, int linesCleared) * @brief 为指定棋盘格集合触发清除粒子效果。 */ void TriggerCellClearEffect(const Point* cells, int cellCount, bool strongBurst) +{ + TriggerColoredCellClearEffect(cells, cellCount, RGB(255, 238, 120), strongBurst); +} + +/** + * @brief 为指定棋盘格集合触发带颜色区分的清除高亮和粒子效果。 + */ +void TriggerColoredCellClearEffect(const Point* cells, int cellCount, COLORREF flashColor, bool strongBurst) { if (cells == nullptr || cellCount <= 0) { @@ -369,6 +410,7 @@ void TriggerCellClearEffect(const Point* cells, int cellCount, bool strongBurst) } COLORREF particleColor = BrickColor[(cells[i].x + cells[i].y) % 7]; + AddCellFlash(cells[i].x, cells[i].y, flashColor, strongBurst); AddBurstParticles(cells[i].x * 100 + 50, cells[i].y * 100 + 50, particleColor, strongBurst); } } diff --git a/src/source/TetrisRender.cpp b/src/source/TetrisRender.cpp index e2bb580..38daad9 100644 --- a/src/source/TetrisRender.cpp +++ b/src/source/TetrisRender.cpp @@ -1042,6 +1042,47 @@ void TDrawScreen(HDC hdc, HWND hWnd) } } + for (int i = 0; i < 64; i++) + { + if (cellFlashEffects[i].ticks <= 0 || cellFlashEffects[i].totalTicks <= 0) + { + continue; + } + + if (cellFlashEffects[i].x < 0 || cellFlashEffects[i].x >= nGameWidth || + cellFlashEffects[i].y < 0 || cellFlashEffects[i].y >= nGameHeight) + { + continue; + } + + int alpha = 48 + cellFlashEffects[i].ticks * 168 / cellFlashEffects[i].totalTicks; + int pulseInset = SS(2 + (cellFlashEffects[i].totalTicks - cellFlashEffects[i].ticks) % 3); + RECT flashRect = + { + gameRect.left + cellFlashEffects[i].x * grid + pulseInset, + gameRect.top + cellFlashEffects[i].y * grid + pulseInset, + gameRect.left + (cellFlashEffects[i].x + 1) * grid - pulseInset, + gameRect.top + (cellFlashEffects[i].y + 1) * grid - pulseInset + }; + + Graphics cellGraphics(hdc); + cellGraphics.SetSmoothingMode(SmoothingModeAntiAlias); + SolidBrush cellBrush(Color(alpha, GetRValue(cellFlashEffects[i].color), GetGValue(cellFlashEffects[i].color), GetBValue(cellFlashEffects[i].color))); + Pen cellPen(Color(230, GetRValue(cellFlashEffects[i].color), GetGValue(cellFlashEffects[i].color), GetBValue(cellFlashEffects[i].color)), static_cast(SS(2))); + cellGraphics.FillRectangle( + &cellBrush, + static_cast(flashRect.left), + static_cast(flashRect.top), + static_cast(flashRect.right - flashRect.left), + static_cast(flashRect.bottom - flashRect.top)); + cellGraphics.DrawRectangle( + &cellPen, + static_cast(flashRect.left), + static_cast(flashRect.top), + static_cast(flashRect.right - flashRect.left), + static_cast(flashRect.bottom - flashRect.top)); + } + for (int i = 0; i < 96; i++) { if (particleEffects[i].ticks <= 0 || particleEffects[i].totalTicks <= 0) diff --git a/src/source/TetrisRogue.cpp b/src/source/TetrisRogue.cpp index 8591f01..859f3d8 100644 --- a/src/source/TetrisRogue.cpp +++ b/src/source/TetrisRogue.cpp @@ -888,7 +888,7 @@ int ClearExplosiveAreaAt(int centerY, int centerX) } } - TriggerCellClearEffect(clearedCells, clearedCellCount < 25 ? clearedCellCount : 25, true); + TriggerColoredCellClearEffect(clearedCells, clearedCellCount < 25 ? clearedCellCount : 25, RGB(255, 116, 78), true); return clearedCellCount; } @@ -919,7 +919,7 @@ int ClearColumnAt(int column) } } - TriggerCellClearEffect(clearedCells, clearedCellCount, false); + TriggerColoredCellClearEffect(clearedCells, clearedCellCount, RGB(120, 232, 255), false); return clearedCellCount; } @@ -950,7 +950,7 @@ int ClearRowAt(int row) } } - TriggerCellClearEffect(clearedCells, clearedCellCount, false); + TriggerColoredCellClearEffect(clearedCells, clearedCellCount, RGB(196, 255, 132), false); return clearedCellCount; }