关键词:
cocos2d-lua项目启动流程
lua调用cocos2d引擎API

 
 
这里是个小测试
环境
  1. 引擎版本:Cocos2d-x 3.10
  2. 开发工具: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文件中拷出来的,加了一些注释。
从这里我们可以看出进入游戏逻辑的流程:

 
 
  1. 初始化Director
  2. 新建GLView,然后进行一些设置
  3. 新建Scene
  4. 使用Director运行这个场景
游戏逻辑就可以从这个Scene中的init函数开始,添加UI层,添加事件监听器,添加游戏层等等...如果我们有一些统计、资源管理器等,也可以在AppDelegate的函数中来进行。

Lua项目

也来看AppDelegate.cpp中的函数

从上面代码可以看到,Cocos2d-x新建的Lua语言项目中,这里没有进行GLView的设置,没有使用C++代码来创建Scene,所以这些操作肯定和"src/main.lua"脚本有关。这里我们一步一步来看src目录下这些脚本执行的步骤(注意看注释的序号):

 
 
  1. 在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下打开两个项目,可以对比一下项目结构:
compare.png
从最外层结构可以看出Lua工程比C++工程多了两个lib:
  1. libsimulator模拟器支持
  2. 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文件夹可以看到如下文件列表:

 
 
manual:cocos2d.png
从其中LuaOpengl.cpp中包含的代码:
LuaOpengl.png
可以看到这里在注册一个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() { // initialize director auto director = Director::getInstance(); //初始化Director auto glview = director->getopenGLView(); //获得GLView,也就是游戏窗口 //此时GLView为空 if(!glview) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX) //如果当前是以上平台,就创建一个大小为designResolutionSize的窗口 glview = GLViewImpl::createWithRect("TestCpp",Rect(0,0,designResolutionSize.width,designResolutionSize.height)); #else //其他平台,则使用默认设置(在ios上是全屏窗口,其他平台不太清楚,也有可能是默认设置了一个窗口大小) glview = GLViewImpl::create("TestCpp"); #endif director->setopenGLView(glview); //director获得当前新建的窗口 } // turn on display FPS director->setdisplayStats(true); //显示帧率信息 // set FPS. the default value is 1.0/60 if you don't call this director->setAnimationInterval(1.0 / 60); //设置动画帧率,也就是界面刷新帧率咯 // Set the design resolution glview->setDesignResolutionSize(designResolutionSize.width,designResolutionSize.height,ResolutionPolicy::NO_BORDER); //设置设计分辨率,而不是实际分辨率,这里是为了适配,不能把实际分辨率固定 Size frameSize = glview->getFrameSize(); //获得实际窗口大小 //根据实际窗口大小,设置内容缩放比例 // 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)); } // 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)); } // 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(); //使用包管理器。。 不太清楚这里是为什么 // create a scene. it's an autorelease object auto scene = HelloWorld::createScene(); //新建一个场景 // run director->runWithScene(scene); //从这个场景开始运行,开始绘制、子节点管理等 return true; }applicationDidFinishLaunchingapplicationDidFinishLaunchingbool AppDelegate::applicationDidFinishLaunching() { // set default FPS Director::getInstance()->setAnimationInterval(1.0 / 60.0f); //设置动画帧率,也就是游戏帧率了 //重点:添加Lua相关支持 // register lua module auto engine = LuaEngine::getInstance(); //初始化一个Lua语言引擎 ScriptEngineManager::getInstance()->setScriptEngine(engine); //将Lua语言引擎设置为当前脚本引擎(用脚本引擎管理器来管理各种脚本引擎) lua_State* L = engine->getLuaStack()->getLuaState(); //获取Lua引擎的State,也就是一组属性 lua_module_register(L); //向Lua引擎注册一些模块,如网络、动画等 register_all_packages(); //设置脚本加密相关的key和sign LuaStack* stack = engine->getLuaStack(); stack->setXXTEAKeyAndSign("2dxLua",strlen("2dxLua"),"XXTEA",strlen("XXTEA")); //register custom function //LuaStack* stack = engine->getLuaStack(); //register_custom_function(stack->getLuaState()); #if (COCOS2D_DEBUG > 0) && (CC_CODE_IDE_DEBUG_SUPPORT > 0) //如果需要支持CodeIDE,则从引擎本身启动 // 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(); #else //一般情况,这里使用Lua引擎执行第一个Lua脚本 if (engine->executeScriptFile("src/main.lua")) { return false; //脚本默认返回nil,如果脚本执行正常,不会进入这一句 } #endif return true; //正常执行到这里,后面就开始执行Cocos引擎提供的主循环 }cc.FileUtils:getInstance():setPopupNotify(false) cc.FileUtils:getInstance():addSearchPath("src/") cc.FileUtils:getInstance():addSearchPath("res/") require "config" -- 1.执行当前目录下的config.lua,定义一些初始化用的全局变量,包括窗口设置等 require "cocos.init" -- 2.执行cocos/init.lua,初始化框架等一大堆东西,包括OpenGL、音效等引擎的初始化与配置 local function main() require("app.MyApp"):create():run() -- 3.执行app/MyApp.lua,调用对应class的Create方法创建对象,并执行run方法 end -- 先忽略这个,我也不知道是啥 local status,msg = xpcall(main,__G__TRACKBACK__) if not status then print(msg) endlocal MyApp = class("MyApp",cc.load("mvc").AppBase) -- 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-- 7.创建完对象之后,就到了这一步 function AppBase:run(initSceneName) initSceneName = initSceneName or self.configs_.defaultSceneName self:enterScene(initSceneName) -- 8.如果没有指定第一个Scene,则第一个Scene为MainScene end -- 9.生成并进入第一个Scene function AppBase:enterScene(sceneName,transition,time,more) local view = self:createView(sceneName) -- 10.前去生成View view:showWithScene(transition,more) -- 20.因为MainScene继承自ViewBase类,这里就吊用ViewBase的方法了 return view end-- 11.根据name生成一个View function AppBase:createView(name) for _,root in ipairs(self.configs_.viewsRoot) do local packageName = string.format("%s.%s",root,name) -- 12.这里拼接了View的路径,app/views/MainScene.lua local status,view = xpcall(function() -- 13.这里xpcall相当于try-catch结构了,所以看第一个function return require(packageName) -- 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) -- 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#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

Cocos2d-lua的运行理解的更多相关文章

  1. ios – 如何使用Objective C类中的多个参数调用Swift函数?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  2. ios – Swift 4添加手势:覆盖vs @objc

    我想在我的视图中添加一个手势,如下所示:但是,在Swift4中,我的编译器给出了以下错误:建议添加@objc以将此实例方法公开给Objective-C.实现此目的的另一个选项将覆盖touchesBegan()函数并使用它来处理点击.我试图以“Swift”的方式做到这一点,而不必带入Obj-C.有没有纯粹的Swift方式来添加这个轻击手势而不使用@objc?

  3. ios – 将视频分享到Facebook

    我正在编写一个简单的测试应用程序,用于将视频从iOS上传到Facebook.由于FacebookSDK的所有文档都在Objective-C中,因此我发现很难在线找到有关如何使用Swift执行此操作的示例/教程.到目前为止我有这个在我的UI上放置一个共享按钮,但它看起来已禁用,从我读到的这是因为没有内容设置,但我看不出这是怎么可能的.我的getVideoURL()函数返回一个NSURL,它肯定包含视

  4. ios – 以编程方式在Swift中添加联系人

    我想在Swift中以编程方式添加联系人.我发现了一些Objective-C示例,但我没有让它们工作,甚至在Objective-C中也没有.我不希望这涉及到AddressBookUI,因为我想从我自己的UI中获取值.解决方法这是在Swift中添加联系人的快速方法.我在我的iPhone5iOS7.1上验证了它,因为我发现模拟器并不总是与我的手机对AB的东西相同.您可以添加一个按钮并指向此方法:顺便说一下–它假设你已经分配了一个地址簿var,你可以通过覆盖viewDidAppear来打开视图.它也会执行安全提示

  5. ios – 为目标c中的方法传递未知类型的参数,可能吗?

    是否可以将未知类型的参数传递给objective-C方法?在C#中你可以写实现这一点,但我知道Objective-C没有泛型,所以有没有其他方法可以在Objective-C中实现这一点?我需要这个,因为我想创建一个方法来改变不同对象的文本颜色,如UITextField和UIButton的占位符文本.所以我的计划是创建一个名为textWhite的方法,然后在此方法中检查对象的类型,然后运行匹配的代码以使文本颜色变为白色.解决方法是的,可以传递未知类型的参数.见下面的例子.请参考使用id对象的链接作为参数Us

  6. ios – Swift指针算术和解除引用;将一些类似C的地图代码转换为Swift

    我有一点似乎没有工作的Swift代码……解决方法您正在指定locationPointer指向新位置,但仍在下一行中使用ptr,并且ptr的值尚未更改.将您的最后一行更改为:或者你可以改变指向var的指针并推进它:

  7. ios – “禁用模块时使用’@import’”错误 – 启用模块和链接框架= YES

    我有一个使用CocoaPods并使用’SCLAlertView-Objective-C’窗格的项目.该pod使用@importUIKit;模块样式导入.我在目标和项目设置中将“启用模块(C&Objective-C)”和“自动链接框架”设置为YES.当模块被禁用时,我仍然得到“使用’@import’错误.有没有什么可以阻止Xcode能够启用模块,如使用.pch文件,任何链接器标志,或者我没有提到的任

  8. XCode 6.3立即在抛出的Objective-C异常上引发SIGABRT

    考虑以下目标-C代码在XCode6.2中,它按预期工作(记录“错误消息”).但是,由于我们升级到6.3,抛出行(throwstd::logic_error…)引发SIGABRT(堆栈跟踪仅包含_cxa_throw和_pthread_kill,超出applicationdidFinishLaunchingWithOptions)并导致应用程序崩溃.这只发生在我们的应用程序中–当我将完全相同的代码复制

  9. ios – 在swift框架中使用Bridging Headers时失败

    我正在做一个快速的框架,我想使用旧的目标c类.为此,我使用桥接头方法但是当我尝试构建时出现此错误:我将我的{PROJECT}-Bridging-Header.h添加到Swift编译器中的Objective-C桥接头–代码生成我怎么解决它?

  10. XCode 3.2 Ruby和Python模板

    在xcode3.2下,我的ObjectiveCPython/Ruby项目仍然可以打开更新和编译,但是你无法创建新项目.鉴于xcode3.2中缺少ruby和python的所有痕迹(即创建项目并添加新的ruby/python文件),是否有一种简单的方法可以再次安装模板?我发现了一些关于将它们复制到某个文件夹的信息,但我似乎无法让它工作,我怀疑文件夹的位置已经改变为3.2.解决方法3.2中的应用程序模板

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部