完善帮助

This commit is contained in:
2026-04-26 14:28:22 +08:00
parent 96ab175877
commit 68967f66c6
4 changed files with 245 additions and 74 deletions
+8
View File
@@ -31,6 +31,13 @@ struct MenuState
int optionCount; int optionCount;
}; };
struct HelpState
{
int selectedIndex;
int optionCount;
int currentPage;
};
struct PlayerStats struct PlayerStats
{ {
int score; int score;
@@ -207,6 +214,7 @@ extern int workRegion[20][10];
extern Point point; extern Point point;
extern Point target; extern Point target;
extern MenuState menuState; extern MenuState menuState;
extern HelpState helpState;
extern PlayerStats classicStats; extern PlayerStats classicStats;
extern PlayerStats rogueStats; extern PlayerStats rogueStats;
extern UpgradeUiState upgradeUiState; extern UpgradeUiState upgradeUiState;
+44 -1
View File
@@ -698,10 +698,53 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{ {
switch (wParam) switch (wParam)
{ {
case VK_UP:
case VK_LEFT:
case 'W':
case 'A':
if (helpState.currentPage == 0)
{
helpState.selectedIndex--;
if (helpState.selectedIndex < 0)
{
helpState.selectedIndex = helpState.optionCount - 1;
}
InvalidateRect(hWnd, nullptr, FALSE);
}
break;
case VK_DOWN:
case VK_RIGHT:
case 'S':
case 'D':
if (helpState.currentPage == 0)
{
helpState.selectedIndex++;
if (helpState.selectedIndex >= helpState.optionCount)
{
helpState.selectedIndex = 0;
}
InvalidateRect(hWnd, nullptr, FALSE);
}
break;
case VK_RETURN:
case VK_SPACE:
if (helpState.currentPage == 0)
{
helpState.currentPage = helpState.selectedIndex + 1;
InvalidateRect(hWnd, nullptr, FALSE);
}
break;
case VK_ESCAPE: case VK_ESCAPE:
case VK_BACK: case VK_BACK:
case 'M': case 'M':
ReturnToMainMenu(); if (helpState.currentPage == 0)
{
ReturnToMainMenu();
}
else
{
helpState.currentPage = 0;
}
InvalidateRect(hWnd, nullptr, FALSE); InvalidateRect(hWnd, nullptr, FALSE);
break; break;
default: default:
+4
View File
@@ -14,6 +14,7 @@ int workRegion[20][10] = { 0 };
Point point = { 0, 0 }; Point point = { 0, 0 };
Point target = { 0, 0 }; Point target = { 0, 0 };
MenuState menuState = { 0, 2 }; MenuState menuState = { 0, 2 };
HelpState helpState = { 0, 3, 0 };
PlayerStats classicStats = { 0, 1, 0, 0, 0 }; PlayerStats classicStats = { 0, 1, 0, 0, 0 };
PlayerStats rogueStats = { 0, 1, 0, 30, 0, 100, 100, 0 }; PlayerStats rogueStats = { 0, 1, 0, 30, 0, 100, 100, 0 };
UpgradeUiState upgradeUiState = { 0, 0, 0, 0, {} }; UpgradeUiState upgradeUiState = { 0, 0, 0, 0, {} };
@@ -1268,4 +1269,7 @@ void OpenRulesScreen()
{ {
currentScreen = SCREEN_RULES; currentScreen = SCREEN_RULES;
suspendFlag = false; suspendFlag = false;
helpState.selectedIndex = 0;
helpState.optionCount = 3;
helpState.currentPage = 0;
} }
+189 -73
View File
@@ -387,14 +387,14 @@ void TDrawScreen(HDC hdc, HWND hWnd)
{ {
_T("\u7ecf\u5178\u6a21\u5f0f"), _T("\u7ecf\u5178\u6a21\u5f0f"),
_T("Rogue \u6a21\u5f0f"), _T("Rogue \u6a21\u5f0f"),
_T("\u6e38\u620f\u89c4\u5219") _T("\u5e2e\u52a9")
}; };
const TCHAR* modeDescriptions[3] = const TCHAR* modeDescriptions[3] =
{ {
_T("纯粹方块挑战,专注消行、堆叠与生存。"), _T("纯粹方块挑战,专注消行、堆叠与生存。"),
_T("在不断升级的棋盘中收集强化,构筑本局专属流派。"), _T("在不断升级的棋盘中收集强化,构筑本局专属流派。"),
_T("查看操作、成长、主动技能与特殊方块规则") _T("查看操作、模式规则与全部强化效果")
}; };
for (int i = 0; i < menuState.optionCount; i++) for (int i = 0; i < menuState.optionCount; i++)
@@ -502,7 +502,20 @@ void TDrawScreen(HDC hdc, HWND hWnd)
rulesCard.right - SS(36), rulesCard.right - SS(36),
rulesCard.top + SS(78) rulesCard.top + SS(78)
}; };
DrawText(hdc, _T("\u6e38\u620f\u89c4\u5219"), -1, &rulesTitleRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE); const TCHAR* helpTitle = _T("\u5e2e\u52a9");
if (helpState.currentPage == 1)
{
helpTitle = _T("\u6e38\u620f\u4ecb\u7ecd");
}
else if (helpState.currentPage == 2)
{
helpTitle = _T("\u64cd\u4f5c\u8bf4\u660e");
}
else if (helpState.currentPage == 3)
{
helpTitle = _T("\u5f3a\u5316\u56fe\u9274");
}
DrawText(hdc, helpTitle, -1, &rulesTitleRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
HPEN rulesAccentPen = CreatePen(PS_SOLID, SS(3), accentColor); HPEN rulesAccentPen = CreatePen(PS_SOLID, SS(3), accentColor);
oldPen = (HPEN)SelectObject(hdc, rulesAccentPen); oldPen = (HPEN)SelectObject(hdc, rulesAccentPen);
@@ -511,87 +524,187 @@ void TDrawScreen(HDC hdc, HWND hWnd)
SelectObject(hdc, oldPen); SelectObject(hdc, oldPen);
DeleteObject(rulesAccentPen); DeleteObject(rulesAccentPen);
RECT leftSection = RECT contentRect =
{ {
rulesCard.left + SS(36), rulesCard.left + SS(36),
rulesCard.top + SS(126), rulesCard.top + SS(126),
rulesCard.left + SS(330),
rulesCard.bottom - SS(86)
};
RECT rightSection =
{
rulesCard.left + SS(360),
rulesCard.top + SS(126),
rulesCard.right - SS(36), rulesCard.right - SS(36),
rulesCard.bottom - SS(86) rulesCard.bottom - SS(86)
}; };
SetTextColor(hdc, textColor); if (helpState.currentPage == 0)
SelectObject(hdc, sectionFont);
RECT sectionTitle =
{ {
leftSection.left, const TCHAR* optionTitles[3] =
leftSection.top, {
leftSection.right, _T("\u6e38\u620f\u4ecb\u7ecd"),
leftSection.top + SS(34) _T("\u64cd\u4f5c\u8bf4\u660e"),
}; _T("\u5f3a\u5316\u56fe\u9274")
DrawText(hdc, _T("\u57fa\u672c\u64cd\u4f5c"), -1, &sectionTitle, DT_LEFT | DT_VCENTER | DT_SINGLELINE); };
const TCHAR* optionDetails[3] =
{
_T("\u7ecf\u5178\u6a21\u5f0f\u3001Rogue \u6a21\u5f0f\u548c\u590d\u6d3b\u89c4\u5219\u6982\u89c8\u3002"),
_T("\u79fb\u52a8\u3001\u65cb\u8f6c\u3001\u786c\u964d\u3001Hold \u4e0e\u6280\u80fd\u5feb\u6377\u952e\u3002"),
_T("\u67e5\u770b Rogue \u6a21\u5f0f\u5168\u90e8\u5f3a\u5316\u7684\u7b80\u8981\u6548\u679c\u3002")
};
SelectObject(hdc, bodyFont); int optionHeight = SS(100);
RECT leftBody = int optionGap = SS(22);
{ int optionTop = contentRect.top + SS(18);
leftSection.left, for (int i = 0; i < helpState.optionCount; ++i)
leftSection.top + SS(48), {
leftSection.right, RECT optionRect =
leftSection.bottom {
}; contentRect.left,
DrawText( optionTop + i * (optionHeight + optionGap),
hdc, contentRect.right,
_T("\u2190 / A\uff1a\u5411\u5de6\u79fb\u52a8\r\n") optionTop + i * (optionHeight + optionGap) + optionHeight
_T("\u2192 / D\uff1a\u5411\u53f3\u79fb\u52a8\r\n") };
_T("\u2191 / W\uff1a\u65cb\u8f6c\u65b9\u5757\r\n") bool selected = (i == helpState.selectedIndex);
_T("\u2193 / S\uff1a\u8f6f\u964d\r\n") COLORREF optionFill = selected ? RGB(255, 245, 249) : RGB(255, 252, 250);
_T("Space\uff1a\u786c\u964d\r\n") COLORREF optionFrame = selected ? accentColor : frameColor;
_T("C / Shift\uff1a备用仓\uff08获得后\uff09\r\n") HPEN optionPen = CreatePen(PS_SOLID, selected ? SS(2) : SS(1), optionFrame);
_T("Z\uff1a黑洞奇点\uff08获得后\uff09\r\n") HBRUSH optionBrush = CreateSolidBrush(optionFill);
_T("X\uff1a清屏炸弹\uff08获得后\uff09\r\n") oldPen = (HPEN)SelectObject(hdc, optionPen);
_T("V\uff1a空中换形\uff08获得后\uff09\r\n") oldBrush = (HBRUSH)SelectObject(hdc, optionBrush);
_T("P\uff1a\u6682\u505c / \u7ee7\u7eed\r\n") RoundRect(hdc, optionRect.left, optionRect.top, optionRect.right, optionRect.bottom, SS(24), SS(24));
_T("R\uff1a\u91cd\u5f00\u5f53\u524d\u5bf9\u5c40\r\n") SelectObject(hdc, oldBrush);
_T("M\uff1a\u8fd4\u56de\u4e3b\u83dc\u5355"), SelectObject(hdc, oldPen);
-1, DeleteObject(optionBrush);
&leftBody, DeleteObject(optionPen);
DT_LEFT | DT_TOP | DT_WORDBREAK);
SelectObject(hdc, sectionFont); SetTextColor(hdc, selected ? titleColor : textColor);
RECT rulesSectionTitle = SelectObject(hdc, sectionFont);
{ RECT optionTitleRect =
rightSection.left, {
rightSection.top, optionRect.left + SS(28),
rightSection.right, optionRect.top + SS(16),
rightSection.top + SS(34) optionRect.right - SS(28),
}; optionRect.top + SS(48)
DrawText(hdc, _T("\u6a21\u5f0f\u89c4\u5219"), -1, &rulesSectionTitle, DT_LEFT | DT_VCENTER | DT_SINGLELINE); };
DrawText(hdc, optionTitles[i], -1, &optionTitleRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, bodyFont); SetTextColor(hdc, RGB(112, 91, 104));
RECT rulesBody = SelectObject(hdc, bodyFont);
RECT optionDetailRect =
{
optionRect.left + SS(28),
optionRect.top + SS(52),
optionRect.right - SS(28),
optionRect.bottom - SS(14)
};
DrawText(hdc, optionDetails[i], -1, &optionDetailRect, DT_LEFT | DT_TOP | DT_WORDBREAK);
}
}
else
{ {
rightSection.left, SetTextColor(hdc, textColor);
rightSection.top + SS(48), SelectObject(hdc, bodyFont);
rightSection.right, const TCHAR* pageText = _T("");
rightSection.bottom UINT pageFlags = DT_LEFT | DT_TOP | DT_WORDBREAK;
}; if (helpState.currentPage == 1)
DrawText( {
hdc, pageText =
_T("经典模式:没有成长与主动技能,只考验基础堆叠、消行和生存。\r\n\r\n") _T("经典模式:只考验堆叠、消行和生存。\r\n\r\n")
_T("Rogue \u6a21\u5f0f\uff1a消行得分数与 EXP。EXP 满后选择强化,逐步塑造本局能力\r\n\r\n") _T("Rogue消行得分 EXP,升级后选择强化\r\n\r\n")
_T("强化会带来爆破、雷霆、狂热、黑洞、备用仓等能力;部分进阶强化需要先掌握对应前置\r\n\r\n") _T("战斗越久危险越高,底部封锁区会压缩空间\r\n\r\n")
_T("战斗持续越久,危险等级越高,底部封锁区会逐步压缩可用空间"), _T("死亡后可以按 V 看视频复活一次,经典模式和 Rogue 模式都支持");
-1, }
&rulesBody, else if (helpState.currentPage == 2)
DT_LEFT | DT_TOP | DT_WORDBREAK); {
pageText =
_T("\u2190 / A\uff1a\u5411\u5de6\u79fb\u52a8\r\n")
_T("\u2192 / D\uff1a\u5411\u53f3\u79fb\u52a8\r\n")
_T("\u2191 / W\uff1a\u65cb\u8f6c\u65b9\u5757\r\n")
_T("\u2193 / S\uff1a\u8f6f\u964d\r\n")
_T("Space\uff1a\u786c\u964d\r\n")
_T("C / Shift\uff1a备用仓\uff08获得后\uff09\r\n")
_T("Z\uff1a黑洞奇点\uff08获得后\uff09\r\n")
_T("X\uff1a清屏炸弹\uff08获得后\uff09\r\n")
_T("V\uff1a空中换形\uff08获得后\uff09\r\n")
_T("P\uff1a\u6682\u505c / \u7ee7\u7eed\r\n")
_T("R\uff1a\u91cd\u5f00\u5f53\u524d\u5bf9\u5c40\r\n")
_T("M\uff1a\u8fd4\u56de\u4e3b\u83dc\u5355\r\n")
_T("死亡后 V:看视频复活一次");
}
else if (helpState.currentPage == 3)
{
const TCHAR* categoryNames[8] =
{
_T("基础"),
_T("保命 / 操作"),
_T("清场"),
_T("特殊方块"),
_T("进阶"),
_T("狂热 / 风险"),
_T("升级系"),
_T("构筑")
};
const TCHAR* categoryTexts[8] =
{
_T("赏金纹章:得分+20%\r\n成长印记:EXP+25%\r\n缓坠羽翼:下落变慢\r\n连击律动:连续消行加分;先见之眼:预览+1"),
_T("最后一搏:濒死清底3行\r\n备用仓:解锁 Hold\r\n完美旋转:卡墙修正\r\n时间缓流:高堆叠减速;空中换形:V 变 I 块"),
_T("卸压清场:清最高行\r\n底线清道夫:消行充能清底\r\n清屏炸弹:X 清底5行\r\n黑洞奇点:Z 吞噬最多方块"),
_T("爆破核心:爆破块清 3x3\r\n棱镜激光:清整列\r\n十字方块:清行列\r\n彩虹方块:补齐缺口;方块改造:提高 I 块概率"),
_T("连锁火花:消行追加破坏\r\n连环炸弹:爆破扩大 5x5\r\n雷霆四消:四消额外轰击\r\n雷霆棱镜:四消额外激光"),
_T("狂热节拍:20行进狂热\r\n怒火连段:连击加倍率\r\n无尽狂热:延长狂热\r\n高压悬赏 / 豪赌四消 / 极限玩家:高风险高收益"),
_T("双重抉择:升级多选1个\r\n命运轮盘:6选2但带诅咒\r\n升级冲击波 / 进化冲击:升级清底\r\n成长核心:永久得分 / EXP +15%"),
_T("操控大师:Hold 后减速并预览+1\r\n方块风暴:接下来全 I 块\r\n稳定结构:落地补洞\r\n虚空核心:黑洞和彩虹联动;赌徒契约:强化可能翻倍或落空")
};
int columnGap = SS(18);
int rowGap = SS(14);
int columnWidth = (contentRect.right - contentRect.left - columnGap) / 2;
int rowHeight = (contentRect.bottom - contentRect.top - rowGap * 3) / 4;
for (int i = 0; i < 8; ++i)
{
int column = i % 2;
int row = i / 2;
RECT categoryRect =
{
contentRect.left + column * (columnWidth + columnGap),
contentRect.top + row * (rowHeight + rowGap),
contentRect.left + column * (columnWidth + columnGap) + columnWidth,
contentRect.top + row * (rowHeight + rowGap) + rowHeight
};
HPEN categoryPen = CreatePen(PS_SOLID, 1, RGB(232, 202, 215));
HBRUSH categoryBrush = CreateSolidBrush(RGB(255, 252, 250));
oldPen = (HPEN)SelectObject(hdc, categoryPen);
oldBrush = (HBRUSH)SelectObject(hdc, categoryBrush);
RoundRect(hdc, categoryRect.left, categoryRect.top, categoryRect.right, categoryRect.bottom, SS(16), SS(16));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(categoryBrush);
DeleteObject(categoryPen);
SetTextColor(hdc, titleColor);
SelectObject(hdc, bodyFont);
RECT categoryTitleRect =
{
categoryRect.left + SS(16),
categoryRect.top + SS(10),
categoryRect.right - SS(16),
categoryRect.top + SS(34)
};
DrawText(hdc, categoryNames[i], -1, &categoryTitleRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
SetTextColor(hdc, RGB(86, 66, 80));
SelectObject(hdc, smallFont);
RECT categoryBodyRect =
{
categoryRect.left + SS(16),
categoryRect.top + SS(40),
categoryRect.right - SS(16),
categoryRect.bottom - SS(10)
};
DrawText(hdc, categoryTexts[i], -1, &categoryBodyRect, DT_LEFT | DT_TOP | DT_WORDBREAK);
}
}
if (helpState.currentPage != 3)
{
DrawText(hdc, pageText, -1, &contentRect, pageFlags);
}
}
SelectObject(hdc, smallFont); SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(128, 104, 118)); SetTextColor(hdc, RGB(128, 104, 118));
@@ -602,7 +715,10 @@ void TDrawScreen(HDC hdc, HWND hWnd)
rulesCard.right - SS(36), rulesCard.right - SS(36),
rulesCard.bottom - SS(24) rulesCard.bottom - SS(24)
}; };
DrawText(hdc, _T("Esc / Backspace / M \u8fd4\u56de\u4e3b\u83dc\u5355"), -1, &backHintRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); const TCHAR* helpHint = helpState.currentPage == 0
? _T("\u65b9\u5411\u952e / WASD \u5207\u6362\uff0cEnter / Space \u786e\u8ba4\uff0cEsc / M \u8fd4\u56de\u4e3b\u83dc\u5355")
: _T("Esc / Backspace / M \u8fd4\u56de\u5e2e\u52a9");
DrawText(hdc, helpHint, -1, &backHintRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
DrawMusicButton(); DrawMusicButton();
SelectObject(hdc, oldFont); SelectObject(hdc, oldFont);