#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, §ionTitle, 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); }