增加技能演示选项

This commit is contained in:
wyk
2026-04-28 18:28:46 +08:00
parent da741d1e56
commit c77b877b8b
12 changed files with 512 additions and 39 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 572 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 722 KiB

+18
View File
@@ -191,6 +191,16 @@ struct CellFlashEffect
COLORREF color;
};
struct GravityFallEffect
{
int ticks;
int totalTicks;
int x;
int fromY;
int toY;
int cellValue;
};
enum ScreenState
{
SCREEN_MENU = 0,
@@ -240,6 +250,7 @@ extern ClearEffectState clearEffectState;
extern FloatingTextEffect floatingTextEffects[8];
extern ParticleEffect particleEffects[96];
extern CellFlashEffect cellFlashEffects[64];
extern GravityFallEffect gravityFallEffects[80];
extern int currentScreen;
extern int currentMode;
extern int currentFallInterval;
@@ -270,11 +281,17 @@ void StartGameWithMode(int mode);
void ReturnToMainMenu();
void ReviveAfterVideo();
void StartRogueSkillDemo();
void StartRogueSkillDemoAt(int demoIndex);
bool IsRogueSkillDemoMode();
bool TickRogueSkillDemo();
void AdvanceRogueSkillDemo();
int GetRogueSkillDemoCount();
const TCHAR* GetRogueSkillDemoName(int demoIndex);
const TCHAR* GetRogueSkillDemoDetail(int demoIndex);
const TCHAR* GetCurrentRogueSkillDemoName();
void SetFeedbackMessage(const TCHAR* title, const TCHAR* detail, int ticks);
void OpenRulesScreen();
void OpenSkillDemoScreen();
void OpenCreditScreen();
void ChangeCreditPage(int direction);
void OpenUpgradeMenu();
@@ -292,6 +309,7 @@ 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 TriggerGravityFallEffect(int x, int fromY, int toY, int cellValue);
void AwardRogueSkillClearRewards(int clearedCells, int& scoreGain, int& expGain, bool allowLevelProgress);
void CheckRogueLevelProgress();
void ApplyBoardGravity();
+5
View File
@@ -84,6 +84,11 @@ void RollCurrentPieceSpecialFlags(bool allowRandomSpecials);
*/
void QueueLineClearEffect(const int* rows, int rowCount, int linesCleared);
/**
* @brief 记录固定方块受重力下落的轨迹,用于播放纵向残影特效。
*/
void TriggerGravityFallEffect(int x, int fromY, int toY, int cellValue);
/**
* @brief 尝试把旋转后的方块横向偏移指定格数后放置。
*/
+1
View File
@@ -12,6 +12,7 @@
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDM_SKILL_DEMO 106
#define IDI_TETRIS 107
#define IDI_SMALL 108
#define IDC_TETRIS 109
Binary file not shown.
+98 -4
View File
@@ -197,6 +197,30 @@ static RECT GetHelpOptionRect(HWND hWnd, int index)
return rect;
}
static RECT GetHelpSkillDemoItemRect(HWND hWnd, int index)
{
LayoutMetrics metrics = GetLayoutMetrics(hWnd);
RECT rulesCard = GetRulesCardRect(hWnd);
RECT contentRect =
{
rulesCard.left + ScaleValue(metrics, 36),
rulesCard.top + ScaleValue(metrics, 126),
rulesCard.right - ScaleValue(metrics, 36),
rulesCard.bottom - ScaleValue(metrics, 86)
};
int itemHeight = ScaleValue(metrics, 58);
int itemGap = ScaleValue(metrics, 10);
int itemTop = contentRect.top + ScaleValue(metrics, 8) - helpScrollOffset;
RECT rect =
{
contentRect.left,
itemTop + index * (itemHeight + itemGap),
contentRect.right,
itemTop + index * (itemHeight + itemGap) + itemHeight
};
return rect;
}
static RECT GetHelpBackHintRect(HWND hWnd)
{
LayoutMetrics metrics = GetLayoutMetrics(hWnd);
@@ -744,6 +768,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (wmId)
{
case IDM_SKILL_DEMO:
OpenSkillDemoScreen();
InvalidateRect(hWnd, nullptr, FALSE);
break;
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
@@ -1005,8 +1033,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
helpState.selectedIndex = i;
if (i == 3)
{
StartRogueSkillDemo();
ResetGameTimer(hWnd);
helpState.currentPage = 5;
helpState.selectedIndex = 0;
helpScrollOffset = 0;
}
else
{
@@ -1023,6 +1052,31 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
InvalidateRect(hWnd, nullptr, FALSE);
}
}
else if (helpState.currentPage == 5)
{
if (IsPointInRect(GetHelpBackHintRect(hWnd), mouseX, mouseY))
{
helpState.currentPage = 0;
helpState.selectedIndex = 3;
helpScrollOffset = 0;
InvalidateRect(hWnd, nullptr, FALSE);
}
else
{
int demoCount = GetRogueSkillDemoCount();
for (int i = 0; i < demoCount; i++)
{
if (IsPointInRect(GetHelpSkillDemoItemRect(hWnd, i), mouseX, mouseY))
{
helpState.selectedIndex = i;
StartRogueSkillDemoAt(i);
ResetGameTimer(hWnd);
InvalidateRect(hWnd, nullptr, FALSE);
break;
}
}
}
}
else if (IsPointInRect(GetHelpBackHintRect(hWnd), mouseX, mouseY))
{
if (helpState.currentPage == 4)
@@ -1256,6 +1310,19 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
ChangeCreditPage(-1);
InvalidateRect(hWnd, nullptr, FALSE);
}
else if (helpState.currentPage == 5)
{
helpState.selectedIndex--;
if (helpState.selectedIndex < 0)
{
helpState.selectedIndex = GetRogueSkillDemoCount() - 1;
}
if (helpState.selectedIndex * 68 < helpScrollOffset)
{
helpScrollOffset = helpState.selectedIndex * 68;
}
InvalidateRect(hWnd, nullptr, FALSE);
}
break;
case VK_DOWN:
case VK_RIGHT:
@@ -1275,6 +1342,20 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
ChangeCreditPage(1);
InvalidateRect(hWnd, nullptr, FALSE);
}
else if (helpState.currentPage == 5)
{
helpState.selectedIndex++;
if (helpState.selectedIndex >= GetRogueSkillDemoCount())
{
helpState.selectedIndex = 0;
helpScrollOffset = 0;
}
else if (helpState.selectedIndex * 68 > helpScrollOffset + 360)
{
helpScrollOffset = helpState.selectedIndex * 68 - 360;
}
InvalidateRect(hWnd, nullptr, FALSE);
}
break;
case VK_RETURN:
case VK_SPACE:
@@ -1282,8 +1363,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (helpState.selectedIndex == 3)
{
StartRogueSkillDemo();
ResetGameTimer(hWnd);
helpState.currentPage = 5;
helpState.selectedIndex = 0;
helpScrollOffset = 0;
}
else
{
@@ -1292,6 +1374,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
}
InvalidateRect(hWnd, nullptr, FALSE);
}
else if (helpState.currentPage == 5)
{
StartRogueSkillDemoAt(helpState.selectedIndex);
ResetGameTimer(hWnd);
InvalidateRect(hWnd, nullptr, FALSE);
}
break;
case VK_ESCAPE:
case VK_BACK:
@@ -1304,6 +1392,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
ReturnToMainMenu();
}
else if (helpState.currentPage == 5)
{
helpState.currentPage = 0;
helpState.selectedIndex = 3;
helpScrollOffset = 0;
}
else
{
helpState.currentPage = 0;
+2 -1
View File
@@ -15,7 +15,7 @@ int workRegion[20][10] = { 0 };
Point point = { 0, 0 };
Point target = { 0, 0 };
MenuState menuState = { 0, 4 };
HelpState helpState = { 0, 3, 0 };
HelpState helpState = { 0, 4, 0 };
int helpScrollOffset = 0;
int creditPageIndex = 0;
int creditAnimationTicks = 0;
@@ -29,6 +29,7 @@ ClearEffectState clearEffectState = { 0, 0, 0, {} };
FloatingTextEffect floatingTextEffects[8] = {};
ParticleEffect particleEffects[96] = {};
CellFlashEffect cellFlashEffects[64] = {};
GravityFallEffect gravityFallEffects[80] = {};
int currentScreen = SCREEN_MENU;
int currentMode = MODE_CLASSIC;
int currentFallInterval = 500;
+74 -1
View File
@@ -116,6 +116,11 @@ void ResetVisualEffects()
{
cellFlashEffects[i].ticks = 0;
}
for (int i = 0; i < 80; i++)
{
gravityFallEffects[i].ticks = 0;
}
}
/**
@@ -158,6 +163,15 @@ bool TickVisualEffects()
}
}
for (int i = 0; i < 80; i++)
{
if (gravityFallEffects[i].ticks > 0)
{
gravityFallEffects[i].ticks--;
active = true;
}
}
return active;
}
@@ -429,6 +443,51 @@ void TriggerColoredCellClearEffect(const Point* cells, int cellCount, COLORREF f
}
}
/**
* @brief 为一个受重力下落的固定方块记录纵向残影和落点粒子。
*/
void TriggerGravityFallEffect(int x, int fromY, int toY, int cellValue)
{
if (x < 0 || x >= nGameWidth || fromY < 0 || fromY >= nGameHeight ||
toY < 0 || toY >= nGameHeight || toY <= fromY || cellValue == 0)
{
return;
}
int effectIndex = -1;
for (int i = 0; i < 80; i++)
{
if (gravityFallEffects[i].ticks <= 0)
{
effectIndex = i;
break;
}
}
if (effectIndex < 0)
{
return;
}
int totalTicks = 12 + (toY - fromY) * 2;
if (totalTicks > 26)
{
totalTicks = 26;
}
gravityFallEffects[effectIndex].ticks = totalTicks;
gravityFallEffects[effectIndex].totalTicks = totalTicks;
gravityFallEffects[effectIndex].x = x;
gravityFallEffects[effectIndex].fromY = fromY;
gravityFallEffects[effectIndex].toY = toY;
gravityFallEffects[effectIndex].cellValue = cellValue;
COLORREF particleColor = BrickColor[(cellValue - 1) % 7];
AddParticle(x * 100 + 50, toY * 100 + 18, -2 - rand() % 5, -12 - rand() % 7, 4, particleColor);
AddParticle(x * 100 + 50, toY * 100 + 18, 2 + rand() % 5, -12 - rand() % 7, 4, particleColor);
AddCellFlash(x, toY, RGB(210, 245, 255), true);
}
/**
* @brief 判断指定方块、旋转状态和位置是否可以合法放置。
*/
@@ -575,6 +634,20 @@ void OpenRulesScreen()
/**
* @brief 打开致谢界面并重置致谢页切换状态。
*/
void OpenSkillDemoScreen()
{
rogueDemoMode = false;
currentScreen = SCREEN_RULES;
suspendFlag = false;
helpState.selectedIndex = 0;
helpState.optionCount = 4;
helpState.currentPage = 5;
helpScrollOffset = 0;
creditPageIndex = 0;
creditAnimationTicks = 0;
creditAnimationDirection = 0;
}
void OpenCreditScreen()
{
rogueDemoMode = false;
@@ -594,7 +667,7 @@ void OpenCreditScreen()
*/
void ChangeCreditPage(int direction)
{
constexpr int creditPageCount = 3;
constexpr int creditPageCount = 4;
if (direction == 0)
{
return;
+227 -23
View File
@@ -131,7 +131,7 @@ static Bitmap* LoadBackgroundImage()
*/
static Bitmap* LoadCreditImage(int index)
{
constexpr int creditPageCount = 3;
constexpr int creditPageCount = 4;
static ULONG_PTR gdiplusToken = 0;
static Bitmap* creditImages[creditPageCount] = {};
static bool attempted[creditPageCount] = {};
@@ -152,16 +152,25 @@ static Bitmap* LoadCreditImage(int index)
{
L"assets\\images\\qls.jpg",
L"assets\\images\\wyk.jpg",
L"assets\\images\\swj.jpg"
L"assets\\images\\swj.jpg",
L"assets\\images\\qhy.jpg"
};
const std::wstring candidates[] =
const std::wstring creditExtraCandidates[] =
{
BuildAssetPath(imageNames[index]),
BuildWorkingDirAssetPath(imageNames[index])
BuildWorkingDirAssetPath(imageNames[index]),
BuildAssetPath(L"assets\\images\\qhy.png"),
BuildWorkingDirAssetPath(L"assets\\images\\qhy.png"),
BuildAssetPath(L"assets\\images\\qhy.jpeg"),
BuildWorkingDirAssetPath(L"assets\\images\\qhy.jpeg"),
BuildAssetPath(L"assets\\images\\qhy.bmp"),
BuildWorkingDirAssetPath(L"assets\\images\\qhy.bmp")
};
int candidateCount = (index == 3) ? 8 : 2;
for (const std::wstring& candidate : candidates)
for (int i = 0; i < candidateCount; i++)
{
const std::wstring& candidate = creditExtraCandidates[i];
if (candidate.empty())
{
continue;
@@ -639,6 +648,10 @@ void TDrawScreen(HDC hdc, HWND hWnd)
{
helpTitle = _T("\u81f4\u8c22");
}
else if (helpState.currentPage == 5)
{
helpTitle = _T("\u6280\u80fd\u6f14\u793a");
}
DrawText(hdc, helpTitle, -1, &rulesTitleRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
HPEN rulesAccentPen = CreatePen(PS_SOLID, SS(3), accentColor);
@@ -880,21 +893,108 @@ void TDrawScreen(HDC hdc, HWND hWnd)
DeleteObject(contentClipRegion);
DeleteObject(oldClipRegion);
}
else if (helpState.currentPage == 5)
{
int demoCount = GetRogueSkillDemoCount();
int itemHeight = SS(58);
int itemGap = SS(10);
int contentHeight = contentRect.bottom - contentRect.top;
int virtualHeight = SS(8) + demoCount * (itemHeight + itemGap);
int maxHelpScroll = virtualHeight - contentHeight;
if (maxHelpScroll < 0)
{
maxHelpScroll = 0;
}
if (helpScrollOffset > maxHelpScroll)
{
helpScrollOffset = maxHelpScroll;
}
HRGN oldClipRegion = CreateRectRgn(0, 0, 0, 0);
int hasOldClipRegion = GetClipRgn(hdc, oldClipRegion);
HRGN contentClipRegion = CreateRectRgn(contentRect.left, contentRect.top, contentRect.right, contentRect.bottom);
SelectClipRgn(hdc, contentClipRegion);
int itemTop = contentRect.top + SS(8) - helpScrollOffset;
for (int i = 0; i < demoCount; i++)
{
RECT itemRect =
{
contentRect.left,
itemTop + i * (itemHeight + itemGap),
contentRect.right,
itemTop + i * (itemHeight + itemGap) + itemHeight
};
if (itemRect.bottom < contentRect.top || itemRect.top > contentRect.bottom)
{
continue;
}
bool selected = (i == helpState.selectedIndex);
COLORREF itemFill = selected ? RGB(255, 245, 249) : RGB(255, 252, 250);
COLORREF itemFrame = selected ? accentColor : frameColor;
HPEN itemPen = CreatePen(PS_SOLID, selected ? SS(2) : SS(1), itemFrame);
HBRUSH itemBrush = CreateSolidBrush(itemFill);
oldPen = (HPEN)SelectObject(hdc, itemPen);
oldBrush = (HBRUSH)SelectObject(hdc, itemBrush);
RoundRect(hdc, itemRect.left, itemRect.top, itemRect.right, itemRect.bottom, SS(18), SS(18));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(itemBrush);
DeleteObject(itemPen);
SetTextColor(hdc, selected ? titleColor : textColor);
SelectObject(hdc, sectionFont);
RECT nameRect =
{
itemRect.left + SS(22),
itemRect.top + SS(8),
itemRect.left + SS(210),
itemRect.bottom - SS(8)
};
DrawText(hdc, GetRogueSkillDemoName(i), -1, &nameRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
SetTextColor(hdc, RGB(112, 91, 104));
SelectObject(hdc, bodyFont);
RECT detailRect =
{
itemRect.left + SS(220),
itemRect.top + SS(8),
itemRect.right - SS(22),
itemRect.bottom - SS(8)
};
DrawText(hdc, GetRogueSkillDemoDetail(i), -1, &detailRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
}
if (hasOldClipRegion == 1)
{
SelectClipRgn(hdc, oldClipRegion);
}
else
{
SelectClipRgn(hdc, nullptr);
}
DeleteObject(contentClipRegion);
DeleteObject(oldClipRegion);
}
else if (helpState.currentPage == 4)
{
const int creditAnimationTotalTicks = 60;
constexpr int creditPageCount = 3;
constexpr int creditPageCount = 4;
const TCHAR* creditNames[creditPageCount] =
{
_T("qls"),
_T("wyk"),
_T("juju")
_T("juju"),
_T("qhy")
};
const TCHAR* creditTexts[creditPageCount] =
{
_T("\u611f\u8c22\u6fc0\u60c5\u6295\u8eab\u4e8e\u6d4b\u8bd5\u4e4b\u4e2d\u7684Lisa"),
_T("\u611f\u8c22\u70ed\u5ff1coding\u7684\u5c0f\u86cb\u7cd5"),
_T("\u611f\u8c22\u8bfe\u524d\u95f2\u91cc\u5077\u5fd9\u7684juju")
_T("\u611f\u8c22\u8bfe\u524d\u95f2\u91cc\u5077\u5fd9\u7684juju"),
_T("\u611f\u8c22qhy\u7684\u5929\u624d\u6784\u60f3")
};
int currentCredit = creditPageIndex;
@@ -946,9 +1046,11 @@ void TDrawScreen(HDC hdc, HWND hWnd)
previousOffset = currentOffset - creditAnimationDirection * slideDistance;
}
Bitmap* preloadedCreditImageA = LoadCreditImage(0);
Bitmap* preloadedCreditImageB = LoadCreditImage(1);
Bitmap* preloadedCreditImageC = LoadCreditImage(2);
Bitmap* preloadedCreditImages[creditPageCount] = {};
for (int i = 0; i < creditPageCount; i++)
{
preloadedCreditImages[i] = LoadCreditImage(i);
}
Graphics creditGraphics(hdc);
creditGraphics.SetInterpolationMode(InterpolationModeHighQualityBilinear);
@@ -959,14 +1061,10 @@ void TDrawScreen(HDC hdc, HWND hWnd)
OffsetRect(&shiftedImageArea, offset, 0);
OffsetRect(&shiftedTextArea, offset, 0);
Bitmap* creditImage = preloadedCreditImageA;
if (cardIndex == 1)
Bitmap* creditImage = nullptr;
if (cardIndex >= 0 && cardIndex < creditPageCount)
{
creditImage = preloadedCreditImageB;
}
else if (cardIndex == 2)
{
creditImage = preloadedCreditImageC;
creditImage = preloadedCreditImages[cardIndex];
}
if (creditImage != nullptr)
{
@@ -1083,7 +1181,7 @@ void TDrawScreen(HDC hdc, HWND hWnd)
SelectObject(hdc, oldPen);
DeleteObject(chevronPen);
}
if (helpState.currentPage != 3 && helpState.currentPage != 4)
if (helpState.currentPage != 3 && helpState.currentPage != 4 && helpState.currentPage != 5)
{
RECT calculateRect = { contentRect.left, contentRect.top, contentRect.right, contentRect.top };
DrawText(hdc, pageText, -1, &calculateRect, pageFlags | DT_CALCRECT);
@@ -1133,7 +1231,9 @@ void TDrawScreen(HDC hdc, HWND hWnd)
? _T("\u65b9\u5411\u952e / WASD \u5207\u6362\uff0cEnter / Space \u786e\u8ba4\uff0cEsc / M \u8fd4\u56de\u4e3b\u83dc\u5355")
: (helpState.currentPage == 4
? _T("\u5de6\u53f3\u65b9\u5411\u952e / A D \u5207\u6362\uff0cEsc / Backspace / M \u8fd4\u56de\u4e3b\u83dc\u5355")
: _T("\u9f20\u6807\u6eda\u8f6e\u4e0a\u4e0b\u7ffb\u52a8\uff0cEsc / Backspace / M \u8fd4\u56de\u5e2e\u52a9"));
: (helpState.currentPage == 5
? _T("\u70b9\u51fb\u6280\u80fd\u540d\u79f0\u6216 Enter \u6f14\u793a\uff0c\u6eda\u8f6e\u7ffb\u52a8\uff0cEsc / Backspace / M \u8fd4\u56de\u5e2e\u52a9")
: _T("\u9f20\u6807\u6eda\u8f6e\u4e0a\u4e0b\u7ffb\u52a8\uff0cEsc / Backspace / M \u8fd4\u56de\u5e2e\u52a9")));
DrawText(hdc, helpHint, -1, &backHintRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
SelectClipRgn(hdc, nullptr);
@@ -1373,6 +1473,72 @@ void TDrawScreen(HDC hdc, HWND hWnd)
}
}
for (int i = 0; i < 80; i++)
{
if (gravityFallEffects[i].ticks <= 0 || gravityFallEffects[i].totalTicks <= 0)
{
continue;
}
if (gravityFallEffects[i].x < 0 || gravityFallEffects[i].x >= nGameWidth ||
gravityFallEffects[i].fromY < 0 || gravityFallEffects[i].fromY >= nGameHeight ||
gravityFallEffects[i].toY < 0 || gravityFallEffects[i].toY >= nGameHeight)
{
continue;
}
int elapsed = gravityFallEffects[i].totalTicks - gravityFallEffects[i].ticks;
int travel = gravityFallEffects[i].toY - gravityFallEffects[i].fromY;
int offsetY = travel * grid * elapsed / gravityFallEffects[i].totalTicks;
int drawX = gameRect.left + gravityFallEffects[i].x * grid;
int fromPixelY = gameRect.top + gravityFallEffects[i].fromY * grid;
int toPixelY = gameRect.top + gravityFallEffects[i].toY * grid;
int currentPixelY = fromPixelY + offsetY;
int colorIndex = gravityFallEffects[i].cellValue - 1;
if (colorIndex < 0 || colorIndex >= 7)
{
colorIndex = (gravityFallEffects[i].x + gravityFallEffects[i].toY) % 7;
}
COLORREF fallColor = BrickColor[colorIndex];
int alpha = 56 + gravityFallEffects[i].ticks * 150 / gravityFallEffects[i].totalTicks;
int trailTop = fromPixelY + grid / 2;
int trailBottom = currentPixelY + grid / 2;
if (trailBottom < trailTop + SS(8))
{
trailBottom = trailTop + SS(8);
}
if (trailBottom > toPixelY + grid / 2)
{
trailBottom = toPixelY + grid / 2;
}
Graphics fallGraphics(hdc);
fallGraphics.SetSmoothingMode(SmoothingModeAntiAlias);
SolidBrush trailBrush(Color(alpha / 2, GetRValue(fallColor), GetGValue(fallColor), GetBValue(fallColor)));
fallGraphics.FillRectangle(
&trailBrush,
static_cast<INT>(drawX + SS(12)),
static_cast<INT>(trailTop),
static_cast<INT>(grid - SS(24)),
static_cast<INT>(trailBottom - trailTop));
SolidBrush ghostBrush(Color(alpha, GetRValue(fallColor), GetGValue(fallColor), GetBValue(fallColor)));
Pen ghostPen(Color(230, 255, 255, 255), static_cast<REAL>(SS(2)));
fallGraphics.FillRectangle(
&ghostBrush,
static_cast<INT>(drawX + SS(3)),
static_cast<INT>(currentPixelY + SS(3)),
static_cast<INT>(grid - SS(6)),
static_cast<INT>(grid - SS(6)));
fallGraphics.DrawRectangle(
&ghostPen,
static_cast<INT>(drawX + SS(3)),
static_cast<INT>(currentPixelY + SS(3)),
static_cast<INT>(grid - SS(6)),
static_cast<INT>(grid - SS(6)));
}
if (clearEffectState.ticks > 0 && clearEffectState.totalTicks > 0)
{
int elapsed = clearEffectState.totalTicks - clearEffectState.ticks;
@@ -1561,12 +1727,50 @@ void TDrawScreen(HDC hdc, HWND hWnd)
if (currentMode == MODE_ROGUE)
{
int progressTop = IsRogueSkillDemoMode() ? 350 : 270;
int progressBottom = IsRogueSkillDemoMode() ? 568 : 488;
int upgradeTop = IsRogueSkillDemoMode() ? 590 : 510;
if (IsRogueSkillDemoMode())
{
RECT demoSkillRect =
{
leftPanelRect.left + SS(20),
leftPanelRect.top + SS(270),
leftPanelRect.right - SS(20),
leftPanelRect.top + SS(332)
};
DrawPanelCardAlpha(demoSkillRect, RGB(255, 244, 248), RGB(232, 184, 202), 20, panelNestedAlpha);
SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(132, 102, 118));
RECT demoSkillLabelRect =
{
demoSkillRect.left + SS(18),
demoSkillRect.top + SS(8),
demoSkillRect.right - SS(18),
demoSkillRect.top + SS(26)
};
DrawText(hdc, _T("\u5f53\u524d\u6280\u80fd"), -1, &demoSkillLabelRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, sectionFont);
SetTextColor(hdc, titleColor);
RECT demoSkillNameRect =
{
demoSkillRect.left + SS(18),
demoSkillRect.top + SS(26),
demoSkillRect.right - SS(18),
demoSkillRect.bottom - SS(8)
};
DrawText(hdc, GetCurrentRogueSkillDemoName(), -1, &demoSkillNameRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
}
RECT progressRect =
{
leftPanelRect.left + SS(20),
leftPanelRect.top + SS(270),
leftPanelRect.top + SS(progressTop),
leftPanelRect.right - SS(20),
leftPanelRect.top + SS(488)
leftPanelRect.top + SS(progressBottom)
};
DrawPanelCardAlpha(progressRect, RGB(255, 248, 251), RGB(233, 191, 208), 24, panelAlpha);
@@ -1670,7 +1874,7 @@ void TDrawScreen(HDC hdc, HWND hWnd)
RECT upgradeListRect =
{
leftPanelRect.left + SS(20),
leftPanelRect.top + SS(510),
leftPanelRect.top + SS(upgradeTop),
leftPanelRect.right - SS(20),
leftPanelRect.bottom - SS(20)
};
+87 -10
View File
@@ -111,6 +111,7 @@ static int pendingUpgradeShockwaveRows = 0;
static bool pendingEvolutionImpactShockwave = false;
static int rogueDemoStepIndex = 0;
static int rogueDemoTicks = 0;
static bool rogueDemoAutoAdvance = true;
enum RogueDemoKind
{
@@ -194,6 +195,7 @@ static void ShowRogueDemoFloatingName(const TCHAR* name);
static void FillRogueDemoCell(int y, int x, int value);
static void FillRogueDemoRows(int firstRow, int lastRow, int baseValue);
static void SetRogueDemoCurrentPiece(int pieceType, int pieceState, int x, int y);
static void StartRogueSkillDemoInternal(int demoIndex, bool autoAdvance);
/**
* @brief 限制 Rogue 模式的下一方块预览数量。
@@ -1966,6 +1968,10 @@ void ApplyBoardGravity()
int cell = workRegion[y][x];
workRegion[y][x] = 0;
workRegion[writeY][x] = cell;
if (writeY != y)
{
TriggerGravityFallEffect(x, y, writeY, cell);
}
writeY--;
}
}
@@ -2772,16 +2778,89 @@ bool IsRogueSkillDemoMode()
return rogueDemoMode;
}
/**
* @brief 返回 Rogue 技能演示条目数量,供帮助页逐行绘制可点击名单。
*/
int GetRogueSkillDemoCount()
{
return kRogueDemoStepCount;
}
/**
* @brief 按序号返回 Rogue 技能演示名称。
*/
const TCHAR* GetRogueSkillDemoName(int demoIndex)
{
if (demoIndex < 0 || demoIndex >= kRogueDemoStepCount)
{
return _T("");
}
return kRogueDemoSteps[demoIndex].name;
}
/**
* @brief 按序号返回 Rogue 技能演示说明。
*/
const TCHAR* GetRogueSkillDemoDetail(int demoIndex)
{
if (demoIndex < 0 || demoIndex >= kRogueDemoStepCount)
{
return _T("");
}
return kRogueDemoSteps[demoIndex].detail;
}
/**
* @brief 返回当前正在演示的 Rogue 技能名称。
*/
const TCHAR* GetCurrentRogueSkillDemoName()
{
if (!rogueDemoMode)
{
return _T("");
}
return GetRogueSkillDemoName(rogueDemoStepIndex);
}
/**
* @brief 从帮助页进入 Rogue 技能演示,并播放第一段技能展示。
*/
void StartRogueSkillDemo()
{
StartRogueSkillDemoInternal(0, true);
}
/**
* @brief 从帮助页的技能名单进入指定 Rogue 技能演示。
*/
void StartRogueSkillDemoAt(int demoIndex)
{
StartRogueSkillDemoInternal(demoIndex, false);
}
/**
* @brief 进入 Rogue 技能演示并配置起始条目和是否自动轮播。
*/
static void StartRogueSkillDemoInternal(int demoIndex, bool autoAdvance)
{
if (demoIndex < 0)
{
demoIndex = 0;
}
if (demoIndex >= kRogueDemoStepCount)
{
demoIndex = kRogueDemoStepCount - 1;
}
currentMode = MODE_ROGUE;
currentScreen = SCREEN_PLAYING;
rogueDemoMode = true;
rogueDemoStepIndex = 0;
rogueDemoStepIndex = demoIndex;
rogueDemoTicks = 0;
rogueDemoAutoAdvance = autoAdvance;
Restart();
rogueDemoMode = true;
@@ -2805,10 +2884,13 @@ bool TickRogueSkillDemo()
return false;
}
rogueDemoTicks++;
if (rogueDemoTicks >= kRogueDemoStepTicks)
if (rogueDemoAutoAdvance)
{
AdvanceRogueSkillDemo();
rogueDemoTicks++;
if (rogueDemoTicks >= kRogueDemoStepTicks)
{
AdvanceRogueSkillDemo();
}
}
return true;
@@ -2876,12 +2958,7 @@ static void ResetRogueDemoBoard()
*/
static void ShowRogueDemoFloatingName(const TCHAR* name)
{
floatingTextEffects[0].ticks = 56;
floatingTextEffects[0].totalTicks = 56;
floatingTextEffects[0].boardX = 500;
floatingTextEffects[0].boardY = 980;
floatingTextEffects[0].color = RGB(255, 248, 250);
lstrcpyn(floatingTextEffects[0].text, name, sizeof(floatingTextEffects[0].text) / sizeof(TCHAR));
(void)name;
}
/**
Binary file not shown.

After

Width:  |  Height:  |  Size: 572 KiB