cocos2d-js解析官方js-test实例入口

来源:互联网 发布:linux内核分析 孟宁 编辑:程序博客网 时间:2024/04/29 14:04

继续上一篇,搭建好cocos2d-js环境后,主要是html5环境,接下来步入入门阶段,许多人都说官网demo是最好的入门资料,今天就剖析官风提供的js-test入口,界面如下:
看图片

这上面有个关闭按钮和一个列表,列表列出了demo中所有的功能演示,这个js-tests工程在cocos2d-js的SDK中,以前是在samples目录下,现在最新版的放在tests目录中,目录结构如下:
目录结构

我们切换到目录js-tests下,在终端运行:cocos run -p web就能打开浏览器查看效果,如果你部署了服务器的话,可以把tests和web目录直接拷贝到服务器目录下,访问对应的目录也能查看效果,注意,要拷贝tests和web目录,因为js-tests中用到了web目录及cpp-tests目录下的资源,如果不确定,把cocos2d-x-3.x.x目录全拷贝吧,也可以做个虚拟目录指向这个目录。
查看效果后,接下来分析主要的几个文件,在此列出你要分析的几个文件,即是需要我们手动修改维护的文件:index.html(首页,入口页),main.js(cocos2d-js的启动与入口),project.json(项目的配置文件),res(资源目录),src(源文件存放目录,一般是js文件,一般有app.js,resource.js)。
1.index.html文件,这里给出源码:

<!DOCTYPE HTML><html><head>    <meta charset="utf-8">    <title>Cocos2d-HTML5 Test Cases</title>    <link rel="icon"          type="image/GIF"          href="../cpp-tests/Resources/Images/favicon.ico"/></head><body style="text-align: center;background: #f2f6f8;"><img style="clear:both;margin-bottom: 20px" src="../cpp-tests/Resources/Images/cocos2dbanner.png"/><div></div><div style="display:inline-block;width:auto; margin: 0 auto; background: black; position:relative; border:5px solid black; border-radius: 10px; box-shadow: 0 5px 50px #333">    <!--<canvas id="gameCanvas" width="1200" height="675"></canvas>-->    <!--<canvas id="gameCanvas" width="480" height="270"></canvas>-->    <canvas id="gameCanvas" width="800" height="450"></canvas> *(1)*</div><script src="../../web/CCBoot.js"></script>*(2)*<script src="main.js"></script>*(3)*</body></html>

在这里注意三个地方,第一个标签canvas,id为gameCanvas,id会在project.json中配置用到。
第二个../../web/CCBoot.js,注意他的路径,此文件不需要我们维护。
第三个main.js,游戏的真正入口函数来了。

2.介绍下project.json项目配置文件,文件太大,截图说明下:
看键头

从向往下:第一个是否显示左下角FPS的信息,自己测试。第二个就是index.html中canvas的id 。第三个引擎的目录,注意他的路径,第四个使用到的模块,注意在引擎目录下查找,最后个键头js文件的列表,如果你有自己的js文件,请记得添加。

3.你们在看helloword项目是,看到有resource.js文件,里面定义了用到的资源,但是这里没有这个文件,他把资源定义到了其他文件中,这里定义到src/tests_resources.js中,看下他的截图:
看键头

如图,第一个键头指明了js文件存放的路径,注意if判断条件,他是web浏览器才执行的,不是的话情况另当别论,不过本人分析的就是html5的,所以他就进来了,第二个键头指示资源的定义,他使用了相对路径,注意他的res路径指向了tests/cpp-tests/Resources,这个在main.js中指定,到时在说明。这就是资源的定义,代替了我们常见的resource.js文件。

4.进入到main.js,真正的入口,看下他的源码:

