项目架构重构,代码整理
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
#include "stdafx.h"
|
||||
#include "Tetris.h"
|
||||
#include "TetrisAppInternal.h"
|
||||
#include "TetrisAssets.h"
|
||||
#include <shellapi.h>
|
||||
#include <string>
|
||||
|
||||
static bool bgmPlaying = false;
|
||||
static bool bgmUsingMci = false;
|
||||
static constexpr const wchar_t* kBgmAlias = L"TereisBgm";
|
||||
static constexpr const wchar_t* kReviveVideoAlias = L"TereisReviveVideo";
|
||||
|
||||
/**
|
||||
* @brief 尝试通过 MCI 循环播放指定音乐文件。
|
||||
*/
|
||||
static bool TryPlayMciLoop(const std::wstring& path, bool forceMpegVideo)
|
||||
{
|
||||
if (!FileExists(path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mciSendStringW((std::wstring(L"close ") + kBgmAlias).c_str(), nullptr, 0, nullptr);
|
||||
|
||||
std::wstring openCommand = L"open \"" + path + L"\" ";
|
||||
if (forceMpegVideo)
|
||||
{
|
||||
openCommand += L"type mpegvideo ";
|
||||
}
|
||||
openCommand += L"alias ";
|
||||
openCommand += kBgmAlias;
|
||||
|
||||
if (mciSendStringW(openCommand.c_str(), nullptr, 0, nullptr) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring playCommand = std::wstring(L"play ") + kBgmAlias + L" repeat";
|
||||
if (mciSendStringW(playCommand.c_str(), nullptr, 0, nullptr) != 0)
|
||||
{
|
||||
mciSendStringW((std::wstring(L"close ") + kBgmAlias).c_str(), nullptr, 0, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
bgmPlaying = true;
|
||||
bgmUsingMci = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 停止背景音乐并释放当前使用的播放设备。
|
||||
*/
|
||||
void StopBackgroundMusic()
|
||||
{
|
||||
if (bgmUsingMci)
|
||||
{
|
||||
mciSendStringW((std::wstring(L"stop ") + kBgmAlias).c_str(), nullptr, 0, nullptr);
|
||||
mciSendStringW((std::wstring(L"close ") + kBgmAlias).c_str(), nullptr, 0, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
PlaySoundW(nullptr, nullptr, 0);
|
||||
}
|
||||
|
||||
bgmPlaying = false;
|
||||
bgmUsingMci = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 按资源优先级查找并启动背景音乐。
|
||||
*/
|
||||
void StartBackgroundMusic()
|
||||
{
|
||||
if (!bgmEnabled || bgmPlaying)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const wchar_t* bgmWavRelativePath = L"assets\\audio\\bgm.wav";
|
||||
const std::wstring bgmWavCandidates[] =
|
||||
{
|
||||
BuildAssetPath(bgmWavRelativePath),
|
||||
BuildWorkingDirAssetPath(bgmWavRelativePath)
|
||||
};
|
||||
|
||||
for (const std::wstring& candidate : bgmWavCandidates)
|
||||
{
|
||||
if (FileExists(candidate) &&
|
||||
PlaySoundW(candidate.c_str(), nullptr, SND_FILENAME | SND_ASYNC | SND_LOOP))
|
||||
{
|
||||
bgmPlaying = true;
|
||||
bgmUsingMci = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const wchar_t* oggRelativePath = L"assets\\audio\\bgm.ogg";
|
||||
const std::wstring oggCandidates[] =
|
||||
{
|
||||
BuildAssetPath(oggRelativePath),
|
||||
BuildWorkingDirAssetPath(oggRelativePath)
|
||||
};
|
||||
|
||||
for (const std::wstring& candidate : oggCandidates)
|
||||
{
|
||||
if (TryPlayMciLoop(candidate, false) || TryPlayMciLoop(candidate, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const wchar_t* fallbackWavRelativePath = L"assets\\audio\\background.wav";
|
||||
const std::wstring fallbackWavCandidates[] =
|
||||
{
|
||||
BuildAssetPath(fallbackWavRelativePath),
|
||||
BuildWorkingDirAssetPath(fallbackWavRelativePath)
|
||||
};
|
||||
|
||||
for (const std::wstring& candidate : fallbackWavCandidates)
|
||||
{
|
||||
if (FileExists(candidate) &&
|
||||
PlaySoundW(candidate.c_str(), nullptr, SND_FILENAME | SND_ASYNC | SND_LOOP))
|
||||
{
|
||||
bgmPlaying = true;
|
||||
bgmUsingMci = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bgmEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 切换背景音乐开关并刷新窗口。
|
||||
*/
|
||||
void ToggleBackgroundMusic(HWND hWnd)
|
||||
{
|
||||
bgmEnabled = !bgmEnabled;
|
||||
if (bgmEnabled)
|
||||
{
|
||||
StartBackgroundMusic();
|
||||
}
|
||||
else
|
||||
{
|
||||
StopBackgroundMusic();
|
||||
}
|
||||
InvalidateRect(hWnd, nullptr, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 播放复活视频,先尝试 MCI,全屏播放失败时退回系统默认播放器。
|
||||
*/
|
||||
bool PlayReviveVideo(HWND hWnd)
|
||||
{
|
||||
std::wstring videoPath = BuildAssetPath(L"assets\\video\\video.avi");
|
||||
if (!FileExists(videoPath))
|
||||
{
|
||||
videoPath = BuildWorkingDirAssetPath(L"assets\\video\\video.avi");
|
||||
}
|
||||
if (!FileExists(videoPath))
|
||||
{
|
||||
videoPath = BuildAssetPath(L"assets\\video\\video.mp4");
|
||||
}
|
||||
if (!FileExists(videoPath))
|
||||
{
|
||||
videoPath = BuildWorkingDirAssetPath(L"assets\\video\\video.mp4");
|
||||
}
|
||||
if (!FileExists(videoPath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool shouldResumeBgm = bgmEnabled;
|
||||
if (bgmPlaying)
|
||||
{
|
||||
StopBackgroundMusic();
|
||||
}
|
||||
|
||||
bool played = false;
|
||||
for (int attempt = 0; attempt < 2 && !played; attempt++)
|
||||
{
|
||||
bool forceMpegVideo = attempt == 0;
|
||||
mciSendStringW((std::wstring(L"close ") + kReviveVideoAlias).c_str(), nullptr, 0, nullptr);
|
||||
|
||||
std::wstring openCommand = L"open \"" + videoPath + L"\" ";
|
||||
if (forceMpegVideo)
|
||||
{
|
||||
openCommand += L"type mpegvideo ";
|
||||
}
|
||||
openCommand += L"alias ";
|
||||
openCommand += kReviveVideoAlias;
|
||||
|
||||
if (mciSendStringW(openCommand.c_str(), nullptr, 0, hWnd) == 0)
|
||||
{
|
||||
std::wstring playCommand = std::wstring(L"play ") + kReviveVideoAlias + L" fullscreen wait";
|
||||
MCIERROR playResult = mciSendStringW(playCommand.c_str(), nullptr, 0, hWnd);
|
||||
mciSendStringW((std::wstring(L"close ") + kReviveVideoAlias).c_str(), nullptr, 0, nullptr);
|
||||
played = playResult == 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!played)
|
||||
{
|
||||
SHELLEXECUTEINFOW shellInfo = {};
|
||||
shellInfo.cbSize = sizeof(shellInfo);
|
||||
shellInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
|
||||
shellInfo.hwnd = hWnd;
|
||||
shellInfo.lpVerb = L"open";
|
||||
shellInfo.lpFile = videoPath.c_str();
|
||||
shellInfo.nShow = SW_SHOWNORMAL;
|
||||
|
||||
if (ShellExecuteExW(&shellInfo))
|
||||
{
|
||||
if (shellInfo.hProcess != nullptr)
|
||||
{
|
||||
WaitForSingleObject(shellInfo.hProcess, INFINITE);
|
||||
CloseHandle(shellInfo.hProcess);
|
||||
}
|
||||
played = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldResumeBgm)
|
||||
{
|
||||
StartBackgroundMusic();
|
||||
}
|
||||
|
||||
return played;
|
||||
}
|
||||
Reference in New Issue
Block a user