转载标明出处:http://blog.csdn.net/notbaron/article/details/38356437
上篇回顾
上篇中,蛤蟆学习了精灵中的一些动画。认识了常用的精灵动作。
这次蛤蟆学习了cpp-tests项目,感觉受益匪浅。让我们赶紧开始。
目录介绍
这个cpp-tests由于示例代码非常多,导致Class目录下文件贼多,蛤蟆截了两次图才截齐的。如下图 1 ,图 2所示
共58个文件夹,外加7个头文件,5个 CPP文件,非常的有规律哦。
每个文件夹其实基本上就是实现了 下图3 中的一个红框,只是基本上。因为难免会有特里的嘛。
代码架构
a) 第一步 main.cpp
函数从proj.win32目录中的main.cpp开始。
第一个函数是:
int APIENTRY _tWinMain(HINSTANCEhInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
这个和HelloWorld项目是一模一样的。
b) 第二步 AppDelegate.cpp
然后跳到AppDelegate.cpp文件中的bool AppDelegate::applicationDidFinishLaunching() 函数。
这个是整个cpp-tests工程的初始化部分。我们需要很有耐心的看完,看懂这个函数后其他的都是很有规律性的了。
这个函数首先加载一个配置文件:
Configuration::getInstance()->loadConfigFile("configs/config-example.plist");
这个配置文件在项目中的 Resources\configs文件中。该文件只是设置了FPS(Frames Per Second),图片属性等,暂时无须太多关注。
创建一个导演,获得视图,获得屏幕大小,设置视图大小。这些对整理理解没有太大作用。
然后是如下代码,
auto fileUtils = FileUtils::getInstance();
std::vector<std::string> searchPaths;
if (screenSize.height > 320)
{
auto resourceSize =Size(960, 640);
searchPaths.push_back("hd");
searchPaths.push_back("ccs-res/hd");
searchPaths.push_back("ccs-res/hd/scenetest");
searchPaths.push_back("ccs-res/hd/scenetest/ArmatureComponentTest");
searchPaths.push_back("ccs-res/hd/scenetest/AttributeComponentTest");
searchPaths.push_back("ccs-res/hd/scenetest/BackgroundComponentTest");
searchPaths.push_back("ccs-res/hd/scenetest/EffectComponentTest");
searchPaths.push_back("ccs-res/hd/scenetest/LoadSceneEdtiorFileTest");
searchPaths.push_back("ccs-res/hd/scenetest/ParticleComponentTest");
searchPaths.push_back("ccs-res/hd/scenetest/SpriteComponentTest");
searchPaths.push_back("ccs-res/hd/scenetest/TmxMapComponentTest");
searchPaths.push_back("ccs-res/hd/scenetest/UIComponentTest");
searchPaths.push_back("ccs-res/hd/scenetest/TriggerTest");
searchPaths.push_back("ccs-res");
director->setContentScaleFactor(resourceSize.height/designSize.height);
}
else
{
searchPaths.push_back("ccs-res");
searchPaths.push_back("ccs-res/scenetest/ArmatureComponentTest");
searchPaths.push_back("ccs-res/scenetest/AttributeComponentTest");
searchPaths.push_back("ccs-res/scenetest/BackgroundComponentTest");
searchPaths.push_back("ccs-res/scenetest/EffectComponentTest");
searchPaths.push_back("ccs-res/scenetest/LoadSceneEdtiorFileTest");
searchPaths.push_back("ccs-res/scenetest/ParticleComponentTest");
searchPaths.push_back("ccs-res/scenetest/SpriteComponentTest");
searchPaths.push_back("ccs-res/scenetest/TmxMapComponentTest");
searchPaths.push_back("ccs-res/scenetest/UIComponentTest");
searchPaths.push_back("ccs-res/scenetest/TriggerTest");
}
//此处省略的是 给searchPaths变量赋值。主要是有10个test,由于屏幕高端不同引起资源使用不同。
fileUtils->setSearchPaths(searchPaths);
这个是设置资源的查找路径。我么你可以看到由于高度不同,设置的资源优先级是不同的,高度高于320的时候,优先查找hd目录下,如果小于320就不查找hd目录。
#if (CC_TARGET_PLATFORM ==CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM ==CC_PLATFORM_WINRT)
根据平台不一致,选择不同的屏幕解决方案。
auto scene =Scene::create();
auto layer = new TestController();
创建一个场景,创建一个TestControoler层.
TestController类层是在TestController.h中定义的,该类继承Layer类。同时该类中实现了addConsoleAutoTest(); 该函数实现了控制台,用于文本输入输出。该类我们下一步单独介绍。
然后将层添加上场景当中,执行该场景。
最后判断是否是WINRT平台,如果是的话,就获取config-example.plist文件的cocos2d.x.testcpp.autorun 变量时否为TRUE,如果为TRUE就启动个自动运行。
c) 第三步TestController
对于该类,蛤蟆主要介绍其初始化干了什么,因为初始化会影响我们队整个结构的理解。
我们只看TestController::TestController() 构造函数。
首先创建一个关闭菜单。代码如下
auto closeItem =MenuItemImage::create(s_pathClose, s_pathClose,CC_CALLBACK_1(TestController::closeCallback,this) );
auto menu =Menu::create(closeItem,nullptr);
menu->setPosition( Vec2::ZERO);
closeItem->setPosition(Vec2(VisibleRect::right().x- 30,VisibleRect::top().y- 30));
这里CC_CALLBACK_1表示回调函数,点击该菜单后调用函数TestController::closeCallback.
其中s_pathClose 是宏定义在testResource.h 头文件中。如下
static const char s_pathClose[] ="Images/close.png";
然后设置字体类型,接着创建标签菜单,代码如下蛤蟆逐一解释。
TTFConfig ttfConfig("fonts/arial.ttf", 24); //加载resources/fonts/目录下的ariarl.ttf文件。
_itemMenu = Menu::create();//创建菜单
for (int i = 0; i < g_testCount; ++i) //for循环,g_testCount是一个g_aTestNames[]数组的数量,这个数组中每个类型是是一个结构体,一个测试用例名,一个该测试用例的函数叫做callback。
typedef struct_Controller{
const char *test_name;
std::function<TestScene*()> callback;
} Controller;
{
auto label =Label::createWithTTF(ttfConfig,g_aTestNames[i].test_name);//创建标签
auto menuItem =MenuItemLabel::create(label,CC_CALLBACK_1(TestController::menuCallback,this));//根据标签,创建菜单项
_itemMenu->addChild(menuItem, i + 10000);//将菜单项加入到餐单里面
menuItem->setPosition( Vec2( VisibleRect::center().x, (VisibleRect::top().y - (i + 1) *LINE_SPACE) )); //设置菜单项位置。
}
_itemMenu->setContentSize(Size(VisibleRect::getVisibleRect().size.width,(g_testCount + 1) * (LINE_SPACE))); //设置菜单大小
_itemMenu->setPosition(s_tCurPos);//设置菜单位置
addChild(_itemMenu); //添加菜单到TestController层中
addChild(menu, 1); //添加clouse菜单
最后是注册触屏事件,代码如下
auto listener =EventListenerTouchOneByOne::create();//创一个单点监听。
listener->setSwallowTouches(true); //设置是否向下传递。
listener->onTouchBegan = CC_CALLBACK_2(TestController::onTouchBegan,this); //触屏按下的回调函数
listener->onTouchMoved= CC_CALLBACK_2(TestController::onTouchMoved,this);
//触屏滑动的回调函数
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);//给事件添加一个事件侦听器。
auto mouseListener =EventListenerMouse::create();//创建鼠标监听器
mouseListener->onMouseScroll = CC_CALLBACK_1(TestController::onMouseScroll,this);//滚动回调函数
_eventDispatcher->addEventListenerWithSceneGraphPriority(mouseListener,this);//给事件添加侦听器,_eventDispatcher 是,每个Node都有的变量,是一个事件调度器,负责调度各种事件。
d) 第四步 菜单回调函数
按下一个菜单后,菜单都会调用 void TestController::menuCallback(Ref *sender) 函数。代码如下
Director::getInstance()->purgeCachedData(); //purge表示清除的意思,所以这个函数意思是: 移除所有 cocos2d 缓存数据.
清除 TextureCache, SpriteFrameCache, LabelBMFont 缓存
// get the userdata, it's the index of the menu item clicked
automenuItem =static_cast<MenuItem *>(sender);//定义个菜单项常量
int idx = menuItem->getLocalZOrder() - 10000;//获取菜单项的纵坐标
// create the test scene and run it
auto scene = g_aTestNames[idx].callback();//调用该测试用例场景的callback函数,该函数其实就是new一个测试场景而已。
if (scene)//如果上行返回正常,则运行该测试场景。
{
scene->runThisTest(); //运行该测试场景,这样就进入了其中一个测试场景。
scene->release();
}
e) 第五步 测试场景TestScene
现在我们通过点击菜单进入到了测试场景中。测试场景都是继承 TestScene, 而TestScene类是继承Scene类。
如下图4所示
TestScene类定义在testBasic.h文件中。主要是voidTestScene::onEnter() 函数的初始化。设置字体形式,创建一个MainMenu字体标签如下图5 所示,设置MainMenu菜单回调函数testScene_callback。
菜单MainMenu的回调函(testScene_callback函数),重新new一个TestController类。
f) 第六步 具体测试场景***TestScene
具体场景继承于TestScene,相比TestScene类,多实现了一个runThisTest() 函数。
该函数创建一个Layer层,然后将该层添加到场景中。
g) 第七步 具体测试Layer层,基类
在每个测试场景的runThisTest() 函数 中,会创建Layer层。
真正的测试Layer层,继承于***Test层,***Test层继承于BaseTest层。
例如以:
第一个菜单ActionManager中的CrashTest层,继承于 ActionManagerTest,而ActionManagerTest继承于 BaseTest。BaseTest继承于Layer 层。
BaseTest层主要定义了7个虚函数,如下。其中实现了onEnter()和onExit()函数。
virtual std::stringtitle()const;
virtual std::stringsubtitle()const;
virtualvoidrestartCallback(Ref*sender);
virtualvoidnextCallback(Ref* sender);
virtualvoidbackCallback(Ref* sender);
virtual voidonEnter() override;
virtual voidonExit() override;需要在
BaseTest层中的onEnter函数实现了
获取测试场景中title(该函数在ActionManagerTest中实现), 设置字体形式,添加字体到BaseTest层上。
获取子title(该函数在ActionManagerTest中实现),设置子titile的字体形式,添加到BaseTest层上。
BaseTest最重要的的实现了3个菜单,并将菜单加入到BaseTest层中。
菜单如下图 6 红框部分所示。
三个回调函数分别是:
BaseTest::backCallback
BaseTest::restartCallback
BaseTest::nextCallback
这三个函数在 ActionManagerTest层中实现。分别是调用上一个测试层,重新运行该测试层,调用下一个测试层。
OK,其他测试场景都是类似的。
总结
通过本笔记,我们知道了cpp-tests项目的总体架构。从此我们可以根据实际情况来找和版本对应的代码了。再也不愁网上教程的代码和我们所下载版本的不一致了。因为这个项目里面基本包含所有你需要的代码。