紧接上文,JS在单线程下,性能不会比Java差,注意场景是单线程。Java的优势不仅是高级语言的特性,还具备了丰富的系统内核资源,如多线程、网络等支持,要比JS灵活的多很多,这里暂时不在讨论这些问题。
回到主题,如果我们把一个完整的C++图形引擎注入到SpiderMonkey中,把复杂的预算放到C/C++内核中,而JS只作为业务处理和内存管理,是否可以获得C/C++的运行能力,有获得了良好的逻辑处理呢?
答案是肯定的!我们直入主题,我们使用最新的SpiderMonkeyV1.8.5,一起解析一下cocos2d-js的代码,下一步,我们会将SpiderMonkey集成到iOS工程中,与JSPatch结合,打造一个跨平台的JS引擎:
网上有一些文章,只是用了一些皮毛,若要构建一个完整的JS引擎,要经常去看国外的SpiderMonkey论坛,如果想看中文,直接看Cocos2d-x的代码好了。今天,我们从Cocos2d-JS的入口类《ScriptingCore.cpp》开始
在启动函数中,我们找到如下函数:AppDelegate::applicationDidFinishLaunching
ScriptingCore* sc = ScriptingCore::getInstance(); sc->addRegisterCallback(register_all_cocos2dx); sc->addRegisterCallback(register_cocos2dx_js_core); sc->addRegisterCallback(jsb_register_system); sc->addRegisterCallback(register_all_cocos2dx_extension); sc->addRegisterCallback(register_all_cocos2dx_extension_manual); sc->addRegisterCallback(jsb_register_chipmunk); sc->addRegisterCallback(JSB_register_opengl); sc->addRegisterCallback(MinXmlHttpRequest::_js_register); sc->addRegisterCallback(register_jsb_websocket); sc->addRegisterCallback(register_jsb_socketio); sc->addRegisterCallback(register_all_cocos2dx_builder); sc->addRegisterCallback(register_CCBuilderReader); sc->addRegisterCallback(register_all_cocos2dx_ui); sc->addRegisterCallback(register_all_cocos2dx_ui_manual); sc->addRegisterCallback(register_all_cocos2dx_studio); sc->addRegisterCallback(register_all_cocos2dx_studio_manual); sc->addRegisterCallback(register_all_cocos2dx_spine); sc->addRegisterCallback(register_all_cocos2dx_spine_manual); sc->addRegisterCallback(register_all_cocos2dx_3d); sc->addRegisterCallback(register_all_cocos2dx_3d_manual); sc->addRegisterCallback(register_all_cocos2dx_3d_extension);声明 Node的JS类模板JSClass
jsb_cocos2d_Node_class = (JSClass *)calloc(1, sizeof(JSClass)); jsb_cocos2d_Node_class->name = "Node"; // JS中ClassName jsb_cocos2d_Node_class->addProperty = JS_PropertyStub;// 添加属性回调函数(默认就好) jsb_cocos2d_Node_class->delProperty = JS_DeletePropertyStub;// 删除属性回调函数(默认就好) jsb_cocos2d_Node_class->getProperty = JS_PropertyStub; // 获取属性回调函数(默认就好) jsb_cocos2d_Node_class->setProperty = JS_StrictPropertyStub; //设置属性回调函数(默认就好) jsb_cocos2d_Node_class->enumerate = JS_EnumerateStub; // 遍历属性回调函数(默认就好) jsb_cocos2d_Node_class->resolve = JS_ResolveStub; // 解析属性回调函数(默认就好) jsb_cocos2d_Node_class->convert = JS_ConvertStub;// 转换属性回调函数(默认就好) jsb_cocos2d_Node_class->finalize = js_cocos2d_Node_finalize;// 析构函数的回调函数,最好用自己的 jsb_cocos2d_Node_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2);// 拥有2个临时持有对象的槽位,方便持有回调函数的引用,比如点击事件JS_PSG(属性名称,属性回调函数,不可删除| 可以遍历); // 用于只声明只读的属性JS_PSGS(属性名称,get属性回调函数, set属性回调函数,不可删除| 可以遍历);// 用于声明读写的属性
JS_FN定义JS函数声明JS_FN(函数在JS中得名称,函数的Native回调函数,参数个数,不可以删除|可以遍历);
好了这样就可以在JS中直接调用这个JS类对象了:
var parent = new Node(); var child = new Node(); parent.addChild(child);然后再C++代码中添加断点,看看是否断点成功进入。
a) cocos2d-JS引入了Cocos2d-x图形引擎作为JS的底层运行支持,为JS提供了更高层面的API封装,为H5展示更绚丽的画面提供基础,极大的满足了众多页游开发者多平台化的需求。不仅如此,cocos2d-js还提供了一套html5的canvas的API封装,让开发者直接在浏览器上所见即所得的开发方式,然后用JSB作为运行环境,彻底打破游戏开发的编译-调试的运行模式。
b) cocos2d-JS目前也有一些较为突出的缺陷,虽然H5的性能的得到了极大的提升,相对Native性能,还是明显差很多,究其原因有:(i)JSBinding代码太多,大约15W行左右,代码较大,频繁的转换JS与C++对象,耗时的同时产生了大量的临时对象,GC时候,卡顿感明显,类似于Android,大家可以脑补一下【性能下降】(ii)不是严格意义的JS语言规范,JS与Native的两套内存管理机制,相互制约,导致C++需要维护一个很大的Map的双向对象映射关系,来维护不同的内存管理模式【性能下降】(iii)JS只是工具,失去了JS的灵活性,为了减少binding的复杂度,Cocos2d-JS很多成员变量都是用函数方式去获取,得到的往往是个临时变量,而不能直接操作,需要前端开发者,长时间的理解规范,才能够避免技术上的缺陷
有没有一种办法既可以满足JS的灵活性,也可以满足Native的内存管理呢?答案是肯定的,请持续关注下一阶段的AppEngine的实时动态。
QQ浏览器的独门暗器是什么?如果某些网站是支持cocos2d-JS的,那么直接启动Cocos2d-JS内核作为加载容器,性能爆表啊,有木有?!莫非以后的浏览器将是游戏市场的必争之地?
Cocos2d-JS的介绍,到此告一段落,有想法的同学,可以私聊我。
