添加致谢页
This commit is contained in:
+275
-12
@@ -126,6 +126,66 @@ static Bitmap* LoadBackgroundImage()
|
||||
return backgroundImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 按序号加载致谢页图片资源。
|
||||
*/
|
||||
static Bitmap* LoadCreditImage(int index)
|
||||
{
|
||||
static ULONG_PTR gdiplusToken = 0;
|
||||
static Bitmap* creditImages[2] = {};
|
||||
static bool attempted[2] = {};
|
||||
|
||||
if (index < 0 || index >= 2)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!attempted[index])
|
||||
{
|
||||
attempted[index] = true;
|
||||
|
||||
GdiplusStartupInput startupInput;
|
||||
if (GdiplusStartup(&gdiplusToken, &startupInput, nullptr) == Ok)
|
||||
{
|
||||
const wchar_t* imageNames[2] =
|
||||
{
|
||||
L"assets\\images\\qls.jpg",
|
||||
L"assets\\images\\wyk.jpg"
|
||||
};
|
||||
const std::wstring candidates[] =
|
||||
{
|
||||
BuildAssetPath(imageNames[index]),
|
||||
BuildWorkingDirAssetPath(imageNames[index])
|
||||
};
|
||||
|
||||
for (const std::wstring& candidate : candidates)
|
||||
{
|
||||
if (candidate.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
DWORD attributes = GetFileAttributesW(candidate.c_str());
|
||||
if (attributes == INVALID_FILE_ATTRIBUTES || (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Bitmap* loadedImage = Bitmap::FromFile(candidate.c_str(), FALSE);
|
||||
if (loadedImage != nullptr && loadedImage->GetLastStatus() == Ok)
|
||||
{
|
||||
creditImages[index] = loadedImage;
|
||||
break;
|
||||
}
|
||||
|
||||
delete loadedImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return creditImages[index];
|
||||
}
|
||||
|
||||
void TDrawScreen(HDC hdc, HWND hWnd)
|
||||
{
|
||||
RECT clientRect;
|
||||
@@ -383,12 +443,15 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
||||
SX(34),
|
||||
SY(34)
|
||||
};
|
||||
DrawPanelCardAlpha(
|
||||
backButtonRect,
|
||||
RGB(255, 242, 247),
|
||||
RGB(222, 130, 166),
|
||||
12,
|
||||
214);
|
||||
HBRUSH backBrush = CreateSolidBrush(RGB(255, 242, 247));
|
||||
HPEN backFramePen = CreatePen(PS_SOLID, 1, RGB(222, 130, 166));
|
||||
HBRUSH oldBackBrush = (HBRUSH)SelectObject(hdc, backBrush);
|
||||
HPEN oldBackFramePen = (HPEN)SelectObject(hdc, backFramePen);
|
||||
RoundRect(hdc, backButtonRect.left, backButtonRect.top, backButtonRect.right, backButtonRect.bottom, SS(12), SS(12));
|
||||
SelectObject(hdc, oldBackBrush);
|
||||
SelectObject(hdc, oldBackFramePen);
|
||||
DeleteObject(backFramePen);
|
||||
DeleteObject(backBrush);
|
||||
|
||||
HPEN backPen = CreatePen(PS_SOLID, SS(3), RGB(128, 70, 100));
|
||||
HPEN oldBackPen = (HPEN)SelectObject(hdc, backPen);
|
||||
@@ -436,18 +499,20 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
||||
SetTextColor(hdc, textColor);
|
||||
DrawText(hdc, _T("选择你的战局"), -1, &subtitleRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
||||
|
||||
const TCHAR* modeNames[3] =
|
||||
const TCHAR* modeNames[4] =
|
||||
{
|
||||
_T("\u7ecf\u5178\u6a21\u5f0f"),
|
||||
_T("Rogue \u6a21\u5f0f"),
|
||||
_T("\u5e2e\u52a9")
|
||||
_T("\u5e2e\u52a9"),
|
||||
_T("\u81f4\u8c22")
|
||||
};
|
||||
|
||||
const TCHAR* modeDescriptions[3] =
|
||||
const TCHAR* modeDescriptions[4] =
|
||||
{
|
||||
_T("纯粹方块挑战,专注消行、堆叠与生存。"),
|
||||
_T("在不断升级的棋盘中收集强化,构筑本局专属流派。"),
|
||||
_T("查看操作、模式规则与全部强化效果。")
|
||||
_T("查看操作、模式规则与全部强化效果。"),
|
||||
_T("感谢程序测试者与代码贡献者。")
|
||||
};
|
||||
|
||||
for (int i = 0; i < menuState.optionCount; i++)
|
||||
@@ -568,6 +633,10 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
||||
{
|
||||
helpTitle = _T("\u5f3a\u5316\u56fe\u9274");
|
||||
}
|
||||
else if (helpState.currentPage == 4)
|
||||
{
|
||||
helpTitle = _T("\u81f4\u8c22");
|
||||
}
|
||||
DrawText(hdc, helpTitle, -1, &rulesTitleRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
|
||||
|
||||
HPEN rulesAccentPen = CreatePen(PS_SOLID, SS(3), accentColor);
|
||||
@@ -807,7 +876,198 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
||||
DeleteObject(contentClipRegion);
|
||||
DeleteObject(oldClipRegion);
|
||||
}
|
||||
if (helpState.currentPage != 3)
|
||||
else if (helpState.currentPage == 4)
|
||||
{
|
||||
const int creditAnimationTotalTicks = 60;
|
||||
const TCHAR* creditNames[2] =
|
||||
{
|
||||
_T("qls"),
|
||||
_T("wyk")
|
||||
};
|
||||
const TCHAR* creditTexts[2] =
|
||||
{
|
||||
_T("\u611f\u8c22\u6fc0\u60c5\u6295\u8eab\u4e8e\u6d4b\u8bd5\u4e4b\u4e2d\u7684Lisa"),
|
||||
_T("\u611f\u8c22\u70ed\u5ff1coding\u7684\u5c0f\u86cb\u7cd5")
|
||||
};
|
||||
|
||||
int currentCredit = creditPageIndex;
|
||||
if (currentCredit < 0)
|
||||
{
|
||||
currentCredit = 0;
|
||||
}
|
||||
if (currentCredit > 1)
|
||||
{
|
||||
currentCredit = 1;
|
||||
}
|
||||
|
||||
int previousCredit = currentCredit - creditAnimationDirection;
|
||||
if (previousCredit < 0)
|
||||
{
|
||||
previousCredit = 1;
|
||||
}
|
||||
if (previousCredit > 1)
|
||||
{
|
||||
previousCredit = 0;
|
||||
}
|
||||
|
||||
RECT imageArea =
|
||||
{
|
||||
contentRect.left + SS(92),
|
||||
contentRect.top + SS(10),
|
||||
contentRect.right - SS(92),
|
||||
contentRect.bottom - SS(112)
|
||||
};
|
||||
RECT textArea =
|
||||
{
|
||||
contentRect.left + SS(72),
|
||||
contentRect.bottom - SS(94),
|
||||
contentRect.right - SS(72),
|
||||
contentRect.bottom - SS(18)
|
||||
};
|
||||
|
||||
HRGN oldClipRegion = CreateRectRgn(0, 0, 0, 0);
|
||||
int hasOldClipRegion = GetClipRgn(hdc, oldClipRegion);
|
||||
HRGN contentClipRegion = CreateRectRgn(contentRect.left, contentRect.top, contentRect.right, contentRect.bottom);
|
||||
SelectClipRgn(hdc, contentClipRegion);
|
||||
|
||||
int slideDistance = contentRect.right - contentRect.left;
|
||||
int currentOffset = 0;
|
||||
int previousOffset = 0;
|
||||
if (creditAnimationTicks > 0 && creditAnimationDirection != 0)
|
||||
{
|
||||
currentOffset = creditAnimationDirection * slideDistance * creditAnimationTicks / creditAnimationTotalTicks;
|
||||
previousOffset = currentOffset - creditAnimationDirection * slideDistance;
|
||||
}
|
||||
|
||||
Bitmap* preloadedCreditImageA = LoadCreditImage(0);
|
||||
Bitmap* preloadedCreditImageB = LoadCreditImage(1);
|
||||
Graphics creditGraphics(hdc);
|
||||
creditGraphics.SetInterpolationMode(InterpolationModeHighQualityBilinear);
|
||||
|
||||
auto DrawCreditCard = [&](int cardIndex, int offset)
|
||||
{
|
||||
RECT shiftedImageArea = imageArea;
|
||||
RECT shiftedTextArea = textArea;
|
||||
OffsetRect(&shiftedImageArea, offset, 0);
|
||||
OffsetRect(&shiftedTextArea, offset, 0);
|
||||
|
||||
Bitmap* creditImage = (cardIndex == 0) ? preloadedCreditImageA : preloadedCreditImageB;
|
||||
if (creditImage != nullptr)
|
||||
{
|
||||
int imageWidth = static_cast<int>(creditImage->GetWidth());
|
||||
int imageHeight = static_cast<int>(creditImage->GetHeight());
|
||||
int areaWidth = shiftedImageArea.right - shiftedImageArea.left;
|
||||
int areaHeight = shiftedImageArea.bottom - shiftedImageArea.top;
|
||||
int drawWidth = areaWidth;
|
||||
int drawHeight = imageHeight * drawWidth / imageWidth;
|
||||
if (drawHeight > areaHeight)
|
||||
{
|
||||
drawHeight = areaHeight;
|
||||
drawWidth = imageWidth * drawHeight / imageHeight;
|
||||
}
|
||||
|
||||
int drawLeft = shiftedImageArea.left + (areaWidth - drawWidth) / 2;
|
||||
int drawTop = shiftedImageArea.top + (areaHeight - drawHeight) / 2;
|
||||
creditGraphics.DrawImage(creditImage, Rect(drawLeft, drawTop, drawWidth, drawHeight));
|
||||
}
|
||||
else
|
||||
{
|
||||
HBRUSH missingBrush = CreateSolidBrush(RGB(255, 245, 249));
|
||||
HPEN missingPen = CreatePen(PS_DASH, SS(2), frameColor);
|
||||
oldBrush = (HBRUSH)SelectObject(hdc, missingBrush);
|
||||
oldPen = (HPEN)SelectObject(hdc, missingPen);
|
||||
RoundRect(hdc, shiftedImageArea.left, shiftedImageArea.top, shiftedImageArea.right, shiftedImageArea.bottom, SS(24), SS(24));
|
||||
SelectObject(hdc, oldBrush);
|
||||
SelectObject(hdc, oldPen);
|
||||
DeleteObject(missingPen);
|
||||
DeleteObject(missingBrush);
|
||||
|
||||
SetTextColor(hdc, RGB(128, 104, 118));
|
||||
SelectObject(hdc, bodyFont);
|
||||
DrawText(hdc, _T("\u56fe\u7247\u8d44\u6e90\u672a\u627e\u5230"), -1, &shiftedImageArea, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
||||
}
|
||||
|
||||
if (creditAnimationTicks <= 0)
|
||||
{
|
||||
SetTextColor(hdc, titleColor);
|
||||
SelectObject(hdc, sectionFont);
|
||||
RECT nameRect =
|
||||
{
|
||||
shiftedTextArea.left,
|
||||
shiftedTextArea.top,
|
||||
shiftedTextArea.right,
|
||||
shiftedTextArea.top + SS(30)
|
||||
};
|
||||
DrawText(hdc, creditNames[cardIndex], -1, &nameRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
||||
|
||||
SetTextColor(hdc, textColor);
|
||||
SelectObject(hdc, bodyFont);
|
||||
RECT detailRect =
|
||||
{
|
||||
shiftedTextArea.left,
|
||||
shiftedTextArea.top + SS(34),
|
||||
shiftedTextArea.right,
|
||||
shiftedTextArea.bottom
|
||||
};
|
||||
DrawText(hdc, creditTexts[cardIndex], -1, &detailRect, DT_CENTER | DT_TOP | DT_WORDBREAK);
|
||||
}
|
||||
};
|
||||
|
||||
if (creditAnimationTicks > 0 && creditAnimationDirection != 0)
|
||||
{
|
||||
DrawCreditCard(previousCredit, previousOffset);
|
||||
}
|
||||
DrawCreditCard(currentCredit, currentOffset);
|
||||
|
||||
if (hasOldClipRegion == 1)
|
||||
{
|
||||
SelectClipRgn(hdc, oldClipRegion);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectClipRgn(hdc, nullptr);
|
||||
}
|
||||
DeleteObject(contentClipRegion);
|
||||
DeleteObject(oldClipRegion);
|
||||
|
||||
RECT leftArrow =
|
||||
{
|
||||
rulesCard.left + SS(52),
|
||||
(rulesCard.top + rulesCard.bottom) / 2 - SS(27),
|
||||
rulesCard.left + SS(106),
|
||||
(rulesCard.top + rulesCard.bottom) / 2 + SS(27)
|
||||
};
|
||||
RECT rightArrow =
|
||||
{
|
||||
rulesCard.right - SS(106),
|
||||
(rulesCard.top + rulesCard.bottom) / 2 - SS(27),
|
||||
rulesCard.right - SS(52),
|
||||
(rulesCard.top + rulesCard.bottom) / 2 + SS(27)
|
||||
};
|
||||
|
||||
HBRUSH arrowBrush = CreateSolidBrush(RGB(255, 245, 249));
|
||||
HPEN arrowPen = CreatePen(PS_SOLID, SS(2), accentColor);
|
||||
oldBrush = (HBRUSH)SelectObject(hdc, arrowBrush);
|
||||
oldPen = (HPEN)SelectObject(hdc, arrowPen);
|
||||
RoundRect(hdc, leftArrow.left, leftArrow.top, leftArrow.right, leftArrow.bottom, SS(18), SS(18));
|
||||
RoundRect(hdc, rightArrow.left, rightArrow.top, rightArrow.right, rightArrow.bottom, SS(18), SS(18));
|
||||
SelectObject(hdc, oldBrush);
|
||||
SelectObject(hdc, oldPen);
|
||||
DeleteObject(arrowPen);
|
||||
DeleteObject(arrowBrush);
|
||||
|
||||
HPEN chevronPen = CreatePen(PS_SOLID, SS(4), titleColor);
|
||||
oldPen = (HPEN)SelectObject(hdc, chevronPen);
|
||||
MoveToEx(hdc, leftArrow.left + SS(32), leftArrow.top + SS(16), nullptr);
|
||||
LineTo(hdc, leftArrow.left + SS(22), leftArrow.top + SS(27));
|
||||
LineTo(hdc, leftArrow.left + SS(32), leftArrow.bottom - SS(16));
|
||||
MoveToEx(hdc, rightArrow.right - SS(32), rightArrow.top + SS(16), nullptr);
|
||||
LineTo(hdc, rightArrow.right - SS(22), rightArrow.top + SS(27));
|
||||
LineTo(hdc, rightArrow.right - SS(32), rightArrow.bottom - SS(16));
|
||||
SelectObject(hdc, oldPen);
|
||||
DeleteObject(chevronPen);
|
||||
}
|
||||
if (helpState.currentPage != 3 && helpState.currentPage != 4)
|
||||
{
|
||||
RECT calculateRect = { contentRect.left, contentRect.top, contentRect.right, contentRect.top };
|
||||
DrawText(hdc, pageText, -1, &calculateRect, pageFlags | DT_CALCRECT);
|
||||
@@ -855,9 +1115,12 @@ void TDrawScreen(HDC hdc, HWND hWnd)
|
||||
};
|
||||
const TCHAR* helpHint = helpState.currentPage == 0
|
||||
? _T("\u65b9\u5411\u952e / WASD \u5207\u6362\uff0cEnter / Space \u786e\u8ba4\uff0cEsc / M \u8fd4\u56de\u4e3b\u83dc\u5355")
|
||||
: _T("\u9f20\u6807\u6eda\u8f6e\u4e0a\u4e0b\u7ffb\u52a8\uff0cEsc / Backspace / M \u8fd4\u56de\u5e2e\u52a9");
|
||||
: (helpState.currentPage == 4
|
||||
? _T("\u5de6\u53f3\u65b9\u5411\u952e / A D \u5207\u6362\uff0cEsc / Backspace / M \u8fd4\u56de\u4e3b\u83dc\u5355")
|
||||
: _T("\u9f20\u6807\u6eda\u8f6e\u4e0a\u4e0b\u7ffb\u52a8\uff0cEsc / Backspace / M \u8fd4\u56de\u5e2e\u52a9"));
|
||||
DrawText(hdc, helpHint, -1, &backHintRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
||||
|
||||
SelectClipRgn(hdc, nullptr);
|
||||
DrawBackButton();
|
||||
DrawMusicButton();
|
||||
SelectObject(hdc, oldFont);
|
||||
|
||||
Reference in New Issue
Block a user