增加技能演示选项
This commit is contained in:
+98
-4
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user