cocos2d-x-html5之游戏启动

接触cocos2dx有5年多来,以后可能要切换到creator了。所以打算重新学习一下cocos2dx源码,并记录一下。

今天我们来讲一下web版本是怎么启动,首先看下模版工程的文件结构,其中index.html为入口。
在这里插入图片描述
接下来我们看下index.html里面的源码

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Cocos2d-html5 Hello World test</title>
    <link rel="icon" type="image/GIF" href="res/favicon.ico" />
    <meta name="viewport" content="width=321,user-scalable=no" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="full-screen" content="yes" />
    <meta name="screen-orientation" content="portrait" />
    <meta name="x5-fullscreen" content="true" />
    <meta name="360-fullscreen" content="true" />
    <style>
        body,
        canvas,
        div {
            -moz-user-select: none;
            -webkit-user-select: none;
            -ms-user-select: none;
            -khtml-user-select: none;
            -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
        }
    </style>
    <!--加载脚本-->
    <script src="../CCBoot.js"></script>
    <!--程序入口-->
    <script src="main.js"></script>
</head>

<body style="padding:0; margin: 0; background: #000;">
    <script src="res/loading.js"></script>
    <canvas id="gameCanvas" width="321" height="480"></canvas>
</body>

</html>

可以看到这边是加载了CCBoot.js和main.js文件,其中CCBoot.js是引擎提供的,里面包含了游戏启动的流程,main.js是每个项目组自己写的。

接下来我们看下main.js的源码:

// 重写 onStart 函数,执行cc.game.run后,最终执行这里
cc.game.onStart = function () {
    // 如果index.html引用了loading.js,这里需要移除
    if (!cc.sys.isNative && document.getElementById("cocosLoading")) //If referenced loading.js, please remove it
        document.body.removeChild(document.getElementById("cocosLoading"));

    // 声明并定义设计分辨率(竖屏)
    var designSize = cc.size(480, 800);
    // 屏幕分辨率
    var screenSize = cc.view.getFrameSize();
    // 如果不是原生,且高度小于800
    if (!cc.sys.isNative && screenSize.height < 800) {
        // 修改设计分辨率
        designSize = cc.size(320, 480);
        cc.loader.resPath = "res/Normal";
    } else {
        cc.loader.resPath = "res/HD";
    }
    // 等比拉伸,会留黑边
    cc.view.setDesignResolutionSize(designSize.width, designSize.height, cc.ResolutionPolicy.SHOW_ALL);

    //load resources
    // 运行loaderScene场景,加载资源成功后,运行回调函数
    cc.LoaderScene.preload(g_resources, function () {
        // 运行自己的场景,在src/myApp.js
        cc.director.runScene(new MyScene());
    }, this);
};
// 启动游戏,该方法在 CCBoot.js里面实现
cc.game.run();

流程可以看注释,从代码中我们看到加载资源的时候,是运行了cc.LoaderScne.preload来创建一个过渡场景,等资源加载成功后,运行自己的场景 MyScene。

接下来我们看下 CCLoaderScene.js的源码

/**
 * <p>cc.LoaderScene is a scene that you can load it when you loading files</p>
 * <p>cc.LoaderScene can present thedownload progress </p>
 * @class
 * @extends cc.Scene
 * @example
 * var lc = new cc.LoaderScene();
 */
