Cocos2d-lua的运行理解

前端之家收集整理的这篇文章主要介绍了Cocos2d-lua的运行理解前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
  1. 关键词:
  2. cocos2d-lua项目启动流程
  3. lua调用cocos2d引擎API
  4.  
  5. 这里是个小测试
  6.  
  7.  

  8.  
  9.  
  10. 环境
    1. 引擎版本:Cocos2d-x 3.10
    1. 开发工具:Xcode8.1
  11. 简述

  12.  
      • 所谓的Cocos2d-lua,其实只是Cocos2d引擎添加Lua绑定的版本。
      • 从创建命令可以看出来 ,这里的引擎其实是同一套,只是创建工程时提供了不同语言的桥接层
      • 使用C++语言和Cocos2d-x引擎进行开发时,我们写的代码是直接调用引擎的API的,因为引擎也是用C++语言编写,不需要进行语言转换
      • 使用Lua语言和Cocos2d-x引擎进行开发时,我们写的代码通过LuaEngine执行,而LuaEngine封装了Cocos2d-x引擎的API,所以就相当于使用Lua脚本在调用Cocos2d-xAPI
      •  
      •  

      •  
      • C++项目和Lua项目的开始过程

      • 简单来比较一下C++项目和Lua项目开始的过程(后面会专门写一下启动流程),这里我们都从AppDelegate.cpp
      •  
      • 函数开始。
      • C++项目

      • 先贴一下代码
      • 这段代码Cocos2d-x 3.10版本新建的C++语言工程中AppDelegate.cpp文件中拷出来的,加了一些注释。
      • 从这里我们可以看出进入游戏逻辑的流程:
      •  
          1. 初始化Director
          1. 新建GLView,然后进行一些设置
          1. 新建Scene
          1. 使用Director运行这个场景
          1. 游戏逻辑就可以从这个Scene中的init函数开始,添加UI层,添加事件监听器,添加游戏层等等...如果我们有一些统计、资源管理器等,也可以在AppDelegate函数中来进行。
          2. Lua项目

          3. 也来看AppDelegate.cpp中的函数
          4. 从上面代码可以看到,Cocos2d-x新建的Lua语言项目中,这里没有进行GLView的设置,没有使用C++代码来创建Scene,所以这些操作肯定和"src/main.lua"脚本有关。这里我们一步一步来看src目录下这些脚本执行的步骤(注意看注释的序号):
          5.  
              1. main.lua中部分注释:
              1. 2.app/MyApp.lua看看require做了什么:
              2. 3.继续去packages/AppBase.lua里看看生成MyApp的时候做了什么:
              3. 4.我们可以看回第1步(注释编号3)中,生成MyApp对象后,执行了run方法,那就看看AppBase.lua中的run方法做了什么:
              4. 5.这里(注释编号10)看到会调用AppBase.lua中的createView方法
              5. 6.上面的函数中执行到了app/views/MainScene.lua脚本,那就去看看做了什么:
              6. 7.上面第一行代码(注释编号16)可以看到,MainScene类继承自ViewBase,那进入mvc/ViewBase.lua看看
              7. 8.这里可以回看到第4步(注释编号10),方法createView执行完成后,生成了一个MainScene对象(继承自ViewBase(继承自ccNode)),然后下一步就是调用MainScene对象的showWithScene函数,在packages/mvc/ViewBase.lua中:
              8. 到这里,对于Cocos2d-x引擎生成C++和Lua语言项目,我们都分析到了生成第一个Scene的步骤,后面就可以开始写UI、写结构、写逻辑等内容了。
              9.  
              10.  

              11.  
              12. 简单对比Cocos2d-x创建的C++工程和Lua工程

              13. 这里使用Cocos2d-x 3.10分别创建了Lua语言工程和C++语言工程,在Xcode下打开两个项目,可以对比一下项目结构:
              14.  
              15. compare.png
              16. 从最外层结构可以看出Lua工程比C++工程多了两个lib
              17.  
                  1. libsimulator模拟器支持
                  1. cocos2d_lua_bindings引擎与Lua脚本的桥接层
                  1. libsimulator就先不看了,和这次主题无关,就先放一边,以后有空再来看(其实我还真没仔细看过这个东东)。
                  2.  
                  3. 打开AppDelegate.cpp文件,看到引入的头文件
                  4. AppDelegate自己的头文件除外,第一个头文件就是CCLuaEngine.h,打开cocos2d_lua_bindings库的manual目录,我们就能看到这个类。打开CCLuaEngine.h文件,可以看到它包含了CCLuaStack.hCCLuaValue.h,这两个文件都是C++与Lua直接交互需要用到的。继续往下看,可以看到cocos2d/LuaScriptHandlerMgr.h,打开manual下的cocos2d文件夹可以看到如下文件列表:
                  5.  
                  6. manual:cocos2d.png
                  7. 从其中LuaOpengl.cpp中包含的代码
                  8.  
                  9. LuaOpengl.png
                  10. 可以看到这里在注册一个module,并绑定函数。另外一些lia_开头的文件中包含的也是这些代码
                  11. 理解一下

                  12. 想想脚本执行时的情景,当执行到一个名为的函数时,用户自己很可能并没有定义这样一个函数,那Lua引擎如何识别“drawCircle”这样一个命令,而不会把它当作错误代码呢?
                  13. 看到上面的文件我们就能知道,字符串“drawCircle”早就被注册LuaEngine中,所以当执行脚本时遇到时,才知道需要去调用哪一个函数
                  14. 这也就是说,cocos2d_lua_bindings库提供了LuaCocos2d引擎的绑定,相当于通过注册Module的方式对Cocos2d引擎提供的(相关的)API进行了一次封装(当然,如果是直接封装API,可能达不到提高开发效率的目的,所以有了quick的出现,也就是把常用的功能(例如创建一个Scene)封装成一个函数newScene)。
                  15. 总结

                  16. 相对于Cocos2d-x C++工程来说,Cocos2d-x生成Lua语言工程提供了对Cocos2d引擎的Lua语言封装。将Cocos2d引擎API绑定到对应的Lua语言函数,在调用到这些函数时,会执行对应的Cocos2d引擎API
                  17. 以这个思想来看,所以能够直接或间接与C++语言进行交互的编程语言都可以用来封装Cocos2d引擎啊。。

                    查看原文:http://www.51xyyx.com/3263.htmlcocos new TestProj -d Desktop/ -l luaAppDelegate::applicationDidFinishLaunching()bool AppDelegate::applicationDidFinishLaunching() {
                  18. // initialize director
                  19. auto director = Director::getInstance(); //初始化Director
                  20. auto glview = director->getOpenGLView(); //获得GLView,也就是游戏窗口
                  21.  
                  22. //此时GLView为空
                  23. if(!glview) {
                  24. #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
                  25. //如果当前是以上平台,就创建一个大小为designResolutionSize的窗口
                  26. glview = GLViewImpl::createWithRect("TestCpp",Rect(0,0,designResolutionSize.width,designResolutionSize.height));
                  27. #else
                  28. //其他平台,则使用默认设置(在ios上是全屏窗口,其他平台不太清楚,也有可能是默认设置了一个窗口大小)
                  29. glview = GLViewImpl::create("TestCpp");
                  30. #endif
                  31. director->setOpenGLView(glview); //director获得当前新建的窗口
                  32. }
                  33.  
                  34. // turn on display FPS
                  35. director->setDisplayStats(true); //显示帧率信息
                  36.  
                  37. // set FPS. the default value is 1.0/60 if you don't call this
                  38. director->setAnimationInterval(1.0 / 60); //设置动画帧率,也就是界面刷新帧率咯
                  39.  
                  40. // Set the design resolution
                  41. glview->setDesignResolutionSize(designResolutionSize.width,designResolutionSize.height,ResolutionPolicy::NO_BORDER); //设置设计分辨率,而不是实际分辨率,这里是为了适配,不能把实际分辨率固定
                  42.  
                  43. Size frameSize = glview->getFrameSize(); //获得实际窗口大小
                  44.  
                  45. //根据实际窗口大小,设置内容缩放比例
                  46. // if the frame's height is larger than the height of medium size.
                  47. if (frameSize.height > mediumResolutionSize.height)
                  48. {
                  49. director->setContentScaleFactor(MIN(largeResolutionSize.height/designResolutionSize.height,largeResolutionSize.width/designResolutionSize.width));
                  50. }
                  51. // if the frame's height is larger than the height of small size.
                  52. else if (frameSize.height > smallResolutionSize.height)
                  53. {
                  54. director->setContentScaleFactor(MIN(mediumResolutionSize.height/designResolutionSize.height,mediumResolutionSize.width/designResolutionSize.width));
                  55. }
                  56. // if the frame's height is smaller than the height of medium size.
                  57. else
                  58. {
                  59. director->setContentScaleFactor(MIN(smallResolutionSize.height/designResolutionSize.height,smallResolutionSize.width/designResolutionSize.width));
                  60. }
                  61.  
                  62. register_all_packages(); //使用包管理器。。 不太清楚这里是为什么
                  63.  
                  64. // create a scene. it's an autorelease object
                  65. auto scene = HelloWorld::createScene(); //新建一个场景
                  66.  
                  67. // run
                  68. director->runWithScene(scene); //从这个场景开始运行,开始绘制、子节点管理等
                  69.  
                  70. return true;
                  71. }applicationDidFinishLaunchingapplicationDidFinishLaunchingbool AppDelegate::applicationDidFinishLaunching()
                  72. {
                  73. // set default FPS
                  74. Director::getInstance()->setAnimationInterval(1.0 / 60.0f); //设置动画帧率,也就是游戏帧率了
                  75.  
                  76. //重点:添加Lua相关支持
                  77. // register lua module
                  78. auto engine = LuaEngine::getInstance(); //初始化一个Lua语言引擎
                  79. ScriptEngineManager::getInstance()->setScriptEngine(engine); //将Lua语言引擎设置为当前脚本引擎(用脚本引擎管理器来管理各种脚本引擎)
                  80. lua_State* L = engine->getLuaStack()->getLuaState(); //获取Lua引擎的State,也就是一组属性
                  81. lua_module_register(L); //向Lua引擎注册一些模块,如网络、动画等
                  82.  
                  83. register_all_packages();
                  84.  
                  85. //设置脚本加密相关的key和sign
                  86. LuaStack* stack = engine->getLuaStack();
                  87. stack->setXXTEAKeyAndSign("2dxLua",strlen("2dxLua"),"XXTEA",strlen("XXTEA"));
                  88.  
                  89. //register custom function
                  90. //LuaStack* stack = engine->getLuaStack();
                  91. //register_custom_function(stack->getLuaState());
                  92.  
                  93. #if (COCOS2D_DEBUG > 0) && (CC_CODE_IDE_DEBUG_SUPPORT > 0)
                  94. //如果需要支持CodeIDE,则从引擎本身启动
                  95. // NOTE:Please don't remove this call if you want to debug with Cocos Code IDE
                  96. auto runtimeEngine = RuntimeEngine::getInstance();
                  97. runtimeEngine->addRuntime(RuntimeLuaImpl::create(),kRuntimeEngineLua);
                  98. runtimeEngine->start();
                  99. #else
                  100. //一般情况,这里使用Lua引擎执行第一个Lua脚本
                  101. if (engine->executeScriptFile("src/main.lua"))
                  102. {
                  103. return false; //脚本默认返回nil,如果脚本执行正常,不会进入这一句
                  104. }
                  105. #endif
                  106.  
                  107. return true; //正常执行到这里,后面就开始执行Cocos引擎提供的主循环
                  108. }cc.FileUtils:getInstance():setPopupNotify(false)
                  109. cc.FileUtils:getInstance():addSearchPath("src/")
                  110. cc.FileUtils:getInstance():addSearchPath("res/")
                  111.  
                  112. require "config" -- 1.执行当前目录下的config.lua,定义一些初始化用的全局变量包括窗口设置等
                  113. require "cocos.init" -- 2.执行cocos/init.lua,初始化框架等一大堆东西,包括OpenGL、音效等引擎的初始化与配置
                  114.  
                  115. local function main()
                  116. require("app.MyApp"):create():run() -- 3.执行app/MyApp.lua调用对应classCreate方法创建对象,并执行run方法
                  117. end
                  118. -- 先忽略这个,我也不知道是啥
                  119. local status,msg = xpcall(main,__G__TRACKBACK__)
                  120. if not status then
                  121. print(msg)
                  122. endlocal MyApp = class("MyApp",cc.load("mvc").AppBase) -- 4.MyApp继承自mvc中的AppBase类,自动找到packages/mvc/AppBase.lua
                  123. function MyApp:onCreate()
                  124. math.randomseed(os.time())
                  125. end
                  126. return MyApplocal AppBase = class("AppBase")
                  127.  
                  128. -- 5.构造函数
                  129. function AppBase:ctor(configs)
                  130. self.configs_ = {
                  131. viewsRoot = "app.views",modelsRoot = "app.models",defaultSceneName = "MainScene",}
                  132.  
                  133. for k,v in pairs(configs or {}) do
                  134. self.configs_[k] = v
                  135. end
                  136.  
                  137. if type(self.configs_.viewsRoot) ~= "table" then
                  138. self.configs_.viewsRoot = {self.configs_.viewsRoot}
                  139. end
                  140. if type(self.configs_.modelsRoot) ~= "table" then
                  141. self.configs_.modelsRoot = {self.configs_.modelsRoot}
                  142. end
                  143.  
                  144. if DEBUG > 1 then
                  145. dump(self.configs_,"AppBase configs")
                  146. end
                  147.  
                  148. if CC_SHOW_FPS then
                  149. cc.Director:getInstance():setDisplayStats(true)
                  150. end
                  151.  
                  152. -- event
                  153. self:onCreate() -- 6.啥也没做的create函数
                  154. end-- 7.创建完对象之后,就到了这一步
                  155. function AppBase:run(initSceneName)
                  156. initSceneName = initSceneName or self.configs_.defaultSceneName
                  157. self:enterScene(initSceneName) -- 8.如果没有指定第一个Scene,则第一个SceneMainScene
                  158. end
                  159. -- 9.生成并进入第一个Scene
                  160. function AppBase:enterScene(sceneName,transition,time,more)
                  161. local view = self:createView(sceneName) -- 10.前去生成View
                  162. view:showWithScene(transition,more) -- 20.因为MainScene继承自ViewBase类,这里就吊用ViewBase方法
                  163. return view
                  164. end-- 11.根据name生成一个View
                  165. function AppBase:createView(name)
                  166. for _,root in ipairs(self.configs_.viewsRoot) do
                  167. local packageName = string.format("%s.%s",root,name) -- 12.这里拼接了View的路径,app/views/MainScene.lua
                  168. local status,view = xpcall(function() -- 13.这里xpcall相当于try-catch结构了,所以看第一个function
                  169. return require(packageName) -- 14.执行上面拼接的MainScene.lua脚本,view获得脚本返回值
                  170. end,function(msg)
                  171. if not string.find(msg,string.format("'%s' not found:",packageName)) then
                  172. print("load view error: ",msg)
                  173. end
                  174. end)
                  175. local t = type(view)
                  176. if status and (t == "table" or t == "userdata") then
                  177. return view:create(self,name) -- 15.这里调用MainScenecreate方法
                  178. end
                  179. end
                  180. error(string.format("AppBase:createView() - not found view \"%s\" in search paths \"%s\"",name,table.concat(self.configs_.viewsRoot,",")),0)
                  181. endlocal MainScene = class("MainScene",cc.load("mvc").ViewBase) -- 16.MainScene类继承自ViewBase,去mvc/ViewBase.lua看看
                  182.  
                  183. -- 19.创建一个Sprite,一个Label添加到这个Node
                  184. function MainScene:onCreate()
                  185. -- add background image
                  186. display.newSprite("HelloWorld.png")
                  187. :move(display.center)
                  188. :addTo(self)
                  189.  
                  190. -- add HelloWorld label
                  191. cc.Label:createWithSystemFont("Hello World","Arial",40)
                  192. :move(display.cx,display.cy + 200)
                  193. :addTo(self)
                  194.  
                  195. end
                  196.  
                  197. return MainScenelocal ViewBase = class("ViewBase",cc.Node) -- 17.继承自Node
                  198.  
                  199. -- 18.构造函数,还是进行一些初始化工作
                  200. function ViewBase:ctor(app,name)
                  201. self:enableNodeEvents()
                  202. self.app_ = app
                  203. self.name_ = name
                  204.  
                  205. -- check CSB resource file
                  206. local res = rawget(self.class,"RESOURCE_FILENAME")
                  207. if res then
                  208. self:createResoueceNode(res)
                  209. end
                  210.  
                  211. local binding = rawget(self.class,"RESOURCE_BINDING")
                  212. if res and binding then
                  213. self:createResoueceBinding(binding)
                  214. end
                  215.  
                  216. if self.onCreate then self:onCreate() end
                  217. end-- 21.这里创建了一个Scene,并且把当前这个Node添加Scene中。其实这就是C++项目HelloWorldScene类的createScene方法
                  218. function ViewBase:showWithScene(transition,time,more)
                  219. self:setVisible(true)
                  220. local scene = display.newScene(self.name_) -- 22.display包含很多功能,有点类似于Director
                  221. scene:addChild(self)
                  222. display.runScene(scene,more) -- 23.runScene熟悉的方法
                  223. return self
                  224. end#include "AppDelegate.h"
                  225. #include "CCLuaEngine.h"
                  226. #include "SimpleAudioEngine.h"
                  227. #include "cocos2d.h"
                  228. #include "lua_module_register.h"
                  229.  
                  230. #if (CC_TARGET_PLATFORM != CC_PLATFORM_LINUX)
                  231. #include "ide-support/CodeIDESupport.h"
                  232. #endif
                  233.  
                  234. #if (COCOS2D_DEBUG > 0) && (CC_CODE_IDE_DEBUG_SUPPORT > 0)
                  235. #include "runtime/Runtime.h"
                  236. #include "ide-support/RuntimeLuaImpl.h"
                  237. #endifdrawCircledrawCircle

                  猜你在找的Cocos2d-x相关文章