Sloppy's Blog

Cocos2d-x脚本lua引擎与JS引擎共存

背景

公司里之前的平台项目有的是LUA开发的,有的是JS开发的。结果公司想把这些小项目整合到一个平台里来。打包形成一个总的APP项目。大家知道cocos2d-x 要么是LUA的,要么是JS的。同时存在,而且需要相互切换。是一件多么蛋疼的事情。多么蛋疼的技术选型开发。没办法。事已至此。就需要整合两个渲染引擎到一起。之前听外包团队好象很麻烦,自己这边测试了一下。发现只需要修改少些就可以了。

步骤

创建项目

  • 我们用命令行先创建cocos2d-x-js项目,cocos new -l js -d c:\cocos HelloCocosApp
  • 再创建cocos2d-x lua项目 cocos new -l -d c:\cocos HelloCocosLua

合并代码

  • 把lua项目下的frameworks\cocos2d-x\cocos\scripting\lua-bindings这些文件复制到js项目中的frameworks\cocos2d-x\cocos\scripting目录下,这样scripting目录下就会有两个目录:js-bindings,lua-bindings
  • 把lua项目下的frameworks\cocos2d-x\external\lua文件夹复制到js目录下的frameworks\cocos2d-x\external目录下

添加项目引用

  • 接下来所有的项目在JS项目内完成,打开js项目的win32解决方案,添加项目引用,目录在:frameworks\cocos2d-x\cocos\scripting\lua-bindings\proj.win32\libluacocos2d.vcxproj
  • 在cocos项目属性上添加项目引用,
  • 添加c++附加包含目录,
    • $(EngineRoot)external\lua\tolua
    • $(EngineRoot)external\lua\lua

修改代码

  • 修改libjscocos2d里的ScriptingCore。修改单例,可以销毁。之前的单例是无法销毁的。代码如下:


    ScriptingCore ScriptingCore::getInstance()
    {
    //static ScriptingCore
    instance = nullptr;
    if (_defaultEngine == nullptr)

    _defaultEngine = new (std::nothrow) ScriptingCore();
    

    return _defaultEngine;
    }
    // 析构里增加至nullptr
    ScriptingCore::~ScriptingCore()
    {
    cleanup();
    JS_ShutDown();
    _defaultEngine = nullptr;
    }

  • 新建JSEngine类跟LuaEngine类,把原来初始化JS引擎的代码复制到JSEngine,把初始化Lua引擎的代码复制到LuaEngine里。分别提外部接口调用。这里我们可以做成单例使用。然后新建一个Scene自定义。在类里主要逻辑代码,监听从Lua跟JS发送过来的事件,切换引擎。
    bool CoolExpScene::init() {
      if (!Scene::init()) {
          return false;
      }
      Director::getInstance()->getEventDispatcher()->addCustomEventListener("SWITCH_LUA_ENGINE", [this](EventCustom* event) {
          CCLOG("CPP:SWITCH LUA ENGINE");
          Director::getInstance()->getScheduler()->performFunctionInCocosThread([]() {
              LuaEngine::getInstance()->initEngine();
          });
      });
      Director::getInstance()->getEventDispatcher()->addCustomEventListener("SWITCH_JS_ENGINE", [this](EventCustom* event) {
          CCLOG("CPP:SWITCH JS ENGINE");
          Director::getInstance()->getScheduler()->performFunctionInCocosThread([]() {
              JSEngine::getInstance()->initEngine();
          });
      });
      return true;
    }
    void CoolExpScene::onEnter() {
      Scene::onEnter();
      JSEngine::getInstance()->initEngine();
    }
    

AppDelegate.cpp初始化修改如下:
Director::getInstance()->runWithScene(CoolExpScene::create());

  • 修改脚本代码,关键性代码如下
    js

    var imageView = new ccui.ImageView(“res/strawberry.png”);
    imageView.attr({
    x: size.width / 2,
    y: size.height / 2
    
    });
    this.addChild(imageView);
    imageView.setTouchEnabled(true);
    imageView.addTouchEventListener(function(sender, type){
    if (type == ccui.Widget.TOUCH_ENDED) {
        cc.director.getRunningScene().removeAllChildren();
        cc.director.getEventDispatcher().dispatchCustomEvent("SWITCH_LUA_ENGINE");
    }
    
    });

    lua: cc.Director:getInstance():getEventDispatcher():dispatchCustomEvent(“SWITCH_JS_ENGINE”)

android编译修改

Android.mk文件关键修改如下:

..........代码
LOCAL_STATIC_LIBRARIES := cocos2d_js_static
LOCAL_STATIC_LIBRARIES += cocos2d_lua_static

..........代码

$(call import-module, scripting/js-bindings/proj.android)
$(call import-module,scripting/lua-bindings/proj.android)

IOS编译修改

添加libluacocos2dx项目引用,添加对应的head search path即可