昨天在调新工程的时候发现个问题,程序启动后直接黑屏了,设断点看了一下,发现时因为无法找到Resource目录下的资源,仔细检查了一下,文件名都没错,到底为什么会有这种情况,然后又开了cocos2dx的官方例子看了看,发现官方例子都是没问题的,我这工程是直接用cocos new命令生成的,难道被官方坑了?还是打开方式不对?决定跟进程序看一下。发现这个跟cocos2dx在win32下读取文件的流程有关,cocos2dx在win32下读取文件的核心几步大概是这样,首先是通过FileUtils::fullPathForFilename这个方法找到绝对路径,注意该方法中的这段代码:
for (auto searchIt = _searchPathArray.cbegin(); searchIt != _searchPathArray.cend(); ++searchIt)
{
for (auto resolutionIt = _searchResolutionsOrderArray.cbegin(); resolutionIt != _searchResolutionsOrderArray.cend(); ++resolutionIt)
{
fullpath = this->getPathForFilename(newFilename, *resolutionIt, *searchIt);
if (fullpath.length() > 0)
{
// Using the filename passed in as key.
_fullPathCache.insert(std::make_pair(filename, fullpath));
return fullpath;
}
}
}
其实寻找的路径在_searchPathArray这个数组中,这个里面是绝对路径,这个数组可以通过FileUtils::setSearchPaths这个接口来设置,这个看下API就懂了。回到正题上,这个路径为什么会不对,在跟进去看,这个路径数组是怎么组成的,这个路径数组默认只是由一个路径组成,在FileUtils::init这个方法中可以看到他怎么构成的:
bool FileUtils::init()
{
_searchPathArray.push_back(_defaultResRootPath);
_searchResolutionsOrderArray.push_back("");
return true;
}
可以发现默认是在_defaultResRootPath这个路径搜索,这个字符串默认又是怎么生成的呢,在FileUtilsWin32::init这个方法中我们可以找到:
bool FileUtilsWin32::init()
{
_checkPath();
_defaultResRootPath = s_resourcePath;
return FileUtils::init();
}
再往下跟,看看s_resourcePath是怎么来的,在CCFileUtilsWin32.cpp这个文件中有这样一个静态函数:
static void _checkPath()
{
if (0 == s_resourcePath.length())
{
WCHAR utf16Path[CC_MAX_PATH] = {0};
GetCurrentDirectoryW(sizeof(utf16Path)-1, utf16Path);
char utf8Path[CC_MAX_PATH] = {0};
int nNum = WideCharToMultiByte(CP_UTF8, 0, utf16Path, -1, utf8Path, sizeof(utf8Path), NULL, NULL);
s_resourcePath = convertPathFormatToUnixStyle(utf8Path);
s_resourcePath.append("/");
}
}
我们发现在win32下,cocos2dx是通过GetCurrentDirectoryW获取到工作目录来在该目录下进行资源搜索的,在看下项目配置,
好吧,默认的工作目录是$(ProjectDir)这个宏的路径,看下这个宏,发现他指向的是proj.win32这个目录,怪不得会错,再看下cocos2dx官方例子的配置,
。。。。。。
好吧,所以一定要注意,用cocos new生成项目之后一定要改掉这个配置,或者把cocos new使用的default模板的这个参数直接改掉,不然会出现资源无法加载的问题。