// 用于下载文件时显示的场景
cc.LoaderScene = cc.Scene.extend({
    _interval: null,
    _label: null,
    _logo: null,
    _className: "LoaderScene",
    cb: null,
    target: null,
    /**
     * Contructor of cc.LoaderScene
     * @returns {boolean}
     */
    init: function () {
        // this赋值给self,后面不用 .bind(this)来访问成员方法
        var self = this;

        //logo
        var logoWidth = 160;
        var logoHeight = 200;

        // bg  创建颜色层
        var bgLayer = self._bgLayer = new cc.LayerColor(cc.color(32, 32, 32, 255));
        // 添加到场景
        self.addChild(bgLayer, 0);

        //image move to CCSceneFile.js
        var fontSize = 24,
            lblHeight = -logoHeight / 2 + 100; // 默认正中间
        cc._loaderImage = null;
        if (cc._loaderImage) {
            //loading logo 
            // 加载logo
            cc.loader.loadImg(cc._loaderImage, {
                // 不跨域
                isCrossOrigin: false
            }, function (err, img) {
                logoWidth = img.width;
                logoHeight = img.height;
                // 显示logo
                self._initStage(img, cc.visibleRect.center);
            });
            fontSize = 14;
            // 有logo的时候,logo往下 10像素
            lblHeight = -logoHeight / 2 - 10;
        }
        //loading percent
        var label = self._label = new cc.LabelTTF("Loading... 0%", "Arial", fontSize);
        // 设置坐标
        label.setPosition(cc.pAdd(cc.visibleRect.center, cc.p(0, lblHeight)));
        label.setColor(cc.color(180, 180, 180));
        bgLayer.addChild(this._label, 10);
        return true;
    },

    _initStage: function (img, centerPos) {
        var self = this;
        // 创建纹理
        var texture2d = self._texture2d = new cc.Texture2D();
        texture2d.initWithElement(img);
        texture2d.handleLoadedTexture();
        var logo = self._logo = new cc.Sprite(texture2d);
        // 设置缩放
        logo.setScale(cc.contentScaleFactor());
        logo.x = centerPos.x;
        logo.y = centerPos.y;
        self._bgLayer.addChild(logo, 10);
    },
    /**
     * custom onEnter
     */
    onEnter: function () {
        var self = this;
        cc.Node.prototype.onEnter.call(self);
        // 0.3秒后执行 _startLoading  这边是循环定时器
        self.schedule(self._startLoading, 0.3);
    },
    /**
     * custom onExit
     */
    onExit: function () {
        cc.Node.prototype.onExit.call(this);
        var tmpStr = "Loading... 0%";
        this._label.setString(tmpStr);
    },

    /**
     * init with resources
     * @param {Array} resources
     * @param {Function|String} cb
     * @param {Object} target
     */
    initWithResources: function (resources, cb, target) {
        if (cc.isString(resources))
            resources = [resources];
        this.resources = resources || [];
        this.cb = cb;
        this.target = target;
    },

    _startLoading: function () {
        var self = this;
        // 取消定时器
        self.unschedule(self._startLoading);
        var res = self.resources;
        // 加载资源
        cc.loader.load(res,
            // 每个加载后的回调
            function (result, count, loadedCount) {
                var percent = (loadedCount / count * 100) | 0;
                percent = Math.min(percent, 100);
                self._label.setString("Loading... " + percent + "%");
            },
            function () {
                if (self.cb)
                    self.cb.call(self.target);
            });
    },

    _updateTransform: function () {
        this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
        this._bgLayer._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
        this._label._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
        this._logo && this._logo._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
    }
});
/**
 * <p>cc.LoaderScene.preload can present a loaderScene with download progress.</p>
 * <p>when all the resource are downloaded it will invoke call function</p>
 * @param resources 需要加载的资源
 * @param cb 资源全部加载后的回调
 * @param target cb函数的指向
 * @returns {cc.LoaderScene|*}
 * @example
 * //Example
 * cc.LoaderScene.preload(g_resources, function () {
        cc.director.runScene(new HelloWorldScene());
    }, this);
 */
cc.LoaderScene.preload = function (resources, cb, target) {
    var _cc = cc;
    if (!_cc.loaderScene) {
        // 实例化LoaderScene
        _cc.loaderScene = new cc.LoaderScene();
        // 初始化,显示logo等信息
        _cc.loaderScene.init();
        // 注册监听工程文件修改
        cc.eventManager.addCustomListener(cc.Director.EVENT_PROJECTION_CHANGED, function () {
            _cc.loaderScene._updateTransform();
        });
    }

    // 保存要加载的资源,资源全部加载完成后的回调
    _cc.loaderScene.initWithResources(resources, cb, target);
    // 运行当前场景
    cc.director.runScene(_cc.loaderScene);
    return _cc.loaderScene;
};

看下src/myApp.js的源码

// 自己的层
var MyLayer = cc.Layer.extend({
    // 文本控件声明
    helloLabel: null,
    // 精灵控件声明
    sprite: null,

    init: function () {

        //
        // 1. super init first
        this._super();

        /
        // 2. add a menu item with "X" image, which is clicked to quit the program
        //    you may modify it.
        // ask director the window size
        // 获取窗口大大
        var size = cc.director.getWinSize();

        // add a "close" icon to exit the progress. it's an autorelease object
        // 创建菜单选项
        var closeItem = new cc.MenuItemImage(
            s_CloseNormal,
            s_CloseSelected,
            function () {
                cc.log("close");
            }, this);
        // 设置锚点
        closeItem.setAnchorPoint(0.5, 0.5);
        // 创建菜单
        var menu = new cc.Menu(closeItem);
        menu.setPosition(0, 0);
        // 添加到层
        this.addChild(menu, 1);
        closeItem.setPosition(size.width - 20, 20);

        /
        // 3. add your codes below...
        // add a label shows "Hello World"
        // create and initialize a label
        // 创建文本控件
        this.helloLabel = new cc.LabelTTF("Hello World", "Impact", 38);
        // position the label on the center of the screen
        this.helloLabel.setPosition(size.width / 2, size.height - 40);
        // add the label as a child to this layer
        this.addChild(this.helloLabel, 5);

        // add "Helloworld" splash screen"
        // 创建精灵
        this.sprite = new cc.Sprite(s_HelloWorld);
        this.sprite.setAnchorPoint(0.5, 0.5);
        this.sprite.setPosition(size.width / 2, size.height / 2);
        this.sprite.setScale(size.height / this.sprite.getContentSize().height);
        this.addChild(this.sprite, 0);
    }
});

// 自己的场景
var MyScene = cc.Scene.extend({
    // 运行场景后,下一帧执行该函数
    onEnter: function () {
        this._super();
        // 创建一个层
        var layer = new MyLayer();
        // 添加到场景上
        this.addChild(layer);
        // 运行层的init方法
        layer.init();
    }
});

做个总结:
1、入口为index.html,里面加载了CCBoot.js和main.js
2、main.js重写了CCBoot.js里面的cc.game.onStart方法,并执行cc.game.run(),然后执行onStart方法(原因见后面教程
3、onStart方法运行了LoaderScene场景并加载游戏资源
4、加载成功后,运行自己的场景myScene

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值