关键词: 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运行这个场景
Lua项目
也来看AppDelegate.cpp中的函数 从上面代码可以看到,Cocos2d-x新建的Lua语言项目中,这里没有进行GLView的设置,没有使用C++代码来创建Scene,所以这些操作肯定和"src/main.lua"脚本有关。这里我们一步一步来看src目录下这些脚本执行的步骤(注意看注释的序号):- 在main.lua中部分注释:
简单对比Cocos2d-x创建的C++工程和Lua工程
这里使用Cocos2d-x 3.10分别创建了Lua语言工程和C++语言工程,在Xcode下打开两个项目,可以对比一下项目结构: 从最外层结构可以看出Lua工程比C++工程多了两个lib:- libsimulator模拟器支持
- cocos2d_lua_bindings引擎与Lua脚本的桥接层
理解一下
想想脚本执行时的情景,当执行到一个名为的函数时,用户自己很可能并没有定义这样一个函数,那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() { @H_301_96@// initialize director auto director = Director::getInstance(); @H_301_96@//初始化Director auto glview = director->getOpenGLView(); @H_301_96@//获得GLView,也就是游戏窗口 @H_301_96@//此时GLView为空 if(!glview) { @H_301_96@//如果当前是以上平台,就创建一个大小为designResolutionSize的窗口 glview = GLViewImpl::createWithRect("TestCpp",Rect(0,0,designResolutionSize.width,designResolutionSize.height)); @H_301_96@//其他平台,则使用默认设置(在ios上是全屏窗口,其他平台不太清楚,也有可能是默认设置了一个窗口大小) glview = GLViewImpl::create("TestCpp"); director->setOpenGLView(glview); @H_301_96@//director获得当前新建的窗口 } @H_301_96@// turn on display FPS director->setDisplayStats(true); @H_301_96@//显示帧率信息 @H_301_96@// set FPS. the default value is 1.0/60 if you don't call this director->setAnimationInterval(1.0 / 60); @H_301_96@//设置动画帧率,也就是界面刷新帧率咯 @H_301_96@// Set the design resolution glview->setDesignResolutionSize(designResolutionSize.width,designResolutionSize.height,ResolutionPolicy::NO_BORDER); @H_301_96@//设置设计分辨率,而不是实际分辨率,这里是为了适配,不能把实际分辨率固定 Size frameSize = glview->getFrameSize(); @H_301_96@//获得实际窗口大小 @H_301_96@//根据实际窗口大小,设置内容缩放比例 @H_301_96@// if the frame's height is larger than the height of medium size. if (frameSize.height > mediumResolutionSize.height) { director->setContentScaleFactor(MIN(largeResolutionSize.height/designResolutionSize.height,largeResolutionSize.width/designResolutionSize.width)); } @H_301_96@// if the frame's height is larger than the height of small size. else if (frameSize.height > smallResolutionSize.height) { director->setContentScaleFactor(MIN(mediumResolutionSize.height/designResolutionSize.height,mediumResolutionSize.width/designResolutionSize.width)); } @H_301_96@// if the frame's height is smaller than the height of medium size. else { director->setContentScaleFactor(MIN(smallResolutionSize.height/designResolutionSize.height,smallResolutionSize.width/designResolutionSize.width)); } register_all_packages(); @H_301_96@//使用包管理器。。 不太清楚这里是为什么 @H_301_96@// create a scene. it's an autorelease object auto scene = HelloWorld::createScene(); @H_301_96@//新建一个场景 @H_301_96@// run director->runWithScene(scene); @H_301_96@//从这个场景开始运行,开始绘制、子节点管理等 return true; }applicationDidFinishLaunchingapplicationDidFinishLaunchingbool AppDelegate::applicationDidFinishLaunching() { @H_301_96@// set default FPS Director::getInstance()->setAnimationInterval(1.0 / 60.0f); @H_301_96@//设置动画帧率,也就是游戏帧率了 @H_301_96@//重点:添加Lua相关支持 @H_301_96@// register lua module auto engine = LuaEngine::getInstance(); @H_301_96@//初始化一个Lua语言引擎 ScriptEngineManager::getInstance()->setScriptEngine(engine); @H_301_96@//将Lua语言引擎设置为当前脚本引擎(用脚本引擎管理器来管理各种脚本引擎) lua_State* L = engine->getLuaStack()->getLuaState(); @H_301_96@//获取Lua引擎的State,也就是一组属性 lua_module_register(L); @H_301_96@//向Lua引擎注册一些模块,如网络、动画等 register_all_packages(); @H_301_96@//设置脚本加密相关的key和sign LuaStack* stack = engine->getLuaStack(); stack->setXXTEAKeyAndSign("2dxLua",strlen("2dxLua"),"XXTEA",strlen("XXTEA")); @H_301_96@//register custom function @H_301_96@//LuaStack* stack = engine->getLuaStack(); @H_301_96@//register_custom_function(stack->getLuaState()); @H_301_96@#if (COCOS2D_DEBUG > 0) && (CC_CODE_IDE_DEBUG_SUPPORT > 0) @H_301_96@//如果需要支持CodeIDE,则从引擎本身启动 @H_301_96@// NOTE:Please don't remove this call if you want to debug with Cocos Code IDE auto runtimeEngine = RuntimeEngine::getInstance(); runtimeEngine->addRuntime(RuntimeLuaImpl::create(),kRuntimeEngineLua); runtimeEngine->start(); @H_301_96@#else @H_301_96@//一般情况,这里使用Lua引擎执行第一个Lua脚本 if (engine->executeScriptFile("src/main.lua")) { return false; @H_301_96@//脚本默认返回nil,如果脚本执行正常,不会进入这一句 } @H_301_96@#endif return true; @H_301_96@//正常执行到这里,后面就开始执行Cocos引擎提供的主循环 }cc.FileUtils:getInstance():setPopupNotify(false) cc.FileUtils:getInstance():addSearchPath("src/") cc.FileUtils:getInstance():addSearchPath("res/") require "config" @H_301_96@-- 1.执行当前目录下的config.lua,定义一些初始化用的全局变量,包括窗口设置等 require "cocos.init" @H_301_96@-- 2.执行cocos/init.lua,初始化框架等一大堆东西,包括OpenGL、音效等引擎的初始化与配置 local function main() require("app.MyApp"):create():run() @H_301_96@-- 3.执行app/MyApp.lua,调用对应class的Create方法创建对象,并执行run方法 end @H_301_96@-- 先忽略这个,我也不知道是啥 local status,msg = xpcall(main,__G__TRACKBACK__) if not status then print(msg) endlocal MyApp = class("MyApp",cc.load("mvc").AppBase) @H_301_96@-- 4.类MyApp继承自mvc中的AppBase类,自动找到packages/mvc/AppBase.lua 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@H_301_96@-- 7.创建完对象之后,就到了这一步 function AppBase:run(initSceneName) initSceneName = initSceneName or self.configs_.defaultSceneName self:enterScene(initSceneName) @H_301_96@-- 8.如果没有指定第一个Scene,则第一个Scene为MainScene end @H_301_96@-- 9.生成并进入第一个Scene function AppBase:enterScene(sceneName,transition,time,more) local view = self:createView(sceneName) @H_301_96@-- 10.前去生成View view:showWithScene(transition,more) @H_301_96@-- 20.因为MainScene继承自ViewBase类,这里就吊用ViewBase的方法了 return view end@H_301_96@-- 11.根据name生成一个View function AppBase:createView(name) for _,root in ipairs(self.configs_.viewsRoot) do local packageName = string.format("%s.%s",root,name) @H_301_96@-- 12.这里拼接了View的路径,app/views/MainScene.lua local status,view = xpcall(function() @H_301_96@-- 13.这里xpcall相当于try-catch结构了,所以看第一个function return require(packageName) @H_301_96@-- 14.执行上面拼接的MainScene.lua脚本,view获得脚本返回值 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) @H_301_96@-- 15.这里调用了MainScene的create方法噢 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 drawCircledrawCircle 原文链接:https://www.f2er.com/cocos2dx/338601.html