(原创)cocos2d-x 3.0 示例代码分析2:TestController
星月最近有点忙,所以博客更新落下了~~~(小白:赶紧进入正题。。。)
上一篇文章中http://www.cnblogs.com/wodehao0808/p/4019587.html,有段代码:
// 创建图层 auto layer = new TestController();
在本章中看下这个layer是用来做啥的,哈哈哈~~~(小白:傻笑你妹~~)
-- TestController.h // TestController是一个Layer,用这个layer来控制整个testcpp #ifndef _CONTROLLER_H_ #define _CONTROLLER_H_ #include "cocos2d.h" USING_NS_CC; class TestController : public Layer { public: // 构造函数 TestController(); // 析构函数 ~TestController(); // 菜单按钮回调 void menuCallback(Ref * sender); // 关闭按钮回调 void closeCallback(Ref * sender); // 触摸:开始 bool onTouchBegan(Touch* touches, Event *event); // 触摸:移动 void onTouchMoved(Touch* touches, Event *event); // 鼠标:滚动 void onMouseScroll(Event *event); // 函数实现了控制台,用于文本输入输出 void addConsoleAutoTest(); private: Point _beginPos; // 开始触摸点 Menu* _itemMenu; // 菜单按钮 }; #endif
上面是头文件,里面注释很清楚。3.0增加了一个:鼠标:滚动。功能,越来越强大了。。。
接下来看.cpp文件。。。
// TestController.h // C++ includes #include <map> #include <functional> #include <string> #include <chrono> // 日期时间相关的库,参考资料: http://www.2cto.com/kf/201404/290706.html #include <thread> // 线程操作的类, 参考资料:http://www.cocoachina.com/cocos/20140523/8530.html // test inclues #include "AppDelegate.h" #include "BaseTest.h" // 基类,提供场景一些公共功能,详情请查看该类的说明文章。(小白:你出了吗?星月:还没...) #include "controller.h" #include "testResource.h" // 资源配置 #include "tests.h" // 头文件集合~~~ #if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32) && (CC_TARGET_PLATFORM != CC_PLATFORM_WP8) && (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT) #include <unistd.h> #include <sys/socket.h> #else #include <io.h> #endif #include "cocostudio/CocoStudio.h" // 定义数据结构:变量名,一个返回TestScene指针的函数 typedef struct _Controller{ const char *test_name; std::function<TestScene*()> callback; } Controller; // Controller类型的数组变量 Controller g_aTestNames[] = { // // TESTS MUST BE ORDERED ALPHABETICALLY // violators will be prosecuted // // 第一个参数是name,第二个参数是:返回生成的新的scene。的函数方法 // 星月:对c++ 11 新特性不是很了解,上面是按照自己的理解去解释的,不一定正确,欢迎各位指出错误(小白:你个坑货~~~) { "Accelerometer", []() { return new AccelerometerTestScene(); } }, { "ActionManager", [](){return new ActionManagerTestScene(); } }, { "Actions - Basic", [](){ return new ActionsTestScene(); } }, { "Actions - Ease", [](){return new ActionsEaseTestScene();} }, { "Actions - Progress", [](){return new ProgressActionsTestScene(); } }, { "Audio - CocosDenshion", []() { return new CocosDenshionTestScene(); } }, { "Box2d - Basic", []() { return new Box2DTestScene(); } }, { "Box2d - TestBed", []() { return new Box2dTestBedScene(); } }, { "Bugs", []() { return new BugsTestScene(); } }, { "Chipmunk", []() { return new ChipmunkAccelTouchTestScene(); } }, { "Click and Move", [](){return new ClickAndMoveTestScene(); } }, { "Configuration", []() { return new ConfigurationTestScene(); } }, #if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8) #if (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT) { "Console", []() { return new ConsoleTestScene(); } }, #endif #endif #if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8) #if (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT) #if (CC_TARGET_PLATFORM != CC_PLATFORM_EMSCRIPTEN) #if (CC_TARGET_PLATFORM != CC_PLATFORM_NACL) #if (CC_TARGET_PLATFORM != CC_PLATFORM_MARMALADE) #if (CC_TARGET_PLATFORM != CC_PLATFORM_BADA) { "Curl", []() { return new CurlTestScene(); } }, #endif #endif #endif #endif #endif #endif { "Current Language", []() { return new CurrentLanguageTestScene(); } }, { "EventDispatcher", []() { return new EventDispatcherTestScene(); } }, { "Effects - Advanced", []() { return new EffectAdvanceScene(); } }, { "Effects - Basic", [](){return new EffectTestScene();} }, { "Extensions", []() { return new ExtensionsTestScene(); } }, { "FileUtils", []() { return new FileUtilsTestScene(); } }, { "Fonts", []() { return new FontTestScene(); } }, { "Interval", [](){return new IntervalTestScene(); } }, { "Keyboard", []() { return new KeyboardTestScene(); } }, { "Keypad", []() { return new KeypadTestScene(); } }, { "Node: Clipping", []() { return new ClippingNodeTestScene(); } }, { "Node: Draw", [](){return new DrawPrimitivesTestScene();} }, { "Node: Label - New API", [](){return new AtlasTestSceneNew(); } }, { "Node: Label - Old API", [](){return new AtlasTestScene(); } }, { "Node: Layer", [](){return new LayerTestScene();} }, { "Node: Menu", [](){return new MenuTestScene();} }, { "Node: MotionStreak", [](){return new MotionStreakTestScene();} }, { "Node: Node", [](){return new CocosNodeTestScene();} }, { "Node: Parallax", [](){return new ParallaxTestScene(); } }, { "Node: Particles", [](){return new ParticleTestScene(); } }, { "Node: Physics", []() { return new PhysicsTestScene(); } }, { "Node: RenderTexture", [](){return new RenderTextureScene(); } }, { "Node: Scene", [](){return new SceneTestScene();} }, { "Node: Spine", []() { return new SpineTestScene(); } }, { "Node: Sprite", [](){return new SpriteTestScene(); } }, { "Node: TileMap", [](){return new TileMapTestScene(); } }, { "Node: Text Input", [](){return new TextInputTestScene(); } }, { "Mouse", []() { return new MouseTestScene(); } }, { "MutiTouch", []() { return new MutiTouchTestScene(); } }, { "Performance tests", []() { return new PerformanceTestScene(); } }, { "Renderer", []() { return new NewRendererTestScene(); } }, { "ReleasePool", [](){ return new ReleasePoolTestScene(); } }, { "Rotate World", [](){return new RotateWorldTestScene(); } }, { "Scheduler", [](){return new SchedulerTestScene(); } }, { "Shader - Basic", []() { return new ShaderTestScene(); } }, { "Shader - Sprite", []() { return new ShaderTestScene2(); } }, { "Texture2D", [](){return new TextureTestScene(); } }, { "TextureCache", []() { return new TextureCacheTestScene(); } }, { "TexturePacker Encryption", []() { return new TextureAtlasEncryptionTestScene(); } }, { "Touches", [](){return new PongScene();} }, { "Transitions", [](){return new TransitionsTestScene();} }, { "Unit Test", []() { return new UnitTestScene(); }}, { "UserDefault", []() { return new UserDefaultTestScene(); } }, { "Zwoptex", []() { return new ZwoptexTestScene(); } }, }; static int g_testCount = sizeof(g_aTestNames) / sizeof(g_aTestNames[0]); // 获得菜单项数目 static Controller *currentController = nullptr; // 定义一个静态指针,指向当前打开的场景 #define LINE_SPACE 40 // 菜单项之间的间距 static Point s_tCurPos = Point::ZERO; // 定义一个静态位置变量,当前菜单项位置 //sleep for t seconds static void wait(int t) { // 线程睡眠函数,参考资料:http://www.2cto.com/kf/201312/264724.html 和 http://zh.cppreference.com/w/cpp/thread/sleep_for std::chrono::milliseconds dura( t * 1000 ); std::this_thread::sleep_for( dura ); } // 构造函数 TestController::TestController() : _beginPos(Point::ZERO) // 初始化:开始触摸点 { // add close menu // 右上角的关闭按钮 auto closeItem = MenuItemImage::create(s_pathClose, s_pathClose, CC_CALLBACK_1(TestController::closeCallback, this) ); auto menu =Menu::create(closeItem, NULL); // 设置关闭按钮的位置 menu->setPosition( Point::ZERO ); closeItem->setPosition(Point( VisibleRect::right().x - 30, VisibleRect::top().y - 30)); // add menu items for tests // 字体配置: 字体路径,字体大小 TTFConfig ttfConfig("fonts/arial.ttf", 24); // 创建主菜单,添加菜单项 _itemMenu = Menu::create(); for (int i = 0; i < g_testCount; ++i) { 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); // 为了避免冲突,这里加10000 menuItem->setPosition( Point( 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); addChild(menu, 1); // Register Touch Event 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); // 将触摸监听添加到事件调度eventDispacher中 auto mouseListener = EventListenerMouse::create(); // 创建一个鼠标响应事件 mouseListener->onMouseScroll = CC_CALLBACK_1(TestController::onMouseScroll, this); // 鼠标:滚动。回调函数 _eventDispatcher->addEventListenerWithSceneGraphPriority(mouseListener, this); // 将触摸监听添加到事件调度eventDispacher中 } // 析构函数 TestController::~TestController() { } // 菜单按钮回调 void TestController::menuCallback(Ref * sender) { Director::getInstance()->purgeCachedData(); // 清除缓存的数据 // get the userdata, it's the index of the menu item clicked auto menuItem = static_cast<MenuItem *>(sender); // 转换类型 int idx = menuItem->getLocalZOrder() - 10000; // 获得点击菜单是第几个,addChild的时候加了10000,所以这里减去10000 // create the test scene and run it // 获取父类为TestScene的xxx场景 auto scene = g_aTestNames[idx].callback(); // 根据index获得数组元素,调用元素方法callback()返回创建的场景 if (scene) // 场景存在,运行这个场景 { scene->runThisTest(); // 运行这个场景 scene->release(); // 释放,因为用new生成的~~~ } } // 关闭按钮回调,结束游戏 void TestController::closeCallback(Ref * sender) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); return; #endif Director::getInstance()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif } // 触摸:开始 bool TestController::onTouchBegan(Touch* touch, Event *event) { _beginPos = touch->getLocation(); // 记录触摸开始点 return true; // true:触摸成功 } // 触摸:移动 void TestController::onTouchMoved(Touch* touch, Event *event) { auto touchLocation = touch->getLocation(); // 当前触摸点 float nMoveY = touchLocation.y - _beginPos.y; // y轴移动距离 auto curPos = _itemMenu->getPosition(); // 获得菜单项位置 auto nextPos = Point(curPos.x, curPos.y + nMoveY); // 计算移动后,菜单项位置 if (nextPos.y < 0.0f) // 如果移动后位置小于最小位置,则将移动后位置设置为:最小。 { _itemMenu->setPosition(Point::ZERO); return; } // 如果移动后位置大于最大位置,则将移动后位置设置为:最大。 if (nextPos.y > ((g_testCount + 1)* LINE_SPACE - VisibleRect::getVisibleRect().size.height)) { _itemMenu->setPosition(Point(0, ((g_testCount + 1)* LINE_SPACE - VisibleRect::getVisibleRect().size.height))); return; } _itemMenu->setPosition(nextPos); // 设置菜单项位置 _beginPos = touchLocation; // 将当前触摸点位置设置为起始位置,以便下次计算 s_tCurPos = nextPos; // 保存菜单项当前位置 } // 鼠标:滚动(类似于onTouchMoved,这里就不解释了~~~) void TestController::onMouseScroll(Event *event) { auto mouseEvent = static_cast<EventMouse*>(event); float nMoveY = mouseEvent->getScrollY() * 6; auto curPos = _itemMenu->getPosition(); auto nextPos = Point(curPos.x, curPos.y + nMoveY); if (nextPos.y < 0.0f) { _itemMenu->setPosition(Point::ZERO); return; } if (nextPos.y > ((g_testCount + 1)* LINE_SPACE - VisibleRect::getVisibleRect().size.height)) { _itemMenu->setPosition(Point(0, ((g_testCount + 1)* LINE_SPACE - VisibleRect::getVisibleRect().size.height))); return; } _itemMenu->setPosition(nextPos); s_tCurPos = nextPos; } #if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8) && (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT) // 函数实现了控制台,用于文本输入输出 void TestController::addConsoleAutoTest() { // 获得控制台 auto console = Director::getInstance()->getConsole(); static struct Console::Command autotest = { "autotest", "testcpp autotest command, use -h to list available tests", [](int fd, const std::string& args) { Scheduler *sched = Director::getInstance()->getScheduler(); if(args == "help" || args == "-h") { const char msg[] = "usage: autotest ActionsTest\n\tavailable tests: "; send(fd, msg, sizeof(msg),0); send(fd, "\n",1,0); for(int i = 0; i < g_testCount; i++) { send(fd, "\t",1,0); send(fd, g_aTestNames[i].test_name, strlen(g_aTestNames[i].test_name)+1,0); send(fd, "\n",1,0); } const char help_main[] = "\tmain, return to main menu\n"; send(fd, help_main, sizeof(help_main),0); const char help_next[] = "\tnext, run next test\n"; send(fd, help_next, sizeof(help_next),0); const char help_back[] = "\tback, run prev test\n"; send(fd, help_back, sizeof(help_back),0); const char help_restart[] = "\trestart, restart current test\n"; send(fd, help_restart, sizeof(help_restart),0); return; } if(args == "main") { sched->performFunctionInCocosThread( [&]() { auto scene = Scene::create(); auto layer = new TestController(); scene->addChild(layer); layer->release(); Director::getInstance()->replaceScene(scene); cocostudio::ArmatureDataManager::destroyInstance(); } ); return; } const char msg_notest[] = "autotest: can't detect running test.\n"; AppDelegate* app = (AppDelegate *)Application::getInstance(); BaseTest* currentTest = app->getCurrentTest(); if(args == "next") { if(currentTest != nullptr) { //currentTest->nextCallback(nullptr); sched->performFunctionInCocosThread( [&](){ currentTest->nextCallback(nullptr); } ); } else { send(fd, msg_notest, sizeof(msg_notest),0); } return; } if(args == "back") { if(currentTest != nullptr) { sched->performFunctionInCocosThread( [&](){ currentTest->backCallback(nullptr); } ); } else { send(fd, msg_notest, sizeof(msg_notest),0); } return; } if(args == "restart") { if(currentTest != nullptr) { sched->performFunctionInCocosThread( [&](){ currentTest->restartCallback(nullptr); } ); } else { send(fd, msg_notest, sizeof(msg_notest),0); } return; } if(args == "run") { for (int i = 0; i < g_testCount; i++) { // create the test scene and run it std::string msg("autotest: running test:"); msg += g_aTestNames[i].test_name; send(fd, msg.c_str(), strlen(msg.c_str()),0); send(fd, "\n",1,0); currentController = &g_aTestNames[i]; sched->performFunctionInCocosThread( [&](){ auto scene = currentController->callback(); if(scene) { scene->runThisTest(); scene->release(); } } ); wait(1); BaseTest* firstTest = app->getCurrentTest(); if(firstTest == nullptr) { continue; } std::string t1(""); t1 += firstTest->subtitle(); send(fd, t1.c_str(), strlen(t1.c_str()),0); send(fd, "\n",1,0); wait(2); while(1) { //currentTest->nextCallback(nullptr); sched->performFunctionInCocosThread( [&](){ BaseTest *t = app->getCurrentTest(); if(t != nullptr) { t->nextCallback(nullptr); } } ); wait(1); BaseTest * curTest = app->getCurrentTest(); if(curTest == nullptr) { break; } std::string title(""); title += curTest->subtitle(); send(fd, title.c_str(), strlen(title.c_str()),0); send(fd, "\n",1,0); wait(2); if(t1 == title) { break; } } } return; } for(int i = 0; i < g_testCount; i++) { if(args == g_aTestNames[i].test_name) { currentController = &g_aTestNames[i]; std::string msg("autotest: running test:"); msg += args; send(fd, msg.c_str(), strlen(msg.c_str()),0); send(fd, "\n",1,0); sched->performFunctionInCocosThread( [&](){ auto scene = currentController->callback(); if(scene) { scene->runThisTest(); scene->release(); } } ); return; } } //no match found,print warning message std::string msg("autotest: could not find test:"); msg += args; send(fd, msg.c_str(), strlen(msg.c_str()),0); send(fd, "\n",1,0); } }; console->addCommand(autotest); } #endif
好吧,这篇文章勉强完成。星月在这里给大家道歉,写这篇文章时没有考虑到会涉及这么多知识点,希望大家指出错误的敌方,星月会不断改变~~~
// 函数实现了控制台,用于文本输入输出
void TestController::addConsoleAutoTest()
这个函数星月没有解释,不是因为懒(星月很勤快的~~~,小白:噗!!!群众的眼睛是雪亮的!!!!)...咳,这个星月也没有研究过,所以就不解释误导大家。
如果大家有这个方法的解释,希望能告诉星月,让星月也学习下,在此不尽感激!!!
作者使用 cocos2d-x 3.0 示例代码分析,未经作者允许,请勿转载!在此谢谢各位手下留情~~~
本文没有获得作者本人同意,不得转载,否则必追究相关责任。转载请注明出处!!~~