• 【CSON原创】HTML5游戏框架cnGameJS开发实录(核心函数模块篇)


    返回目录

    1.cnGameJs框架的代码组织 

      核心函数模块,主要的作用是为之后的框架开发和用户对游戏的开发提供方便,整个框架在一个闭包之中,避免对全局作用域的污染。之后每个不同的模块分别在自己的闭包内,使不同模块的分割更清晰。因此我们框架的模块划分会是这样:

    (function(win,undefined){//最大的闭包

    var fun1=function(){//各模块公用的方法
    }

    //这里放各个小模块,它们有各自的闭包

    }(window,undefined)

     

      那么我们如何再划分其他小模块呢?为了方便各个小模块有各自的命名空间,并且在各自的闭包中,我们新增一个register方法,该方法可以在不同命名空间下扩展自己的模块,我们需要传入的首先是命名空间的名称,该方法为我们生成该命名空间对象,之后我们执行自己的方法,为命名空间对象执行相应的扩展操作:

            /**
    *生成命名空间,并执行相应操作
    *
    */
    register:function(nameSpace,func){
    var nsArr=nameSpace.split(".");
    var parent=win;
    for(var i=0,len=nsArr.length;i<len;i++){
    (typeof parent[nsArr[i]]=='undefined')&&(parent[nsArr[i]]={});
    parent=parent[nsArr[i]];
    }
    if(func){
    func.call(parent,this);
    }
    return parent;
    }

      如上,首先可以把传入的命名空间字符串分割,然后生成对象,之后执行用户传入的函数进行扩展操作,如下:

    cnGame.register("cnGame.core",function(){this.func=function(){}});

      这样就可以生成core模块,并且为该模块添加func方法,那么我们框架的代码组织看起来将是这样:

    (function(win,undefined){

    var cnGame={
    register:function(nameSpace,handler){

    }
    }

    /*core模块*/
    cnGame.register("core",function(){
    //添加该模块内容
    })

    /*input模块*/
    cnGame.register("input",function(){
    //添加该模块内容
    })

    win["cnGame"]=cnGame;


    })(window,undefined);

      
    2.框架的初始化

      框架初始化的时候,需要保存的对象分别有:canvas对象,context对象,canvas的位置,尺寸等,我们可以先看看初始化的函数:

            /**
    *初始化
    *
    */
    init:function(id,options){
    options=options||{};
    this.canvas = this.core.$(id||"canvas");
    this.context = this.canvas.getContext('2d');
    this.width = options.width||800;
    this.height = options.height||600;
    this.title = this.core.$$('title')[0];
    canvasPos=getCanvasPos(this.canvas);
    this.x=canvasPos[0]||0;
    this.y=canvasPos[1]||0;
    this.canvas.width=this.width;
    this.canvas.height=this.height;
    this.canvas.style.left=this.x +"px";
    this.canvas.style.top=this.y +"px";

    },

      非常简单,就是保存一些初始化值,方便后续使用。另外可以注意到我们调用了getCanvasPos方法来获取canvas的位置参数,该参数循环获取对象的offsetParent,并叠加offsetLeft和offsetTop,从而得到canvas在页面的位置。该函数源码如下:

        /**
    *获取canvas在页面的位置
    *
    */
    var getCanvasPos=function(canvas){
    var left = 0;
    var top = 0;
    while (canvas.offsetParent) {
    left += canvas.offsetLeft;
    top += canvas.offsetTop;
    canvas = canvas.offsetParent;

    }
    return [left, top];

    }

    3.工具函数模块

      之后我们就可以用上面的register方法添加第一个模块:core模块。该模块也很简单,主要功能就是添加工具函数,方便后续的框架开发和用户的游戏开发。这里包含了一些常用的工具函数,例如通过id获取元素,原型继承,对象复制,事件绑定等等。注意如果涉及不同浏览器的兼容问题,我们可以一开始就根据浏览器设置function,而不是每次都判断浏览器类型再进行相应操作,效率会更加高。拿事件绑定进行举例:

      

            /**
    事件绑定
    *
    */
    this.bindHandler=(function(){

    if(window.addEventListener){
    return function(elem,type,handler){
    elem.addEventListener(type,handler,false);

    }
    }
    else if(window.attachEvent){
    return function(elem,type,handler){
    elem.attachEvent("on"+type,handler);
    }
    }
    })();

      预先根据浏览器特性返回不同function,这样后续使用就不用再判断浏览器特性,提高效率。

      附上所有工具函数的源码,由于都很简单,所以对该模块就不在详述了。

    /**
    *
    *基本工具函数模块
    *
    *
    */
    cnGame.register("cnGame.core",function(cg){
    /**
    按id获取元素
    *
    */
    this.$=function(id){
    return document.getElementById(id);
    };
    /**
    按标签名获取元素
    *
    */
    this.$$=function(tagName,parent){
    parent=parent||document;
    return parent.getElementsByTagName(tagName);
    };
    /**
    按类名获取元素
    *
    */
    this.$Class=function(className,parent){
    var arr=[],result=[];
    parent=parent||document;
    arr=this.$$("*");
    for(var i=0,len=arr.length;i<len;i++){
    if((" "+arr[i].className+" ").indexOf(" "+className+" ")>0){
    result.push(arr[i]);
    }
    }
    return result;
    };
    /**
    事件绑定
    *
    */
    this.bindHandler=(function(){

    if(window.addEventListener){
    return function(elem,type,handler){
    elem.addEventListener(type,handler,false);

    }
    }
    else if(window.attachEvent){
    return function(elem,type,handler){
    elem.attachEvent("on"+type,handler);
    }
    }
    })();
    /**
    事件解除
    *
    */
    this.removeHandler=(function(){
    if(window.removeEventListerner){
    return function(elem,type,handler){
    elem.removeEventListerner(type,handler,false);

    }
    }
    else if(window.detachEvent){
    return function(elem,type,handler){
    elem.detachEvent("on"+type,handler);
    }
    }
    })();
    /**
    获取事件对象
    *
    */
    this.getEventObj=function(eve){
    return eve||win.event;
    };
    /**
    获取事件目标对象
    *
    */
    this.getEventTarget=function(eve){
    var eve=this.getEventObj(eve);
    return eve.target||eve.srcElement;
    };
    /**
    禁止默认行为
    *
    */
    this.preventDefault=function(eve){
    if(eve.preventDefault){
    eve.preventDefault();
    }
    else{
    eve.returnValue=false;
    }

    };
    /**
    获取对象计算的样式
    *
    */
    this.getComputerStyle=(function(){
    var body=document.body;
    if(body.currentStyle){
    return function(elem){
    return elem.currentStyle;
    }
    }
    else if(document.defaultView.getComputedStyle){
    return function(elem){
    return document.defaultView.getComputedStyle(elem, null);
    }
    }

    })();
    /**
    是否为undefined
    *
    */
    this.isUndefined=function(elem){
    return typeof elem==='undefined';
    },
    /**
    是否为数组
    *
    */
    this.isArray=function(elem){
    return Object.prototype.toString.call(elem)==="[object Array]";
    };
    /**
    是否为Object类型
    *
    */
    this.isObject=function(elem){
    return elem===Object(elem);
    };
    /**
    是否为字符串类型
    *
    */
    this.isString=function(elem){
    return Object.prototype.toString.call(elem)==="[object String]";
    };
    /**
    是否为数值类型
    *
    */
    this.isNum=function(elem){
    return Object.prototype.toString.call(elem)==="[object Number]";
    };
    /**
    *复制对象属性
    *
    */
    this.extend=function(destination,source,isCover){
    var isUndefined=this.isUndefined;
    (isUndefined(isCover))&&(isCover=true);
    for(var name in source){
    if(isCover||isUndefined(destination[name])){
    destination[name]=source[name];
    }

    }
    return destination;
    };
    /**
    *原型继承对象
    *
    */
    this.inherit=function(child,parent){
    var func=function(){};
    func.prototype=parent.prototype;
    child.prototype=new func();
    child.prototype.constructor=child;
    child.prototype.parent=parent;
    };

    });



  • 相关阅读:
    不测的秘密:精准测试之路----读书笔记(第二章)
    如何使用for循环连续的实例化多个对象!
    java如何在一个有序的数组类插入一个数!
    webstrom 常用快捷键
    如何使Label带有链接??此法感觉有点取巧!!!
    System.DateTime的一些格式
    如何解决”无法将类型为“System.DateTime”的对象强制转换为类型“System.String”。“
    如何解决“连接未关闭。 连接的当前状态为打开”问题
    c语言中 %p的含义
    什么情况下用递归?
  • 原文地址:https://www.cnblogs.com/Cson/p/2348280.html
Copyright © 2020-2023  润新知