cocos2dx 获取资源绝对路径
在执行某项目时,发现在 VS 调试环境下能够正常运行,但直接在生成目录执行 exe 文件时却出现黑屏现象。经过排查,问题出在资源文件加载方面,由于找不到图片,从而导致黑屏。
Cocos2d-x 查找图片的机制
下面我们来分析 Cocos2d-x 是如何查找图片的,先来看关键部分的源码。
获得完整路径
pathKey = CCFileUtils::sharedFileUtils()->fullPathForFilename(pathKey.c_str());
fullPathForFilename 函数的定义如下:
/**
* Returns the fullpath for a given filename.
* First it will try to get a new filename from the "filenameLookup" dictionary.
* If a new filename can't be found on the dictionary, it will use the original filename.
* Then it will try to obtain the full path of the filename using the CCFileUtils search rules: resolutions, and search paths.
* The file search is based on the array element order of search paths and resolution directories.
*
* For instance:
* .....
*
* @since v2.1
*/
virtual std::string fullPathForFilename(const char* pszFileName);
该函数的查找步骤如下:
- 判断是否为绝对路径:首先会判断传入的路径是否已经是绝对路径,如果是,则直接返回该路径。
- 从缓存中查询:接着会从缓存中查询之前已经加载过的资源,以传入的关键字作为 key 进行路径缓存查询。
- 从文件名查找字典中匹配:如果在缓存中找不到,则会从文件名查找字典中进行匹配。
- 从查询路径数组中匹配查找:若仍未找到,就会从查询路径数组中逐个进行匹配查找。在这个过程中,我们会发现
m_searchPathArray里已经存在了该项目目录下的Resource文件夹路径。显然,在初始化的时候设置了默认路径,下面我们继续追踪。
初始化默认资源路径
CCFileUtils 在初始化的时候会将默认资源路径 String 添加到数组中,代码如下:
bool CCFileUtils::init()
{
m_searchPathArray.push_back(m_strDefaultResRootPath);
m_searchResolutionsOrderArray.push_back("");
return true;
}
接下来我们查找 m_strDefaultResRootPath 是在哪里赋值的。以 win32 项目为例,在 CCFileUtilsWin32.cpp 中的子类构造函数里:
bool CCFileUtilsWin32::init()
{
_checkPath();
m_strDefaultResRootPath = s_pszResourcePath;
return CCFileUtils::init();
}
static void _checkPath()
{
if (! s_pszResourcePath[0])
{
WCHAR wszPath[MAX_PATH] = {0};
int nNum = WideCharToMultiByte(CP_ACP, 0, wszPath,
GetCurrentDirectoryW(sizeof(wszPath), wszPath),
s_pszResourcePath, MAX_PATH, NULL, NULL);
s_pszResourcePath[nNum] = '\\';
}
}
在 win32 平台,是通过 DWORD GetCurrentDirectoryW(DWORD nBufferLength, LPWSTR lpBuffer) 这个 win32 API 函数来获取当前的工作目录。当然,其他平台也有对应的获取方式。
项目属性中的工作目录设置
打开项目属性管理器面板的调试子面板,我们会发现通过 cocos2d-x 模板生成的项目,默认将工作目录设置为了 $(ProjectDir)..\\Resources。所以在调试时,得到的工作目录便是这个 Resources 文件夹。
解决方案
解决该问题的办法是将图片拷贝到 exe 所在的文件目录下。因为 exe 所在的目录就是当前工作目录,这样就可以匹配上资源文件,从而解决黑屏问题。