cocos2d-x从c++到js22:使用非侵入方式扩展UI系统接口的举例

Posted 老G

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cocos2d-x从c++到js22:使用非侵入方式扩展UI系统接口的举例相关的知识,希望对你有一定的参考价值。

如何较好的运用脚本语言,使用他的动态性是关键。使用动态性来扩展代码,可以保证非侵入方式。这种方式,把原先的引擎代码和当前自己的二次开发代码隔离开了,便于后续的升级维护。而且,又不像继承那么重量级。


下面就如何用动态添加的扩展方式,使用非侵入来完善和增强CocoStudio的UI功能,做一举例:


零、入口函数


一开始,我们需要加载ui到游戏中,然后我们访问这个ui,在上面执行一系列操作,把结果对象返回出来。这个代码的主干就是这个样子。


var loadUI = function(filepath,owner){
    ui = ccs.GUIReader.getInstance().widgetFromJsonFile(filepath)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
    //一系列操作
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
    return ui;
}



在每次加载控件的时候,要使用这个额外扩展的函数,而不是那个引擎里的自带函数。这样在ui加载完成之后,里面所有的东西都已经自动处理好了,直接拿来用就行了。




一、改进子控件访问方式


getChildByName 和 getChildById实在是很罗嗦的方式。因为UI控件本身就是个node,也是按照节点树来组织的。所以,我们可以使用类似JSON的方式,首先递归把所有控件名字都绑定。然后逐个处理。伪代码如下:


绑定名字(node,owner){
  子节点数组 = node.getChildren()
  遍历子节点数组:{
     名字key = childNode.getName()
     node[名字key]=childNode
     绑定名字(childNode)
  }
}


这样就可以通过非常自然的"."方式访问控件了,例如:


曾祖父控件.祖父控件.父控件.子控件.xxxxx函数()


二、动态添加接口


动态添加接口,已经说过很多了,继续伪码:


首先,跟上面一样,递归访问所有子节点。


然后用分支代码,判断类型,为了严格包装类型对应,我们使用javascript的构造器来判断:


if(child.constructor == 按钮)
    按钮节点的扩展函数(child)
else if(child.constructor == 文本框)
    文本框节点的扩展函数(child)
//……其他节点类型


然后我在扩展函数里直接,对相应的child进行操作:


按钮节点的扩展函数(child){
    child.log=function(){
        log("调用log函数成功")
    }
}


三、回调函数自动绑定


为了让UI系统支持自动绑定回调函数,我们可以使用一种特殊的方法。还记得CocosBuilder里面的owner么。


我们在owner上预制几个方法,然后根据节点名字和回调函数类型,直接拼出来。以按钮举例:


owner.touchEventListener_按钮名字 = function(sender, type){
    switch(type){
        case ccui.Widget.TOUCH_BAGAN:
            log("按钮名字 TOUCH_BAGAN")
        case ccui.Widget.TOUCH_MOVED:
            log("按钮名字 TOUCH_MOVED")
        case ccui.Widget.TOUCH_ENDED:
            log("按钮名字 TOUCH_ENDED")
        case ccui.Widget.TOUCH_CANCELED:
            log("按钮名字 TOUCH_CANCELED")
    }
}


因为JavaScript的缺陷,不能拿到当前控件的类型名。还好CocoStudio提供了一个getDescription()接口,里面能够返回一个可用的类型名。然后我们使用拼接方式绑定他:


按钮名字 = child.getName()
fnName = "touchEventListener_" + 按钮名字
child["addEventListener"+child.getDescription()](owner[fnName],owner)


另外,owner最好使用代码生成器做出来,这样可以做到全自动化了。


最后


上面这些写法,适用于任何脚本语言,JS能用,lua也没有问题。

以上是关于cocos2d-x从c++到js22:使用非侵入方式扩展UI系统接口的举例的主要内容,如果未能解决你的问题,请参考以下文章

cocos2d-x从c++到js17:使用FireFox进行JS远程调试

cocos2d-x从c++到js21:使用CocosCode调试JSB

cocos2d-x从c++到jsJS与C++的交互2——JS与C++的“函数重载”问题

cocos2d-x从c++到js19:CoffeeScript开发环境搭建续

cocos2d-x从c++到js16:使用cocos2d-console工具转换脚本为字节码

获取非侵入式升压序列化 C++ 的私有数据成员