Files
Tereis/src/source/TetrisRender.cpp
T

1487 lines
60 KiB
C++

#include "stdafx.h"
#include "Tetris.h"
void TDrawScreen(HDC hdc, HWND hWnd)
{
RECT clientRect;
GetClientRect(hWnd, &clientRect);
int clientWidth = clientRect.right - clientRect.left;
int clientHeight = clientRect.bottom - clientRect.top;
int scaleX = MulDiv(clientWidth, 1000, WINDOW_CLIENT_WIDTH);
int scaleY = MulDiv(clientHeight, 1000, WINDOW_CLIENT_HEIGHT);
int scale = (scaleX < scaleY) ? scaleX : scaleY;
if (scale < 500)
{
scale = 500;
}
int layoutWidth = MulDiv(WINDOW_CLIENT_WIDTH, scale, 1000);
int layoutHeight = MulDiv(WINDOW_CLIENT_HEIGHT, scale, 1000);
int offsetX = (clientWidth - layoutWidth) / 2;
int offsetY = 0;
auto SX = [offsetX, scale](int value) -> int
{
return offsetX + MulDiv(value, scale, 1000);
};
auto SY = [offsetY, scale](int value) -> int
{
return offsetY + MulDiv(value, scale, 1000);
};
auto SS = [scale](int value) -> int
{
int result = MulDiv(value, scale, 1000);
return result < 1 ? 1 : result;
};
int grid = SS(GRID);
int panelGap = SS(SIDE_PANEL_GAP);
int panelWidth = SS(SIDE_PANEL_WIDTH);
int panelHeight = SS(SIDE_PANEL_HEIGHT - WINDOW_PADDING * 2);
int boardWidth = grid * nGameWidth;
int boardHeight = grid * nGameHeight;
const RECT gameRect =
{
SX(WINDOW_PADDING),
SY(WINDOW_PADDING),
SX(WINDOW_PADDING) + boardWidth,
SY(WINDOW_PADDING) + boardHeight
};
const RECT panelRect =
{
gameRect.right + panelGap,
SY(WINDOW_PADDING),
gameRect.right + panelGap + panelWidth,
SY(WINDOW_PADDING) + panelHeight
};
const COLORREF pageColor = RGB(255, 244, 248);
const COLORREF blobColorA = RGB(255, 230, 238);
const COLORREF blobColorB = RGB(250, 221, 233);
const COLORREF cardColor = RGB(255, 252, 253);
const COLORREF boardColor = RGB(70, 57, 78);
const COLORREF boardInnerColor = RGB(54, 44, 62);
const COLORREF lineColor = RGB(104, 90, 116);
const COLORREF frameColor = RGB(212, 168, 188);
const COLORREF titleColor = RGB(104, 62, 84);
const COLORREF textColor = RGB(92, 73, 88);
const COLORREF accentColor = RGB(228, 145, 182);
HBRUSH pageBrush = CreateSolidBrush(pageColor);
FillRect(hdc, &clientRect, pageBrush);
DeleteObject(pageBrush);
HBRUSH blobBrushA = CreateSolidBrush(blobColorA);
HBRUSH blobBrushB = CreateSolidBrush(blobColorB);
HBRUSH oldBrush = (HBRUSH)SelectObject(hdc, blobBrushA);
HPEN oldPen = (HPEN)SelectObject(hdc, GetStockObject(NULL_PEN));
Ellipse(hdc, clientRect.right - 260, -20, clientRect.right + 80, 260);
Ellipse(hdc, -80, clientRect.bottom - 200, 220, clientRect.bottom + 70);
SelectObject(hdc, blobBrushB);
Ellipse(hdc, clientRect.right - 180, clientRect.bottom - 220, clientRect.right + 120, clientRect.bottom + 40);
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(blobBrushA);
DeleteObject(blobBrushB);
HFONT titleFont = CreateFont(
-SS(34), 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_NATURAL_QUALITY,
VARIABLE_PITCH, _T("Microsoft YaHei UI"));
HFONT sectionFont = CreateFont(
-SS(24), 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_NATURAL_QUALITY,
VARIABLE_PITCH, _T("Microsoft YaHei UI"));
HFONT bodyFont = CreateFont(
-SS(20), 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_NATURAL_QUALITY,
VARIABLE_PITCH, _T("Microsoft YaHei UI"));
HFONT smallFont = CreateFont(
-SS(17), 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_NATURAL_QUALITY,
VARIABLE_PITCH, _T("Microsoft YaHei UI"));
SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, textColor);
auto DrawPanelCard = [&](const RECT& rect, COLORREF fillColor, COLORREF borderColor, int radius)
{
HBRUSH cardBrush = CreateSolidBrush(fillColor);
HPEN cardPen = CreatePen(PS_SOLID, 1, borderColor);
HGDIOBJ savedPen = SelectObject(hdc, cardPen);
HGDIOBJ savedBrush = SelectObject(hdc, cardBrush);
RoundRect(hdc, rect.left, rect.top, rect.right, rect.bottom, SS(radius), SS(radius));
SelectObject(hdc, savedBrush);
SelectObject(hdc, savedPen);
DeleteObject(cardBrush);
DeleteObject(cardPen);
};
if (currentScreen == SCREEN_MENU)
{
RECT menuCard =
{
SX(110),
SY(70),
SX(WINDOW_CLIENT_WIDTH - 110),
SY(WINDOW_CLIENT_HEIGHT - 70)
};
HPEN menuFramePen = CreatePen(PS_SOLID, 1, frameColor);
HBRUSH menuCardBrush = CreateSolidBrush(cardColor);
oldPen = (HPEN)SelectObject(hdc, menuFramePen);
oldBrush = (HBRUSH)SelectObject(hdc, menuCardBrush);
RoundRect(hdc, menuCard.left, menuCard.top, menuCard.right, menuCard.bottom, SS(34), SS(34));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(menuCardBrush);
DeleteObject(menuFramePen);
HFONT oldFont = (HFONT)SelectObject(hdc, titleFont);
SetTextColor(hdc, titleColor);
RECT titleRect =
{
menuCard.left,
menuCard.top + SS(24),
menuCard.right,
menuCard.top + SS(70)
};
DrawText(hdc, _T("Rogue Tetris"), -1, &titleRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
RECT subtitleRect =
{
menuCard.left,
menuCard.top + SS(72),
menuCard.right,
menuCard.top + SS(110)
};
SelectObject(hdc, bodyFont);
SetTextColor(hdc, textColor);
DrawText(hdc, _T("\u8bf7\u9009\u62e9\u5f00\u59cb\u6a21\u5f0f"), -1, &subtitleRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
const TCHAR* modeNames[3] =
{
_T("\u7ecf\u5178\u6a21\u5f0f"),
_T("Rogue \u6a21\u5f0f"),
_T("\u6e38\u620f\u89c4\u5219")
};
const TCHAR* modeDescriptions[3] =
{
_T("\u4fdd\u7559\u5f53\u524d\u539f\u7248\u4fc4\u7f57\u65af\u65b9\u5757\u73a9\u6cd5\uff0c\u76f4\u63a5\u5f00\u59cb\u5bf9\u5c40\u3002"),
_T("\u8fdb\u5165 Rogue \u6a21\u5f0f\uff0c\u5df2\u63a5\u5165\u72ec\u7acb HUD \u4e0e\u7b49\u7ea7 / \u7ecf\u9a8c\u7ed3\u7b97\u3002"),
_T("\u5355\u72ec\u67e5\u770b\u64cd\u4f5c\u65b9\u5f0f\u3001Rogue \u673a\u5236\u4e0e\u5f53\u524d\u7248\u672c\u8bf4\u660e\u3002")
};
for (int i = 0; i < menuState.optionCount; i++)
{
bool isSelected = (i == menuState.selectedIndex);
int top = menuCard.top + SS(140) + i * SS(130);
RECT optionRect =
{
menuCard.left + SS(36),
top,
menuCard.right - SS(36),
top + SS(104)
};
HBRUSH optionBrush = CreateSolidBrush(isSelected ? RGB(255, 232, 240) : RGB(255, 247, 250));
HPEN optionPen = CreatePen(PS_SOLID, isSelected ? SS(3) : 1, isSelected ? accentColor : RGB(226, 198, 210));
oldPen = (HPEN)SelectObject(hdc, optionPen);
oldBrush = (HBRUSH)SelectObject(hdc, optionBrush);
RoundRect(hdc, optionRect.left, optionRect.top, optionRect.right, optionRect.bottom, SS(24), SS(24));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(optionBrush);
DeleteObject(optionPen);
RECT modeNameRect =
{
optionRect.left + SS(24),
optionRect.top + SS(14),
optionRect.right - SS(24),
optionRect.top + SS(44)
};
RECT modeDescriptionRect =
{
optionRect.left + SS(24),
optionRect.top + SS(46),
optionRect.right - SS(24),
optionRect.bottom - SS(14)
};
SelectObject(hdc, sectionFont);
SetTextColor(hdc, isSelected ? titleColor : textColor);
DrawText(hdc, modeNames[i], -1, &modeNameRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(118, 96, 110));
DrawText(hdc, modeDescriptions[i], -1, &modeDescriptionRect, DT_LEFT | DT_WORDBREAK);
}
RECT hintRect =
{
menuCard.left + SS(36),
menuCard.bottom - SS(92),
menuCard.right - SS(36),
menuCard.bottom - SS(36)
};
SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(128, 104, 118));
DrawText(hdc, _T("\u65b9\u5411\u952e / WASD \u5207\u6362\uff0cEnter \u6216 Space \u786e\u8ba4\uff0cEsc \u9000\u51fa"), -1, &hintRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, oldFont);
DeleteObject(titleFont);
DeleteObject(sectionFont);
DeleteObject(bodyFont);
DeleteObject(smallFont);
return;
}
if (currentScreen == SCREEN_RULES)
{
RECT rulesCard =
{
SX(76),
SY(54),
SX(WINDOW_CLIENT_WIDTH - 76),
SY(WINDOW_CLIENT_HEIGHT - 54)
};
HPEN rulesPen = CreatePen(PS_SOLID, 1, frameColor);
HBRUSH rulesBrush = CreateSolidBrush(cardColor);
HFONT oldFont = (HFONT)SelectObject(hdc, titleFont);
oldPen = (HPEN)SelectObject(hdc, rulesPen);
oldBrush = (HBRUSH)SelectObject(hdc, rulesBrush);
RoundRect(hdc, rulesCard.left, rulesCard.top, rulesCard.right, rulesCard.bottom, SS(34), SS(34));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(rulesBrush);
DeleteObject(rulesPen);
SetTextColor(hdc, titleColor);
RECT rulesTitleRect =
{
rulesCard.left + SS(36),
rulesCard.top + SS(26),
rulesCard.right - SS(36),
rulesCard.top + SS(78)
};
DrawText(hdc, _T("\u6e38\u620f\u89c4\u5219"), -1, &rulesTitleRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
HPEN rulesAccentPen = CreatePen(PS_SOLID, SS(3), accentColor);
oldPen = (HPEN)SelectObject(hdc, rulesAccentPen);
MoveToEx(hdc, rulesCard.left + SS(38), rulesCard.top + SS(92), nullptr);
LineTo(hdc, rulesCard.left + SS(186), rulesCard.top + SS(92));
SelectObject(hdc, oldPen);
DeleteObject(rulesAccentPen);
RECT leftSection =
{
rulesCard.left + SS(36),
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.bottom - SS(86)
};
SetTextColor(hdc, textColor);
SelectObject(hdc, sectionFont);
RECT sectionTitle =
{
leftSection.left,
leftSection.top,
leftSection.right,
leftSection.top + SS(34)
};
DrawText(hdc, _T("\u57fa\u672c\u64cd\u4f5c"), -1, &sectionTitle, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, bodyFont);
RECT leftBody =
{
leftSection.left,
leftSection.top + SS(48),
leftSection.right,
leftSection.bottom
};
DrawText(
hdc,
_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\uff1aHold\uff08\u89e3\u9501\u540e\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"),
-1,
&leftBody,
DT_LEFT | DT_TOP | DT_WORDBREAK);
SelectObject(hdc, sectionFont);
RECT rulesSectionTitle =
{
rightSection.left,
rightSection.top,
rightSection.right,
rightSection.top + SS(34)
};
DrawText(hdc, _T("\u6a21\u5f0f\u89c4\u5219"), -1, &rulesSectionTitle, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, bodyFont);
RECT rulesBody =
{
rightSection.left,
rightSection.top + SS(48),
rightSection.right,
rightSection.bottom
};
DrawText(
hdc,
_T("\u7ecf\u5178\u6a21\u5f0f\uff1a\u4fdd\u6301\u539f\u7248\u4fc4\u7f57\u65af\u65b9\u5757\u73a9\u6cd5\uff0c\u4ee5\u6d88\u884c\u548c\u751f\u5b58\u4e3a\u4e3b\u3002\r\n\r\n")
_T("Rogue \u6a21\u5f0f\uff1a\u6d88\u884c\u540e\u9664\u4e86\u83b7\u5f97\u5206\u6570\uff0c\u8fd8\u4f1a\u83b7\u5f97 EXP\u3002EXP \u8fbe\u5230\u9608\u503c\u540e\u89e6\u53d1\u5347\u7ea7\uff0c\u4ece\u4e09\u4e2a\u5f3a\u5316\u4e2d\u9009\u4e00\u4e2a\u3002\r\n\r\n")
_T("\u5f53\u524d\u5df2\u63a5\u5165\uff1a\u7206\u7834\u8def\u7ebf\u3001\u96f7\u7535\u8def\u7ebf\u3001\u72c2\u70ed\u8def\u7ebf\u53ca\u591a\u79cd Rogue \u7279\u6b8a\u5f3a\u5316\u3002\r\n\r\n")
_T("\u63d0\u793a\uff1a\u6682\u505c\u3001\u5931\u8d25\u548c\u5347\u7ea7\u4f1a\u8fdb\u5165\u4e0d\u540c\u754c\u9762\uff0c\u8bf7\u6839\u636e\u5c4f\u5e55\u63d0\u793a\u64cd\u4f5c\u3002"),
-1,
&rulesBody,
DT_LEFT | DT_TOP | DT_WORDBREAK);
SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(128, 104, 118));
RECT backHintRect =
{
rulesCard.left + SS(36),
rulesCard.bottom - SS(58),
rulesCard.right - SS(36),
rulesCard.bottom - SS(24)
};
DrawText(hdc, _T("Esc / Backspace / M \u8fd4\u56de\u4e3b\u83dc\u5355"), -1, &backHintRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, oldFont);
DeleteObject(titleFont);
DeleteObject(sectionFont);
DeleteObject(bodyFont);
DeleteObject(smallFont);
return;
}
HPEN framePen = CreatePen(PS_SOLID, 1, frameColor);
HBRUSH gameCardBrush = CreateSolidBrush(cardColor);
HBRUSH panelBrush = CreateSolidBrush(cardColor);
oldPen = (HPEN)SelectObject(hdc, framePen);
oldBrush = (HBRUSH)SelectObject(hdc, gameCardBrush);
RoundRect(hdc, gameRect.left - SS(10), gameRect.top - SS(10), gameRect.right + SS(10), gameRect.bottom + SS(10), SS(28), SS(28));
SelectObject(hdc, panelBrush);
RoundRect(hdc, panelRect.left, panelRect.top, panelRect.right, panelRect.bottom, SS(30), SS(30));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(gameCardBrush);
DeleteObject(panelBrush);
DeleteObject(framePen);
HBRUSH boardBrush = CreateSolidBrush(boardColor);
FillRect(hdc, &gameRect, boardBrush);
DeleteObject(boardBrush);
RECT innerRect =
{
gameRect.left + SS(6),
gameRect.top + SS(6),
gameRect.right - SS(6),
gameRect.bottom - SS(6)
};
HBRUSH innerBrush = CreateSolidBrush(boardInnerColor);
FillRect(hdc, &innerRect, innerBrush);
DeleteObject(innerBrush);
HPEN borderPen = CreatePen(PS_SOLID, SS(2), RGB(132, 108, 146));
oldPen = (HPEN)SelectObject(hdc, borderPen);
oldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(NULL_BRUSH));
RoundRect(hdc, gameRect.left, gameRect.top, gameRect.right, gameRect.bottom, SS(18), SS(18));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(borderPen);
HPEN gridPen = CreatePen(PS_SOLID, 1, lineColor);
oldPen = (HPEN)SelectObject(hdc, gridPen);
for (int i = 1; i < nGameWidth; i++)
{
int x = gameRect.left + i * grid;
MoveToEx(hdc, x, gameRect.top, nullptr);
LineTo(hdc, x, gameRect.bottom);
}
for (int i = 1; i < nGameHeight; i++)
{
int y = gameRect.top + i * grid;
MoveToEx(hdc, gameRect.left, y, nullptr);
LineTo(hdc, gameRect.right, y);
}
SelectObject(hdc, oldPen);
DeleteObject(gridPen);
for (int i = 0; i < nGameHeight; i++)
{
for (int j = 0; j < nGameWidth; j++)
{
if (workRegion[i][j] != 0)
{
int colorIndex = workRegion[i][j] - 1;
RECT brickRect =
{
gameRect.left + j * grid + SS(2),
gameRect.top + i * grid + SS(2),
gameRect.left + (j + 1) * grid - SS(2),
gameRect.top + (i + 1) * grid - SS(2)
};
HBRUSH brickBrush = CreateSolidBrush(BrickColor[colorIndex]);
HPEN brickPen = CreatePen(PS_SOLID, 1, RGB(255, 248, 250));
oldPen = (HPEN)SelectObject(hdc, brickPen);
oldBrush = (HBRUSH)SelectObject(hdc, brickBrush);
RoundRect(hdc, brickRect.left, brickRect.top, brickRect.right, brickRect.bottom, SS(10), SS(10));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(brickBrush);
DeleteObject(brickPen);
}
}
}
if (targetFlag && !gameOverFlag)
{
HPEN targetPen = CreatePen(PS_DOT, SS(2), RGB(255, 240, 245));
oldPen = (HPEN)SelectObject(hdc, targetPen);
oldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(NULL_BRUSH));
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (bricks[type][state][i][j] != 0)
{
int drawY = target.y + i;
int drawX = target.x + j;
if (drawY >= 0 && drawY < nGameHeight && drawX >= 0 && drawX < nGameWidth)
{
RoundRect(
hdc,
gameRect.left + drawX * grid + SS(5),
gameRect.top + drawY * grid + SS(5),
gameRect.left + (drawX + 1) * grid - SS(5),
gameRect.top + (drawY + 1) * grid - SS(5),
SS(8), SS(8));
}
}
}
}
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(targetPen);
}
if (!gameOverFlag)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (bricks[type][state][i][j] != 0)
{
int drawY = point.y + i;
int drawX = point.x + j;
if (drawY >= 0 && drawY < nGameHeight && drawX >= 0 && drawX < nGameWidth)
{
RECT brickRect =
{
gameRect.left + drawX * grid + SS(2),
gameRect.top + drawY * grid + SS(2),
gameRect.left + (drawX + 1) * grid - SS(2),
gameRect.top + (drawY + 1) * grid - SS(2)
};
HBRUSH brickBrush = CreateSolidBrush(BrickColor[type]);
COLORREF activeOutlineColor = RGB(255, 250, 252);
int activeOutlineWidth = 1;
if (currentPieceIsExplosive)
{
activeOutlineColor = RGB(255, 214, 82);
activeOutlineWidth = SS(3);
}
else if (currentPieceIsLaser)
{
activeOutlineColor = RGB(120, 232, 255);
activeOutlineWidth = SS(3);
}
HPEN brickPen = CreatePen(PS_SOLID, activeOutlineWidth, activeOutlineColor);
oldPen = (HPEN)SelectObject(hdc, brickPen);
oldBrush = (HBRUSH)SelectObject(hdc, brickBrush);
RoundRect(hdc, brickRect.left, brickRect.top, brickRect.right, brickRect.bottom, SS(12), SS(12));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(brickBrush);
DeleteObject(brickPen);
}
}
}
}
}
HFONT oldFont = (HFONT)SelectObject(hdc, titleFont);
SetTextColor(hdc, titleColor);
TextOut(hdc, panelRect.left + SS(24), panelRect.top + SS(22), _T("\u4fc4\u7f57\u65af\u65b9\u5757"), lstrlen(_T("\u4fc4\u7f57\u65af\u65b9\u5757")));
HPEN accentPen = CreatePen(PS_SOLID, SS(3), accentColor);
oldPen = (HPEN)SelectObject(hdc, accentPen);
MoveToEx(hdc, panelRect.left + SS(24), panelRect.top + SS(68), nullptr);
LineTo(hdc, panelRect.left + SS(160), panelRect.top + SS(68));
SelectObject(hdc, oldPen);
DeleteObject(accentPen);
SelectObject(hdc, sectionFont);
SetTextColor(hdc, textColor);
RECT overviewRect =
{
panelRect.left + SS(20),
panelRect.top + SS(92),
panelRect.right - SS(20),
panelRect.top + SS(208)
};
DrawPanelCard(overviewRect, RGB(255, 247, 250), RGB(233, 191, 208), 24);
TCHAR scoreText[64];
_stprintf_s(scoreText, _T("\u5f53\u524d\u5f97\u5206 %d"), tScore);
TextOut(hdc, overviewRect.left + SS(18), overviewRect.top + SS(16), scoreText, lstrlen(scoreText));
TCHAR modeText[64];
_stprintf_s(modeText, _T("\u5f53\u524d\u6a21\u5f0f %s"), currentMode == MODE_CLASSIC ? _T("\u7ecf\u5178") : _T("Rogue"));
TextOut(hdc, overviewRect.left + SS(18), overviewRect.top + SS(48), modeText, lstrlen(modeText));
TCHAR linesText[64];
int totalLines = (currentMode == MODE_CLASSIC) ? classicStats.totalLinesCleared : rogueStats.totalLinesCleared;
_stprintf_s(linesText, _T("\u7d2f\u8ba1\u6d88\u884c %d"), totalLines);
TextOut(hdc, overviewRect.left + SS(18), overviewRect.top + SS(80), linesText, lstrlen(linesText));
if (currentMode == MODE_ROGUE)
{
RECT progressRect =
{
panelRect.left + SS(20),
panelRect.top + SS(224),
panelRect.right - SS(20),
panelRect.top + SS(364)
};
DrawPanelCard(progressRect, RGB(255, 248, 251), RGB(233, 191, 208), 24);
TCHAR levelText[64];
_stprintf_s(levelText, _T("\u5f53\u524d\u7b49\u7ea7 %d"), rogueStats.level);
TextOut(hdc, progressRect.left + SS(18), progressRect.top + SS(16), levelText, lstrlen(levelText));
TCHAR expText[64];
_stprintf_s(expText, _T("EXP %d / %d"), rogueStats.exp, rogueStats.requiredExp);
TextOut(hdc, progressRect.left + SS(18), progressRect.top + SS(46), expText, lstrlen(expText));
RECT expBarRect =
{
progressRect.left + SS(18),
progressRect.top + SS(82),
progressRect.right - SS(18),
progressRect.top + SS(106)
};
HBRUSH expTrackBrush = CreateSolidBrush(RGB(240, 220, 229));
FillRect(hdc, &expBarRect, expTrackBrush);
DeleteObject(expTrackBrush);
RECT expFillRect = expBarRect;
int expWidth = expBarRect.right - expBarRect.left;
if (rogueStats.requiredExp > 0)
{
expFillRect.right = expBarRect.left + expWidth * rogueStats.exp / rogueStats.requiredExp;
}
if (expFillRect.right < expFillRect.left)
{
expFillRect.right = expFillRect.left;
}
HBRUSH expFillBrush = CreateSolidBrush(accentColor);
FillRect(hdc, &expFillRect, expFillBrush);
DeleteObject(expFillBrush);
RECT growthRect =
{
progressRect.left + SS(18),
progressRect.top + SS(118),
progressRect.right - SS(18),
progressRect.bottom - SS(16)
};
SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(122, 95, 110));
TCHAR growthText[128];
_stprintf_s(
growthText,
_T("\u5206\u6570 %d%% EXP %d%% \u901f\u5ea6 %dms"),
rogueStats.scoreMultiplierPercent,
rogueStats.expMultiplierPercent,
currentFallInterval);
DrawText(hdc, growthText, -1, &growthRect, DT_LEFT | DT_TOP | DT_WORDBREAK);
RECT combatRect =
{
panelRect.left + SS(20),
panelRect.top + SS(382),
panelRect.right - SS(20),
panelRect.top + SS(492)
};
DrawPanelCard(combatRect, RGB(255, 247, 250), RGB(233, 191, 208), 24);
SelectObject(hdc, sectionFont);
SetTextColor(hdc, textColor);
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(16), _T("\u5f53\u524d\u6218\u6597\u72b6\u6001"), lstrlen(_T("\u5f53\u524d\u6218\u6597\u72b6\u6001")));
SelectObject(hdc, bodyFont);
TCHAR comboText[64];
_stprintf_s(comboText, _T("\u8fde\u51fb\u94fe %d \u5956\u52b1\u5c42\u6570 %d"), rogueStats.comboChain, rogueStats.comboBonusStacks);
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(50), comboText, lstrlen(comboText));
TCHAR summaryText[96];
_stprintf_s(
summaryText,
_T("\u9884\u89c8 %d \u4fdd\u547d %d \u5df2\u9009 %d"),
rogueStats.previewCount,
rogueStats.lastChanceCount,
upgradeUiState.totalChosenCount);
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(82), summaryText, lstrlen(summaryText));
if (rogueStats.sweeperLevel > 0)
{
TCHAR sweeperText[96];
int sweeperThreshold = 8 - (rogueStats.sweeperLevel - 1) * 2;
if (sweeperThreshold < 3)
{
sweeperThreshold = 3;
}
_stprintf_s(sweeperText, _T("\u6e05\u626b\u8005 %d / %d"), rogueStats.sweeperCharge, sweeperThreshold);
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(114), sweeperText, lstrlen(sweeperText));
}
if (rogueStats.explosiveLevel > 0)
{
TCHAR explosiveText[96];
int explosiveChance = 12 + (rogueStats.explosiveLevel - 1) * 8;
if (explosiveChance > 40)
{
explosiveChance = 40;
}
_stprintf_s(explosiveText, _T("\u7206\u7834\u6982\u7387 %d%% %s"), explosiveChance, currentPieceIsExplosive ? _T("\u672c\u5757\u5df2\u7206\u7834") : _T("\u672c\u5757\u666e\u901a"));
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(146), explosiveText, lstrlen(explosiveText));
}
if (rogueStats.laserLevel > 0)
{
TCHAR laserText[96];
int laserChance = 10 + (rogueStats.laserLevel - 1) * 8;
if (laserChance > 35)
{
laserChance = 35;
}
_stprintf_s(laserText, _T("\u6fc0\u5149\u6982\u7387 %d%% %s"), laserChance, currentPieceIsLaser ? _T("\u672c\u5757\u5df2\u6fc0\u5149") : _T("\u672c\u5757\u666e\u901a"));
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(338), laserText, lstrlen(laserText));
}
if (rogueStats.thunderTetrisLevel > 0)
{
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(370), _T("\u96f7\u9706\u56db\u6d88 \u56db\u6d88\u52a0\u6e05 2 \u884c"), lstrlen(_T("\u96f7\u9706\u56db\u6d88 \u56db\u6d88\u52a0\u6e05 2 \u884c")));
}
if (rogueStats.thunderLaserLevel > 0)
{
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(402), _T("\u96f7\u9706\u6fc0\u5149 \u56db\u6d88\u52a0\u6fc0\u5149 2 \u5217"), lstrlen(_T("\u96f7\u9706\u6fc0\u5149 \u56db\u6d88\u52a0\u6fc0\u5149 2 \u5217")));
}
if (rogueStats.feverLevel > 0)
{
TCHAR feverText[96];
_stprintf_s(feverText, _T("\u72c2\u70ed\u5145\u80fd %d / 20 \u5269\u4f59 %d \u79d2"), rogueStats.feverLineCharge, rogueStats.feverTicks);
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(434), feverText, lstrlen(feverText));
}
if (rogueStats.rageStackLevel > 0)
{
TCHAR rageText[96];
_stprintf_s(rageText, _T("\u66b4\u8d70\u5806\u53e0 \u8fde\u51fb %d"), rogueStats.comboChain);
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(466), rageText, lstrlen(rageText));
}
if (rogueStats.infiniteFeverLevel > 0)
{
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(498), _T("\u65e0\u9650\u72c2\u70ed \u6d88\u884c\u53ef\u5ef6\u957f\u65f6\u95f4"), lstrlen(_T("\u65e0\u9650\u72c2\u70ed \u6d88\u884c\u53ef\u5ef6\u957f\u65f6\u95f4")));
}
if (rogueStats.screenBombLevel > 0)
{
TCHAR bombText[96];
_stprintf_s(bombText, _T("\u6e05\u5c4f\u70b8\u5f39 %d / 30 \u5e93\u5b58 %d X \u4e3b\u52a8\u91ca\u653e"), rogueStats.screenBombCharge, rogueStats.screenBombCount);
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(530), bombText, lstrlen(bombText));
}
if (rogueStats.terminalClearLevel > 0)
{
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(562), _T("\u7ec8\u672b\u6e05\u573a \u6fc0\u6d3b\u6700\u540e\u4e00\u640f\u65f6\u81ea\u52a8\u89e6\u53d1"), lstrlen(_T("\u7ec8\u672b\u6e05\u573a \u6fc0\u6d3b\u6700\u540e\u4e00\u640f\u65f6\u81ea\u52a8\u89e6\u53d1")));
}
if (rogueStats.perfectRotateLevel > 0)
{
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(594), _T("\u5b8c\u7f8e\u65cb\u8f6c \u65cb\u8f6c\u5931\u8d25\u65f6\u81ea\u52a8\u4fee\u6b63"), lstrlen(_T("\u5b8c\u7f8e\u65cb\u8f6c \u65cb\u8f6c\u5931\u8d25\u65f6\u81ea\u52a8\u4fee\u6b63")));
}
if (rogueStats.timeDilationLevel > 0)
{
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(626), _T("\u65f6\u95f4\u7f13\u6d41 \u76d8\u9762\u8fc7\u9ad8\u65f6\u81ea\u52a8\u51cf\u901f"), lstrlen(_T("\u65f6\u95f4\u7f13\u6d41 \u76d8\u9762\u8fc7\u9ad8\u65f6\u81ea\u52a8\u51cf\u901f")));
}
if (rogueStats.highPressureLevel > 0)
{
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(658), _T("\u9ad8\u538b\u5956\u52b1 \u901f\u5ea6\u66f4\u5feb\uff0c\u5f97\u5206 / EXP x1.5"), lstrlen(_T("\u9ad8\u538b\u5956\u52b1 \u901f\u5ea6\u66f4\u5feb\uff0c\u5f97\u5206 / EXP x1.5")));
}
if (rogueStats.tetrisGambleLevel > 0)
{
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(690), _T("\u8d4c\u547d\u56db\u6d88 \u975e\u56db\u6d88\u964d\u76ca\uff0c\u56db\u6d88\u66b4\u589e"), lstrlen(_T("\u8d4c\u547d\u56db\u6d88 \u975e\u56db\u6d88\u964d\u76ca\uff0c\u56db\u6d88\u66b4\u589e")));
}
if (rogueStats.extremePlayerLevel > 0)
{
TCHAR extremeText[96];
_stprintf_s(extremeText, _T("\u6781\u9650\u73a9\u5bb6 \u7f13\u901f\u5269\u4f59 %d"), rogueStats.extremeSlowTicks);
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(722), extremeText, lstrlen(extremeText));
}
if (rogueStats.controlMasterLevel > 0)
{
TCHAR controlText[96];
_stprintf_s(controlText, _T("\u64cd\u63a7\u5927\u5e08 Hold \u7f13\u901f\u5269\u4f59 %d"), rogueStats.holdSlowTicks);
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(754), controlText, lstrlen(controlText));
}
if (rogueStats.chainBlastLevel > 0)
{
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(274), _T("\u8fde\u9501\u7206\u7834 \u5df2\u89e3\u9501"), lstrlen(_T("\u8fde\u9501\u7206\u7834 \u5df2\u89e3\u9501")));
}
if (rogueStats.chainBombLevel > 0)
{
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(306), _T("\u8fde\u73af\u70b8\u5f39 5x5 + \u4e8c\u6b21\u7206\u70b8"), lstrlen(_T("\u8fde\u73af\u70b8\u5f39 5x5 + \u4e8c\u6b21\u7206\u70b8")));
}
if (rogueStats.doubleGrowthLevel > 0)
{
TCHAR growthText[96];
_stprintf_s(growthText, _T("\u6210\u957f\u6838\u5fc3 +15%% Score / +15%% EXP"));
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(178), growthText, lstrlen(growthText));
}
int tunedPieces = 0;
for (int pieceType = 0; pieceType < 7; pieceType++)
{
if (rogueStats.pieceTuningLevels[pieceType] > 0)
{
tunedPieces++;
}
}
if (tunedPieces > 0)
{
TCHAR luckyText[96];
_stprintf_s(luckyText, _T("\u65b9\u5757\u6539\u9020 %d \u79cd\u5df2\u8c03\u6574"), tunedPieces);
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(210), luckyText, lstrlen(luckyText));
}
if (rogueStats.gamblerLevel > 0)
{
TCHAR gamblerText[96];
int variance = 20 + (rogueStats.gamblerLevel - 1) * 10;
if (variance > 40)
{
variance = 40;
}
_stprintf_s(gamblerText, _T("\u8d4c\u5f92\u6982\u7387 \u53cc\u500d/%u\u6548 %d%%"), variance, variance);
TextOut(hdc, combatRect.left + SS(18), combatRect.top + SS(242), gamblerText, lstrlen(gamblerText));
}
RECT upgradeListRect =
{
panelRect.left + SS(20),
panelRect.top + SS(510),
panelRect.right - SS(20),
panelRect.top + SS(676)
};
DrawPanelCard(upgradeListRect, RGB(255, 248, 251), RGB(233, 191, 208), 24);
SelectObject(hdc, sectionFont);
SetTextColor(hdc, textColor);
TextOut(hdc, upgradeListRect.left + SS(18), upgradeListRect.top + SS(16), _T("\u5df2\u83b7\u5f97\u5f3a\u5316"), lstrlen(_T("\u5df2\u83b7\u5f97\u5f3a\u5316")));
SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(128, 104, 118));
RECT upgradeBodyRect =
{
upgradeListRect.left + SS(18),
upgradeListRect.top + SS(48),
upgradeListRect.right - SS(18),
upgradeListRect.bottom - SS(14)
};
TCHAR upgradeSummary[512];
upgradeSummary[0] = _T('\0');
if (rogueStats.scoreUpgradeLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u5206\u6570\u500d\u7387 Lv.%d\r\n"), rogueStats.scoreUpgradeLevel);
}
if (rogueStats.expUpgradeLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("EXP \u5f3a\u5316 Lv.%d\r\n"), rogueStats.expUpgradeLevel);
}
if (rogueStats.slowFallStacks > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u6162\u901f\u4e0b\u843d Lv.%d\r\n"), rogueStats.slowFallStacks);
}
if (rogueStats.comboBonusStacks > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u8fde\u51fb\u52a0\u6210 Lv.%d\r\n"), rogueStats.comboBonusStacks);
}
if (rogueStats.previewUpgradeLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u989d\u5916\u9884\u89c8 Lv.%d\r\n"), rogueStats.previewUpgradeLevel);
}
if (rogueStats.lastChanceUpgradeLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u6700\u540e\u4e00\u640f Lv.1 \u5269\u4f59 %d \u6b21\r\n"), rogueStats.lastChanceCount);
}
if (rogueStats.pressureReliefLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u51cf\u538b Lv.%d\r\n"), rogueStats.pressureReliefLevel);
}
if (rogueStats.sweeperLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u6e05\u626b\u8005 Lv.%d\r\n"), rogueStats.sweeperLevel);
}
if (rogueStats.explosiveLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u7206\u7834\u65b9\u5757 Lv.%d\r\n"), rogueStats.explosiveLevel);
}
if (rogueStats.chainBlastLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u8fde\u9501\u7206\u7834 Lv.1\r\n"));
}
if (rogueStats.chainBombLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u8fde\u73af\u70b8\u5f39 Lv.1\r\n"));
}
if (rogueStats.laserLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u6fc0\u5149\u65b9\u5757 Lv.%d\r\n"), rogueStats.laserLevel);
}
if (rogueStats.thunderTetrisLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u96f7\u9706\u56db\u6d88 Lv.1\r\n"));
}
if (rogueStats.thunderLaserLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u96f7\u9706\u6fc0\u5149 Lv.1\r\n"));
}
if (rogueStats.feverLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u72c2\u70ed\u6a21\u5f0f Lv.1\r\n"));
}
if (rogueStats.rageStackLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u66b4\u8d70\u5806\u53e0 Lv.1\r\n"));
}
if (rogueStats.infiniteFeverLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u65e0\u9650\u72c2\u70ed Lv.1\r\n"));
}
if (rogueStats.screenBombLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u6e05\u5c4f\u70b8\u5f39 Lv.1\r\n"));
}
if (rogueStats.terminalClearLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u7ec8\u672b\u6e05\u573a Lv.1\r\n"));
}
if (rogueStats.perfectRotateLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u5b8c\u7f8e\u65cb\u8f6c Lv.1\r\n"));
}
if (rogueStats.timeDilationLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u65f6\u95f4\u7f13\u6d41 Lv.1\r\n"));
}
if (rogueStats.highPressureLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u9ad8\u538b\u5956\u52b1 Lv.1\r\n"));
}
if (rogueStats.tetrisGambleLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u8d4c\u547d\u56db\u6d88 Lv.1\r\n"));
}
if (rogueStats.extremePlayerLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u6781\u9650\u73a9\u5bb6 Lv.1\r\n"));
}
if (rogueStats.upgradeShockwaveLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u5347\u7ea7\u51b2\u51fb\u6ce2 Lv.1\r\n"));
}
if (rogueStats.evolutionImpactLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u8fdb\u5316\u51b2\u51fb Lv.1\r\n"));
}
if (rogueStats.controlMasterLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u64cd\u63a7\u5927\u5e08 Lv.1\r\n"));
}
if (rogueStats.stableStructureLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u7a33\u5b9a\u7ed3\u6784 Lv.%d\r\n"), rogueStats.stableStructureLevel);
}
if (rogueStats.doubleGrowthLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u6210\u957f\u6838\u5fc3 Lv.1\r\n"));
}
int tunedPieceCount = 0;
for (int pieceType = 0; pieceType < 7; pieceType++)
{
if (rogueStats.pieceTuningLevels[pieceType] > 0)
{
tunedPieceCount++;
_stprintf_s(
upgradeSummary + lstrlen(upgradeSummary),
512 - lstrlen(upgradeSummary),
_T("%s \u65b9\u5757\u6539\u9020 Lv.%d\r\n"),
(pieceType == 0 ? _T("I") :
pieceType == 1 ? _T("T") :
pieceType == 2 ? _T("L") :
pieceType == 3 ? _T("J") :
pieceType == 4 ? _T("O") :
pieceType == 5 ? _T("S") : _T("Z")),
rogueStats.pieceTuningLevels[pieceType]);
}
}
if (rogueStats.gamblerLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u8d4c\u5f92 Lv.%d\r\n"), rogueStats.gamblerLevel);
}
if (rogueStats.dualChoiceLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u53cc\u91cd\u9009\u62e9 Lv.1\r\n"));
}
if (rogueStats.destinyWheelLevel > 0)
{
_stprintf_s(upgradeSummary + lstrlen(upgradeSummary), 512 - lstrlen(upgradeSummary), _T("\u547d\u8fd0\u8f6e\u76d8 Lv.1\r\n"));
}
if (lstrlen(upgradeSummary) == 0)
{
_stprintf_s(upgradeSummary, _T("\u6682\u672a\u9009\u62e9\u4efb\u4f55\u5f3a\u5316\u3002\r\n\u5347\u7ea7\u540e\u4f1a\u5728\u8fd9\u91cc\u7d2f\u79ef\u663e\u793a\u3002"));
}
DrawText(hdc, upgradeSummary, -1, &upgradeBodyRect, DT_LEFT | DT_TOP | DT_WORDBREAK);
SelectObject(hdc, sectionFont);
SetTextColor(hdc, textColor);
}
else
{
SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(128, 104, 118));
TextOut(hdc, panelRect.left + SS(24), panelRect.top + SS(232), _T("\u7ecf\u5178\u6a21\u5f0f\u4fdd\u6301\u539f\u7248\u7b80\u5355\u8ba1\u5206"), lstrlen(_T("\u7ecf\u5178\u6a21\u5f0f\u4fdd\u6301\u539f\u7248\u7b80\u5355\u8ba1\u5206")));
TextOut(hdc, panelRect.left + SS(24), panelRect.top + SS(260), _T("\u6682\u4e0d\u63a5\u5165\u7b49\u7ea7\u548c\u5f3a\u5316\u7cfb\u7edf"), lstrlen(_T("\u6682\u4e0d\u63a5\u5165\u7b49\u7ea7\u548c\u5f3a\u5316\u7cfb\u7edf")));
SelectObject(hdc, sectionFont);
SetTextColor(hdc, textColor);
}
int holdTitleTop = (currentMode == MODE_ROGUE) ? panelRect.top + SS(690) : panelRect.top + SS(430);
int holdCardTop = (currentMode == MODE_ROGUE) ? panelRect.top + SS(724) : panelRect.top + SS(472);
int previewTitleTop = holdTitleTop;
int nextCardTop = holdCardTop;
int hintTop = (currentMode == MODE_ROGUE) ? panelRect.top + SS(818) : panelRect.top + SS(656);
if (currentMode == MODE_ROGUE)
{
TextOut(hdc, panelRect.left + SS(24), holdTitleTop, _T("Hold \u69fd"), lstrlen(_T("Hold \u69fd")));
RECT holdCard =
{
panelRect.left + SS(24),
holdCardTop,
panelRect.left + SS(24) + grid * 2 + SS(40),
holdCardTop + grid * 2 + SS(40)
};
DrawPanelCard(holdCard, RGB(255, 238, 244), RGB(233, 191, 208), 22);
if (rogueStats.holdUnlocked == 0)
{
SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(128, 104, 118));
RECT holdLockedRect =
{
holdCard.left + SS(10),
holdCard.top + SS(18),
holdCard.right - SS(10),
holdCard.bottom - SS(10)
};
DrawText(hdc, _T("\u672a\u89e3\u9501\r\n\u83b7\u53d6 Hold \u5f3a\u5316\u540e\u53ef\u7528"), -1, &holdLockedRect, DT_CENTER | DT_VCENTER | DT_WORDBREAK);
}
else if (holdType >= 0)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (bricks[holdType][0][i][j] != 0)
{
RECT brickRect =
{
holdCard.left + SS(14) + j * (grid / 2),
holdCard.top + SS(14) + i * (grid / 2),
holdCard.left + SS(14) + (j + 1) * (grid / 2) - SS(1),
holdCard.top + SS(14) + (i + 1) * (grid / 2) - SS(1)
};
HBRUSH brickBrush = CreateSolidBrush(BrickColor[holdType]);
HPEN brickPen = CreatePen(PS_SOLID, 1, RGB(255, 248, 250));
oldPen = (HPEN)SelectObject(hdc, brickPen);
oldBrush = (HBRUSH)SelectObject(hdc, brickBrush);
RoundRect(hdc, brickRect.left, brickRect.top, brickRect.right, brickRect.bottom, SS(8), SS(8));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(brickBrush);
DeleteObject(brickPen);
}
}
}
}
else
{
SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(128, 104, 118));
RECT emptyHoldRect =
{
holdCard.left + SS(10),
holdCard.top + SS(18),
holdCard.right - SS(10),
holdCard.bottom - SS(10)
};
DrawText(hdc, _T("\u6682\u65e0\u6682\u5b58\r\nC / Shift \u53ef\u5b58\u5165\u5f53\u524d\u65b9\u5757"), -1, &emptyHoldRect, DT_CENTER | DT_VCENTER | DT_WORDBREAK);
}
previewTitleTop = holdTitleTop;
nextCardTop = holdCardTop;
}
int previewLabelLeft = panelRect.left + SS((currentMode == MODE_ROGUE) ? 132 : 24);
TextOut(hdc, previewLabelLeft, previewTitleTop, _T("\u4e0b\u4e00\u4e2a\u65b9\u5757"), lstrlen(_T("\u4e0b\u4e00\u4e2a\u65b9\u5757")));
int previewCount = 1;
if (currentMode == MODE_ROGUE)
{
previewCount = rogueStats.previewCount;
if (previewCount < 1)
{
previewCount = 1;
}
if (previewCount > 3)
{
previewCount = 3;
}
}
for (int previewIndex = 0; previewIndex < previewCount; previewIndex++)
{
RECT nextCard =
{
previewLabelLeft + previewIndex * SS(94),
nextCardTop,
previewLabelLeft + previewIndex * SS(94) + grid * 2 + SS(40),
nextCardTop + grid * 2 + SS(40)
};
HBRUSH nextCardBrush = CreateSolidBrush(RGB(255, 238, 244));
HPEN nextCardPen = CreatePen(PS_SOLID, 1, RGB(233, 191, 208));
oldPen = (HPEN)SelectObject(hdc, nextCardPen);
oldBrush = (HBRUSH)SelectObject(hdc, nextCardBrush);
RoundRect(hdc, nextCard.left, nextCard.top, nextCard.right, nextCard.bottom, SS(22), SS(22));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(nextCardBrush);
DeleteObject(nextCardPen);
int previewType = nextTypes[previewIndex];
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (bricks[previewType][0][i][j] != 0)
{
RECT brickRect =
{
nextCard.left + SS(14) + j * (grid / 2),
nextCard.top + SS(14) + i * (grid / 2),
nextCard.left + SS(14) + (j + 1) * (grid / 2) - SS(1),
nextCard.top + SS(14) + (i + 1) * (grid / 2) - SS(1)
};
HBRUSH brickBrush = CreateSolidBrush(BrickColor[previewType]);
HPEN brickPen = CreatePen(PS_SOLID, 1, RGB(255, 248, 250));
oldPen = (HPEN)SelectObject(hdc, brickPen);
oldBrush = (HBRUSH)SelectObject(hdc, brickBrush);
RoundRect(hdc, brickRect.left, brickRect.top, brickRect.right, brickRect.bottom, SS(8), SS(8));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(brickBrush);
DeleteObject(brickPen);
}
}
}
}
SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(128, 104, 118));
TextOut(hdc, panelRect.left + SS(24), hintTop, _T("M \uff1a\u8fd4\u56de\u83dc\u5355"), lstrlen(_T("M \uff1a\u8fd4\u56de\u83dc\u5355")));
TextOut(hdc, panelRect.left + SS(24), hintTop + SS(32), _T("\u89c4\u5219\u8bf4\u660e\u8bf7\u5728\u4e3b\u83dc\u5355\u8fdb\u5165"), lstrlen(_T("\u89c4\u5219\u8bf4\u660e\u8bf7\u5728\u4e3b\u83dc\u5355\u8fdb\u5165")));
if (feedbackState.visibleTicks > 0)
{
RECT feedbackRect =
{
gameRect.left + SS(16),
gameRect.top + SS(16),
gameRect.right - SS(16),
gameRect.top + SS(98)
};
DrawPanelCard(feedbackRect, RGB(255, 245, 249), RGB(232, 170, 194), 22);
SelectObject(hdc, bodyFont);
SetTextColor(hdc, titleColor);
RECT titleRect =
{
feedbackRect.left + SS(16),
feedbackRect.top + SS(12),
feedbackRect.right - SS(16),
feedbackRect.top + SS(40)
};
DrawText(hdc, feedbackState.title, -1, &titleRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(116, 90, 104));
RECT detailRect =
{
feedbackRect.left + SS(16),
feedbackRect.top + SS(42),
feedbackRect.right - SS(16),
feedbackRect.bottom - SS(12)
};
DrawText(hdc, feedbackState.detail, -1, &detailRect, DT_LEFT | DT_WORDBREAK);
}
if (suspendFlag || gameOverFlag)
{
RECT overlayRect =
{
gameRect.left + grid,
gameRect.top + grid * 6,
gameRect.right - grid,
gameRect.top + grid * 13
};
HBRUSH overlayBrush = CreateSolidBrush(RGB(255, 241, 246));
HPEN overlayPen = CreatePen(PS_SOLID, 2, RGB(232, 170, 194));
oldPen = (HPEN)SelectObject(hdc, overlayPen);
oldBrush = (HBRUSH)SelectObject(hdc, overlayBrush);
RoundRect(hdc, overlayRect.left, overlayRect.top, overlayRect.right, overlayRect.bottom, SS(26), SS(26));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(overlayBrush);
DeleteObject(overlayPen);
RECT titleRect =
{
overlayRect.left,
overlayRect.top + grid,
overlayRect.right,
overlayRect.top + grid * 3
};
RECT tipRect =
{
overlayRect.left + SS(20),
overlayRect.top + grid * 3,
overlayRect.right - SS(20),
overlayRect.bottom - grid
};
SetTextColor(hdc, RGB(121, 76, 99));
SelectObject(hdc, titleFont);
if (suspendFlag)
{
DrawText(hdc, _T("\u6e38\u620f\u5df2\u6682\u505c"), -1, &titleRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, bodyFont);
DrawText(hdc, _T("\u6309 P \u952e\u7ee7\u7eed\u6e38\u620f"), -1, &tipRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
else
{
DrawText(hdc, _T("\u6e38\u620f\u7ed3\u675f"), -1, &titleRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, bodyFont);
DrawText(hdc, _T("\u6309 R \u952e\u91cd\u65b0\u5f00\u59cb \u6216 M \u8fd4\u56de\u83dc\u5355"), -1, &tipRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
}
if (currentScreen == SCREEN_UPGRADE)
{
HBRUSH dimBrush = CreateSolidBrush(RGB(246, 232, 238));
RECT dimRect =
{
SX(20),
SY(20),
SX(WINDOW_CLIENT_WIDTH - 20),
SY(WINDOW_CLIENT_HEIGHT - 20)
};
FillRect(hdc, &dimRect, dimBrush);
DeleteObject(dimBrush);
RECT overlayRect =
{
SX(60),
SY(80),
SX(WINDOW_CLIENT_WIDTH - 60),
SY(WINDOW_CLIENT_HEIGHT - 80)
};
HBRUSH overlayBrush = CreateSolidBrush(RGB(255, 250, 252));
HPEN overlayPen = CreatePen(PS_SOLID, SS(2), RGB(232, 170, 194));
oldPen = (HPEN)SelectObject(hdc, overlayPen);
oldBrush = (HBRUSH)SelectObject(hdc, overlayBrush);
RoundRect(hdc, overlayRect.left, overlayRect.top, overlayRect.right, overlayRect.bottom, SS(30), SS(30));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(overlayBrush);
DeleteObject(overlayPen);
SetTextColor(hdc, titleColor);
SelectObject(hdc, titleFont);
RECT overlayTitleRect =
{
overlayRect.left,
overlayRect.top + SS(24),
overlayRect.right,
overlayRect.top + SS(68)
};
DrawText(hdc, _T("\u5347\u7ea7\u9009\u62e9"), -1, &overlayTitleRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, bodyFont);
SetTextColor(hdc, textColor);
RECT overlaySubtitleRect =
{
overlayRect.left,
overlayRect.top + SS(70),
overlayRect.right,
overlayRect.top + SS(106)
};
TCHAR overlaySubtitle[128];
_stprintf_s(
overlaySubtitle,
_T("\u672c\u6b21\u51fa\u73b0 %d \u4e2a\u9009\u9879\uff0c\u8fd8\u53ef\u9009 %d \u4e2a"),
upgradeUiState.optionCount,
upgradeUiState.picksRemaining);
DrawText(hdc, overlaySubtitle, -1, &overlaySubtitleRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
int gap = SS(18);
int horizontalPadding = SS(36);
int verticalTop = overlayRect.top + SS(138);
int rowCount = (upgradeUiState.optionCount + 1) / 2;
if (rowCount < 1)
{
rowCount = 1;
}
int cardWidth = (overlayRect.right - overlayRect.left - horizontalPadding * 2 - gap) / 2;
int availableHeight = overlayRect.bottom - verticalTop - SS(72) - (rowCount - 1) * gap;
int cardHeight = availableHeight / rowCount;
for (int i = 0; i < upgradeUiState.optionCount; i++)
{
bool isSelected = (i == upgradeUiState.selectedIndex);
int column = i % 2;
int row = i / 2;
int left = overlayRect.left + horizontalPadding + column * (cardWidth + gap);
int top = verticalTop + row * (cardHeight + gap);
int right = left + cardWidth;
RECT cardRect =
{
left,
top,
right,
top + cardHeight
};
COLORREF cardFill = RGB(255, 247, 250);
COLORREF cardBorder = RGB(221, 197, 208);
COLORREF iconFill = RGB(233, 206, 217);
COLORREF categoryColor = RGB(122, 95, 110);
COLORREF descColor = RGB(108, 86, 99);
COLORREF footerColor = RGB(128, 104, 118);
if (upgradeUiState.options[i].cursed)
{
cardFill = isSelected ? RGB(255, 233, 233) : RGB(255, 243, 243);
cardBorder = isSelected ? RGB(210, 92, 92) : RGB(224, 156, 156);
iconFill = isSelected ? RGB(235, 128, 128) : RGB(232, 182, 182);
categoryColor = RGB(146, 73, 73);
descColor = RGB(120, 74, 74);
footerColor = RGB(150, 70, 70);
}
else if (isSelected)
{
cardFill = RGB(255, 235, 242);
cardBorder = accentColor;
iconFill = RGB(242, 176, 202);
}
HBRUSH cardBrush = CreateSolidBrush(cardFill);
HPEN cardPen = CreatePen(PS_SOLID, isSelected ? SS(3) : 1, cardBorder);
oldPen = (HPEN)SelectObject(hdc, cardPen);
oldBrush = (HBRUSH)SelectObject(hdc, cardBrush);
RoundRect(hdc, cardRect.left, cardRect.top, cardRect.right, cardRect.bottom, SS(24), SS(24));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(cardBrush);
DeleteObject(cardPen);
RECT iconRect =
{
cardRect.left + SS(20),
cardRect.top + SS(20),
cardRect.left + SS(84),
cardRect.top + SS(84)
};
HBRUSH iconBrush = CreateSolidBrush(iconFill);
HPEN iconPen = CreatePen(PS_SOLID, 1, RGB(255, 250, 252));
oldPen = (HPEN)SelectObject(hdc, iconPen);
oldBrush = (HBRUSH)SelectObject(hdc, iconBrush);
RoundRect(hdc, iconRect.left, iconRect.top, iconRect.right, iconRect.bottom, SS(18), SS(18));
SelectObject(hdc, oldBrush);
SelectObject(hdc, oldPen);
DeleteObject(iconBrush);
DeleteObject(iconPen);
SelectObject(hdc, smallFont);
SetTextColor(hdc, categoryColor);
RECT categoryRect =
{
cardRect.left + SS(20),
cardRect.top + SS(96),
cardRect.right - SS(20),
cardRect.top + SS(122)
};
DrawText(hdc, upgradeUiState.options[i].category, -1, &categoryRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
TCHAR levelText[32];
_stprintf_s(levelText, _T("Lv.%d"), upgradeUiState.options[i].currentLevel + 1);
RECT levelRect =
{
cardRect.right - SS(88),
cardRect.top + SS(24),
cardRect.right - SS(20),
cardRect.top + SS(54)
};
DrawText(hdc, levelText, -1, &levelRect, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
SelectObject(hdc, sectionFont);
SetTextColor(hdc, upgradeUiState.options[i].cursed ? RGB(130, 54, 54) : (isSelected ? titleColor : textColor));
RECT nameRect =
{
cardRect.left + SS(20),
cardRect.top + SS(126),
cardRect.right - SS(20),
cardRect.top + SS(170)
};
DrawText(hdc, upgradeUiState.options[i].name, -1, &nameRect, DT_LEFT | DT_VCENTER | DT_WORDBREAK);
SelectObject(hdc, bodyFont);
SetTextColor(hdc, descColor);
RECT descRect =
{
cardRect.left + SS(20),
cardRect.top + SS(182),
cardRect.right - SS(20),
cardRect.bottom - SS(64)
};
DrawText(hdc, upgradeUiState.options[i].description, -1, &descRect, DT_LEFT | DT_WORDBREAK);
SelectObject(hdc, smallFont);
RECT footerRect =
{
cardRect.left + SS(20),
cardRect.bottom - SS(52),
cardRect.right - SS(20),
cardRect.bottom - SS(22)
};
SetTextColor(hdc, footerColor);
DrawText(
hdc,
upgradeUiState.options[i].cursed ? _T("\u547d\u8fd0\u8f6e\u76d8\uff1a\u9644\u5e26\u8bc5\u5492") : _T("\u5360\u4f4d\u56fe\u6807 / \u5360\u4f4d\u7a00\u6709\u5ea6"),
-1,
&footerRect,
DT_LEFT | DT_VCENTER | DT_SINGLELINE);
}
SelectObject(hdc, smallFont);
SetTextColor(hdc, RGB(128, 104, 118));
RECT hintRect =
{
overlayRect.left + SS(30),
overlayRect.bottom - SS(52),
overlayRect.right - SS(30),
overlayRect.bottom - SS(18)
};
DrawText(hdc, _T("W/A/S/D \u6216\u65b9\u5411\u952e\u5207\u6362\uff0cEnter \u6216 Space \u786e\u8ba4"), -1, &hintRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
SelectObject(hdc, oldFont);
DeleteObject(titleFont);
DeleteObject(sectionFont);
DeleteObject(bodyFont);
DeleteObject(smallFont);
}