zoukankan      html  css  js  c++  java
  • (原创)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.htmlhttp://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
    	available tests: ";
                    send(fd, msg, sizeof(msg),0);
                    send(fd, "
    ",1,0);
                    for(int i = 0; i < g_testCount; i++)
                    {
                        send(fd, "	",1,0);
                        send(fd, g_aTestNames[i].test_name, strlen(g_aTestNames[i].test_name)+1,0);
                        send(fd, "
    ",1,0);
                    }
                    const char help_main[] = "	main, return to main menu
    ";
                    send(fd, help_main, sizeof(help_main),0);
    
                    const char help_next[] = "	next, run next test
    ";
                    send(fd, help_next, sizeof(help_next),0);
                    
                    const char help_back[] = "	back, run prev test
    ";
                    send(fd, help_back, sizeof(help_back),0);
                    
                    const char help_restart[] = "	restart, restart current test
    ";
                    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.
    ";
                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, "
    ",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, "
    ",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, "
    ",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, "
    ",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, "
    ",1,0);
            }
            
        };
        console->addCommand(autotest);
    }
    #endif

    好吧,这篇文章勉强完成。星月在这里给大家道歉,写这篇文章时没有考虑到会涉及这么多知识点,希望大家指出错误的敌方,星月会不断改变~~~

    // 函数实现了控制台,用于文本输入输出
    void TestController::addConsoleAutoTest()

    这个函数星月没有解释,不是因为懒(星月很勤快的~~~,小白:噗!!!群众的眼睛是雪亮的!!!!)...咳,这个星月也没有研究过,所以就不解释误导大家。

    如果大家有这个方法的解释,希望能告诉星月,让星月也学习下,在此不尽感激!!!

    作者使用 cocos2d-x 3.0 示例代码分析,未经作者允许,请勿转载!在此谢谢各位手下留情~~~

    本文没有获得作者本人同意,不得转载,否则必追究相关责任。转载请注明出处!!~~

    原文地址:http://www.cnblogs.com/wodehao0808/p/4045327.html

  • 相关阅读:
    .NET 多线程 Task async await
    .NET5 MVC 文件目录
    Html 问题记录
    vue学习笔记(记录知识点)
    vue调试工具vue-devtools安装及使用
    node.js入坑记录
    vue从0开始笔记
    前端样式css问题记录
    谷歌浏览器chrome console 发送POST/GET请求
    jQuery的请求数据方式
  • 原文地址:https://www.cnblogs.com/wodehao0808/p/4045327.html
Copyright © 2011-2022 走看看