前端之家收集整理的这篇文章主要介绍了
Cocos2d-lua的运行理解,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
- 关键词:
- cocos2d-lua项目启动流程
- lua调用cocos2d引擎API
-
-
-
这里是个小测试
-
-
-
-
-
-
-
-
环境
- 引擎版本:Cocos2d-x 3.10
- 开发工具:Xcode8.1
简述
-
-
-
- 所谓的Cocos2d-lua,其实只是Cocos2d引擎添加了Lua绑定的版本。
从创建命令可以看出来 ,这里的引擎其实是同一套,只是创建工程时提供了不同语言的桥接层
- 使用C++语言和Cocos2d-x引擎进行开发时,我们写的代码是直接调用引擎的API的,因为引擎也是用C++语言编写,不需要进行语言转换
- 使用Lua语言和Cocos2d-x引擎进行开发时,我们写的代码通过LuaEngine执行,而LuaEngine封装了Cocos2d-x引擎的API,所以就相当于使用Lua脚本在调用Cocos2d-x的API了
-
-
-
-
-
C++项目和Lua项目的开始过程
- 简单来比较一下C++项目和Lua项目开始的过程(后面会专门写一下启动流程),这里我们都从AppDelegate.cpp的
-
- 函数开始。
C++项目
- 先贴一下代码咯
- 这段代码是Cocos2d-x 3.10版本新建的C++语言工程中AppDelegate.cpp文件中拷出来的,加了一些注释。
- 从这里我们可以看出进入游戏逻辑的流程:
-
-
-
- 初始化Director
- 新建GLView,然后进行一些设置
- 新建Scene
- 使用Director运行这个场景
- 游戏逻辑就可以从这个Scene中的init函数开始,添加UI层,添加事件监听器,添加游戏层等等...如果我们有一些统计、资源管理器等,也可以在AppDelegate的函数中来进行。
Lua项目
- 也来看AppDelegate.cpp中的函数
- 从上面代码可以看到,Cocos2d-x新建的Lua语言项目中,这里没有进行GLView的设置,没有使用C++代码来创建Scene,所以这些操作肯定和"src/main.lua"脚本有关。这里我们一步一步来看src目录下这些脚本执行的步骤(注意看注释的序号):
-
-
-
- 在main.lua中部分注释:
- 2.去app/MyApp.lua看看require做了什么:
- 3.继续去packages/AppBase.lua里看看生成MyApp的时候做了什么:
- 4.我们可以看回第1步(注释编号3)中,生成MyApp对象后,执行了run方法,那就看看AppBase.lua中的run方法做了什么:
- 5.这里(注释编号10)看到会调用到AppBase.lua中的createView方法:
- 6.上面的函数中执行到了app/views/MainScene.lua脚本,那就去看看做了什么:
- 7.上面第一行代码(注释编号16)可以看到,MainScene类继承自ViewBase,那进入mvc/ViewBase.lua看看
- 8.这里可以回看到第4步(注释编号10),方法createView执行完成后,生成了一个MainScene对象(继承自ViewBase(继承自ccNode)),然后下一步就是调用MainScene对象的showWithScene函数,在packages/mvc/ViewBase.lua中:
- 到这里,对于Cocos2d-x引擎生成的C++和Lua语言项目,我们都分析到了生成第一个Scene的步骤,后面就可以开始写UI、写结构、写逻辑等内容了。
-
-
-
-
-
简单对比Cocos2d-x创建的C++工程和Lua工程
- 这里使用Cocos2d-x 3.10分别创建了Lua语言工程和C++语言工程,在Xcode下打开两个项目,可以对比一下项目结构:
-
-
-
- 从最外层结构可以看出Lua工程比C++工程多了两个lib:
-
-
-
- libsimulator模拟器支持
- cocos2d_lua_bindings引擎与Lua脚本的桥接层
- libsimulator就先不看了,和这次主题无关,就先放一边,以后有空再来看(其实我还真没仔细看过这个东东)。
-
- 打开AppDelegate.cpp文件,看到引入的头文件:
- AppDelegate自己的头文件除外,第一个头文件就是CCLuaEngine.h,打开cocos2d_lua_bindings库的manual目录,我们就能看到这个类。打开CCLuaEngine.h文件,可以看到它包含了CCLuaStack.h和CCLuaValue.h,这两个文件都是C++与Lua直接交互需要用到的。继续往下看,可以看到cocos2d/LuaScriptHandlerMgr.h,打开manual下的cocos2d文件夹可以看到如下文件列表:
-
-
-
- 从其中LuaOpengl.cpp中包含的代码:
-
-
-
- 可以看到这里在注册一个module,并绑定函数。另外一些lia_开头的文件中包含的也是这些代码。
理解一下
- 想想脚本执行时的情景,当执行到一个名为的函数时,用户自己很可能并没有定义这样一个函数,那Lua引擎如何识别“drawCircle”这样一个命令,而不会把它当作错误的代码呢?
- 看到上面的文件我们就能知道,字符串“drawCircle”早就被注册到LuaEngine中,所以当执行脚本时遇到时,才知道需要去调用哪一个函数。
- 这也就是说,cocos2d_lua_bindings库提供了Lua对Cocos2d引擎的绑定,相当于通过注册Module的方式对Cocos2d引擎提供的(相关的)API进行了一次封装(当然,如果是直接封装API,可能达不到提高开发效率的目的,所以有了quick的出现,也就是把常用的功能(例如创建一个Scene)封装成一个函数newScene)。
总结
- 相对于Cocos2d-x C++工程来说,Cocos2d-x生成的Lua语言工程提供了对Cocos2d引擎的Lua语言封装。将Cocos2d引擎API绑定到对应的Lua语言函数,在调用到这些函数时,会执行对应的Cocos2d引擎API。
- 以这个思想来看,所以能够直接或间接与C++语言进行交互的编程语言都可以用来封装Cocos2d引擎啊。。
查看原文:http://www.51xyyx.com/3263.htmlcocos new TestProj -d Desktop/ -l luaAppDelegate::applicationDidFinishLaunching()bool AppDelegate::applicationDidFinishLaunching() { -
- auto director = Director::getInstance();
- auto glview = director->getOpenGLView();
-
-
- if(!glview) {
- #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
-
- glview = GLViewImpl::createWithRect("TestCpp",Rect(0,0,designResolutionSize.width,designResolutionSize.height));
- #else
-
- glview = GLViewImpl::create("TestCpp");
- #endif
- director->setOpenGLView(glview);
- }
-
-
- director->setDisplayStats(true);
-
-
- director->setAnimationInterval(1.0 / 60);
-
-
- glview->setDesignResolutionSize(designResolutionSize.width,designResolutionSize.height,ResolutionPolicy::NO_BORDER);
-
- Size frameSize = glview->getFrameSize();
-
-
-
- if (frameSize.height > mediumResolutionSize.height)
- {
- director->setContentScaleFactor(MIN(largeResolutionSize.height/designResolutionSize.height,largeResolutionSize.width/designResolutionSize.width));
- }
-
- else if (frameSize.height > smallResolutionSize.height)
- {
- director->setContentScaleFactor(MIN(mediumResolutionSize.height/designResolutionSize.height,mediumResolutionSize.width/designResolutionSize.width));
- }
-
- else
- {
- director->setContentScaleFactor(MIN(smallResolutionSize.height/designResolutionSize.height,smallResolutionSize.width/designResolutionSize.width));
- }
-
- register_all_packages();
-
-
- auto scene = HelloWorld::createScene();
-
-
- director->runWithScene(scene);
-
- return true;
- }applicationDidFinishLaunchingapplicationDidFinishLaunchingbool AppDelegate::applicationDidFinishLaunching()
- {
-
- Director::getInstance()->setAnimationInterval(1.0 / 60.0f);
-
-
-
- auto engine = LuaEngine::getInstance();
- ScriptEngineManager::getInstance()->setScriptEngine(engine);
- lua_State* L = engine->getLuaStack()->getLuaState();
- lua_module_register(L);
-
- register_all_packages();
-
-
- LuaStack* stack = engine->getLuaStack();
- stack->setXXTEAKeyAndSign("2dxLua",strlen("2dxLua"),"XXTEA",strlen("XXTEA"));
-
-
-
-
-
-
-
- auto runtimeEngine = RuntimeEngine::getInstance();
- runtimeEngine->addRuntime(RuntimeLuaImpl::create(),kRuntimeEngineLua);
- runtimeEngine->start();
-
- if (engine->executeScriptFile("src/main.lua"))
- {
- return false;
- }
-
- return true;
- }cc.FileUtils:getInstance():setPopupNotify(false)
- cc.FileUtils:getInstance():addSearchPath("src/")
- cc.FileUtils:getInstance():addSearchPath("res/")
-
- require "config"
- require "cocos.init"
-
- local function main()
- require("app.MyApp"):create():run()
- end
- local status,msg = xpcall(main,__G__TRACKBACK__)
- if not status then
- print(msg)
- endlocal MyApp = class("MyApp",cc.load("mvc").AppBase)
- function MyApp:onCreate()
- math.randomseed(os.time())
- end
- return MyApplocal AppBase = class("AppBase")
-
- -- 5.构造函数
- function AppBase:ctor(configs)
- self.configs_ = {
- viewsRoot = "app.views",modelsRoot = "app.models",defaultSceneName = "MainScene",}
-
- for k,v in pairs(configs or {}) do
- self.configs_[k] = v
- end
-
- if type(self.configs_.viewsRoot) ~= "table" then
- self.configs_.viewsRoot = {self.configs_.viewsRoot}
- end
- if type(self.configs_.modelsRoot) ~= "table" then
- self.configs_.modelsRoot = {self.configs_.modelsRoot}
- end
-
- if DEBUG > 1 then
- dump(self.configs_,"AppBase configs")
- end
-
- if CC_SHOW_FPS then
- cc.Director:getInstance():setDisplayStats(true)
- end
-
- -- event
- self:onCreate() -- 6.啥也没做的create函数
- end
- function AppBase:run(initSceneName)
- initSceneName = initSceneName or self.configs_.defaultSceneName
- self:enterScene(initSceneName)
- end
- function AppBase:enterScene(sceneName,transition,time,more)
- local view = self:createView(sceneName)
- view:showWithScene(transition,more)
- return view
- end
- function AppBase:createView(name)
- for _,root in ipairs(self.configs_.viewsRoot) do
- local packageName = string.format("%s.%s",root,name)
- local status,view = xpcall(function()
- return require(packageName)
- end,function(msg)
- if not string.find(msg,string.format("'%s' not found:",packageName)) then
- print("load view error: ",msg)
- end
- end)
- local t = type(view)
- if status and (t == "table" or t == "userdata") then
- return view:create(self,name)
- end
- end
- error(string.format("AppBase:createView() - not found view \"%s\" in search paths \"%s\"",name,table.concat(self.configs_.viewsRoot,",")),0)
- endlocal MainScene = class("MainScene",cc.load("mvc").ViewBase) -- 16.MainScene类继承自ViewBase,去mvc/ViewBase.lua看看
-
- -- 19.创建一个Sprite,一个Label,添加到这个Node中
- function MainScene:onCreate()
- -- add background image
- display.newSprite("HelloWorld.png")
- :move(display.center)
- :addTo(self)
-
- -- add HelloWorld label
- cc.Label:createWithSystemFont("Hello World","Arial",40)
- :move(display.cx,display.cy + 200)
- :addTo(self)
-
- end
-
- return MainScenelocal ViewBase = class("ViewBase",cc.Node) -- 17.继承自Node噢
-
- -- 18.构造函数,还是进行一些初始化工作
- function ViewBase:ctor(app,name)
- self:enableNodeEvents()
- self.app_ = app
- self.name_ = name
-
- -- check CSB resource file
- local res = rawget(self.class,"RESOURCE_FILENAME")
- if res then
- self:createResoueceNode(res)
- end
-
- local binding = rawget(self.class,"RESOURCE_BINDING")
- if res and binding then
- self:createResoueceBinding(binding)
- end
-
- if self.onCreate then self:onCreate() end
- end-- 21.这里创建了一个Scene,并且把当前这个Node添加到Scene中。其实这就是C++项目HelloWorldScene类的createScene方法了
- function ViewBase:showWithScene(transition,time,more)
- self:setVisible(true)
- local scene = display.newScene(self.name_) -- 22.display包含很多功能,有点类似于Director了
- scene:addChild(self)
- display.runScene(scene,more) -- 23.runScene熟悉的方法
- return self
- end#include "AppDelegate.h"
- #include "CCLuaEngine.h"
- #include "SimpleAudioEngine.h"
- #include "cocos2d.h"
- #include "lua_module_register.h"
-
- #if (CC_TARGET_PLATFORM != CC_PLATFORM_LINUX)
- #include "ide-support/CodeIDESupport.h"
- #endif
-
- #if (COCOS2D_DEBUG > 0) && (CC_CODE_IDE_DEBUG_SUPPORT > 0)
- #include "runtime/Runtime.h"
- #include "ide-support/RuntimeLuaImpl.h"
- #endifdrawCircledrawCircle