#include "stdafx.h" /** * @file TetrisAssets.cpp * @brief 实现资源路径解析和文件存在性检查,支持构建目录或项目根目录运行。 */ #include "TetrisAssets.h" /** * @brief 根据程序所在目录拼出项目资源文件的绝对路径。 * * 构建脚本会把可执行文件放到构建目录,因此这里先回到项目根目录, * 再拼接 assets 下的图片、音频或视频路径。 * * @param relativePath 相对于项目根目录的资源路径。 * @return 规范化后的绝对路径;解析失败时返回拼接路径。 */ std::wstring BuildAssetPath(const wchar_t* relativePath) { wchar_t modulePath[MAX_PATH] = {}; GetModuleFileNameW(nullptr, modulePath, MAX_PATH); std::wstring basePath(modulePath); size_t lastSlash = basePath.find_last_of(L"\\/"); if (lastSlash != std::wstring::npos) { basePath.resize(lastSlash); } // 可执行文件位于构建目录,向上两级回到项目根目录。 std::wstring projectRelative = basePath + L"\\..\\..\\" + relativePath; wchar_t fullPath[MAX_PATH] = {}; DWORD result = GetFullPathNameW(projectRelative.c_str(), MAX_PATH, fullPath, nullptr); if (result > 0 && result < MAX_PATH) { return fullPath; } return projectRelative; } /** * @brief 根据当前工作目录拼出项目资源文件的绝对路径。 * * 这个路径用于从 IDE 或命令行直接以项目根目录运行时查找资源。 * * @param relativePath 相对于当前工作目录的资源路径。 * @return 规范化后的绝对路径;解析失败时返回拼接路径。 */ std::wstring BuildWorkingDirAssetPath(const wchar_t* relativePath) { wchar_t currentDirectory[MAX_PATH] = {}; DWORD length = GetCurrentDirectoryW(MAX_PATH, currentDirectory); if (length == 0 || length >= MAX_PATH) { return L""; } std::wstring candidate = std::wstring(currentDirectory) + L"\\" + relativePath; wchar_t fullPath[MAX_PATH] = {}; DWORD result = GetFullPathNameW(candidate.c_str(), MAX_PATH, fullPath, nullptr); if (result > 0 && result < MAX_PATH) { return fullPath; } return candidate; } /** * @brief 判断指定路径是否存在且不是目录。 * @param path 待检查的文件路径。 * @return 文件存在且不是目录返回 true,否则返回 false。 */ bool FileExists(const std::wstring& path) { DWORD attributes = GetFileAttributesW(path.c_str()); return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0; }