if(cc.sys){    var scene3SearchPaths = cc.sys.localStorage.getItem("Scene3SearchPaths");    //html5项目判断不成立,直接跳过,想了解请查看api    if (scene3SearchPaths)        jsb.fileUtils.setSearchPaths(JSON.parse(scene3SearchPaths));}cc.game.onStart = function(){    //是否支持retina屏    cc.view.enableRetina(false);    //判断是不是本地化的还是web的,这里判断为否,直接查看else    if (cc.sys.isNative) {        var resolutionPolicy = (cc.sys.os == cc.sys.OS_WP8 || cc.sys.os == cc.sys.OS_WINRT) ? cc.ResolutionPolicy.SHOW_ALL : cc.ResolutionPolicy.FIXED_HEIGHT;        cc.view.setDesignResolutionSize(800, 450, resolutionPolicy);        cc.view.resizeWithBrowserSize(true);        var searchPaths = jsb.fileUtils.getSearchPaths();        searchPaths.push('script');        searchPaths.push('src');        var paths = [            'res/resjs',            'res',            'res/scenetest',            'res/scenetest/ArmatureComponentTest',            'res/scenetest/AttributeComponentTest',            'res/scenetest/BackgroundComponentTest',            'res/scenetest/EffectComponentTest',            'res/scenetest/LoadSceneEdtiorFileTest',            'res/scenetest/ParticleComponentTest',            'res/scenetest/SpriteComponentTest',            'res/scenetest/TmxMapComponentTest',            'res/scenetest/UIComponentTest',            'res/scenetest/TriggerTest'        ];        for (var i = 0; i < paths.length; i++) {            searchPaths.push(paths[i]);        }        jsb.fileUtils.setSearchPaths(searchPaths);    }    else    {        //注意这里,他设置了res的路径,即资源目录,在资源文件中定义时访问的是这个目录下文件        cc.loader.resPath = '../cpp-tests/Resources'    }    //预加载资源,g_resources在test_resource.js中定义,加载完成后会调用第二个参数,一个匿名函数    cc.LoaderScene.preload(g_resources, function () {        //判断条件不成立,进入else        if(window.sideIndexBar && typeof sideIndexBar.start === 'function'){            sideIndexBar.start();        }else{            //这里设置场景,添加layer,运行场景,查看TestController类做了什么,他在test-main.js中定义            var scene = new cc.Scene();            scene.addChild(new TestController());            cc.director.runScene(scene);        }    }, this);};//运行游戏cc.game.run();

看代码,运行逻辑注释已经解释了,这是针对浏览器的,其他的情况没有去分析,其他情况也就是设置资源的搜索路径,现在理着他运行的步骤一步一步跟踪他到底做了什么。

5.从main.js中看到他创建了个类TestController添加到主场景中,接下来查看这个类都做了什么,他的路径为:
js-tests/src/tests-main.js。查看可知道他继承了类LayerGradient,这是个支持两种颜色的渐变的层,单颜色请查看LayerColor类。这里定义了一些全局变量和类的属性,在此不一一列举了,请看源文件,要分析这个类做了什么,就看下他的生命周期中相应的回调函数,第一个构造函数(ctor),第二个onEnter(进入函数),看下构造函数的源码,解释放在注释中:

//下面三个属性在类中定义_itemMenu:null,    _beginPos:0,    isMouseDown:false,    //构造函数    ctor:function() {           //两种渐变的颜色,可修改看效果           this._super(cc.color(0,0,0,255), cc.color(0x46,0x82,0xB4,255));        // globals 这两个为全局属性        director = cc.director;        winSize = director.getWinSize();        // add close menu 关闭按钮参数一,二为两种状态的图标,在资源文件中定义,第三个点击时的回调函数        var closeItem = new cc.MenuItemImage(s_pathClose, s_pathClose, this.onCloseCallback, this);        //设置他的坐标,左下角为原点,向右X轴增大,向上Y轴增大,这个在右上角        closeItem.x = winSize.width - 30;        closeItem.y = winSize.height - 30;        //动画是否自动切换图标        var subItem1 = new cc.MenuItemFont("Automated Test: Off");        subItem1.fontSize = 18;        var subItem2 = new cc.MenuItemFont("Automated Test: On");        subItem2.fontSize = 18;        //自动切换按钮属性设置,回调函数,坐标,是否可见,这里设置不可见,我们看不到效果,请设置可见查看效果        var toggleAutoTestItem = new cc.MenuItemToggle(subItem1, subItem2);        toggleAutoTestItem.setCallback(this.onToggleAutoTest, this);        toggleAutoTestItem.x = winSize.width - toggleAutoTestItem.width / 2 - 10;        toggleAutoTestItem.y = 20;        toggleAutoTestItem.setVisible(false);        if( autoTestEnabled )            toggleAutoTestItem.setSelectedIndex(1);        var menu = new cc.Menu(closeItem, toggleAutoTestItem);//pmenu is just a holder for the close button        menu.x = 0;        menu.y = 0;        // add menu items for tests        this._itemMenu = new cc.Menu();//item menu is where all the label goes, and the one gets scrolled        //d在这里添加主界面中,各个demo的入口,其中testNames是个数组,存放了对象,接下来在分析        for (var i = 0, len = testNames.length; i < len; i++) {            var label = new cc.LabelTTF(testNames[i].title, "Arial", 24);            var menuItem = new cc.MenuItemLabel(label, this.onMenuCallback, this);            this._itemMenu.addChild(menuItem, i + 10000);            menuItem.x = winSize.width / 2;            menuItem.y = (winSize.height - (i + 1) * LINE_SPACE);            // enable disable            if ( !cc.sys.isNative) {                if( 'opengl' in cc.sys.capabilities ){                    menuItem.enabled = (testNames[i].platforms & PLATFORM_HTML5) | (testNames[i].platforms & PLATFORM_HTML5_WEBGL);                }else{                    menuItem.setEnabled( testNames[i].platforms & PLATFORM_HTML5 );                }            } else {                if (cc.sys.os == cc.sys.OS_ANDROID) {                    menuItem.setEnabled( testNames[i].platforms & ( PLATFORM_JSB | PLATFROM_ANDROID ) );                } else if (cc.sys.os == cc.sys.OS_IOS) {                    menuItem.setEnabled( testNames[i].platforms & ( PLATFORM_JSB | PLATFROM_IOS) );                } else if (cc.sys.os == cc.sys.OS_OSX) {                    menuItem.setEnabled( testNames[i].platforms & ( PLATFORM_JSB | PLATFORM_MAC) );                } else {                    menuItem.setEnabled( testNames[i].platforms & PLATFORM_JSB );                }            }        }        this._itemMenu.width = winSize.width;        this._itemMenu.height = (testNames.length + 1) * LINE_SPACE;        this._itemMenu.x = curPos.x;        this._itemMenu.y = curPos.y;        this.addChild(this._itemMenu);        this.addChild(menu, 1);        // 'browser' can use touches or mouse. 事件的处理,即滚动处理        // The benefit of using 'touches' in a browser, is that it works both with mouse events or touches events        if ('touches' in cc.sys.capabilities)            cc.eventManager.addListener({                event: cc.EventListener.TOUCH_ALL_AT_ONCE,                onTouchesMoved: function (touches, event) {                    var target = event.getCurrentTarget();                    var delta = touches[0].getDelta();                    target.moveMenu(delta);                    return true;                }            }, this);        else if ('mouse' in cc.sys.capabilities) {            cc.eventManager.addListener({                event: cc.EventListener.MOUSE,                onMouseMove: function (event) {                    if(event.getButton() == cc.EventMouse.BUTTON_LEFT)                        event.getCurrentTarget().moveMenu(event.getDelta());                },                onMouseScroll: function (event) {                    var delta = cc.sys.isNative ? event.getScrollY() * 6 : -event.getScrollY();                    event.getCurrentTarget().moveMenu({y : delta});                    return true;                }            }, this);        }    }

代码注释说最大部分功能,其他的查看源码,构造函数完成后,会调用onEnter函数,下面给出他的源码:

onEnter:function(){       //调用父类方法        this._super();        //设置主界面菜单y坐标        this._itemMenu.y = TestController.YOffset;    },

接下来查看testNames数组的结构:

var testNames = [    {        title:"ActionManager Test",        platforms: PLATFORM_ALL,        linksrc:"src/ActionManagerTest/ActionManagerTest.js",        testScene:function () {            return new ActionManagerTestScene();        }    },    {        title:"Actions Test",        platforms: PLATFORM_ALL,        linksrc:"src/ActionsTest/ActionsTest.js",        testScene:function () {            return new ActionsTestScene();        }    }

到了这一步,主界面已经显示出来了,现在就是最后一步,当点击其中一项是,他又干了什么,即回调函数onMenuCallback,查看源码:

onMenuCallback:function (sender) {        TestController.YOffset = this._itemMenu.y;        var idx = sender.getLocalZOrder() - 10000;        // get the userdata, it's the index of the menu item clicked        // create the test scene and run it        autoTestCurrentTestName = testNames[idx].title;        var testCase = testNames[idx];        var res = testCase.resource || [];        cc.LoaderScene.preload(res, function () {            var scene = testCase.testScene();            console.log(scene);            if (scene) {                scene.runThisTest();            }        }, this);    }

到了这一步,接下来要分析的是scene.runThisTest()函数做了什么,怎么切换场景了,自己选择感兴趣地模块分析吧。GOOD LUCK!!!!!1

0 0
原创粉丝点击