Cocos2d-lua 是 Cocos2d-x引擎添加了Lua绑定的版本。使用C++和Cocos2d-x引擎开发时,编写的代码是直接调用Cocos2d-x引擎的API,因为Cocos2d-x引擎也是使用C++编写的,所以无需进行语言转换。而使用Lua和Cocos2d-x编码时,编写的代码必须通过LuaEngine引擎执行,LuaEngine引擎封装了Cocos2d-x引擎的API,所以相当于使用Lua脚本在调用Cocos2d-x的API。
main.lua
main.lua
启动文件是Cocos2d-lua项目默认主入口,项目启动时默认首先执行main.lua
文件。
运行流程
步骤0:设置 编译后的客户端开始执行时,使用FileUtils
加载Luac
文件的提示是否显示。
cc.FileUtils:getInstance():setPopupNotify(true)
步骤1:将源代码src
目录和资源res
目录添加到文件搜索路径
cc.FileUtils:getInstance():addSearchPath("src/")
cc.FileUtils:getInstance():addSearchPath("res/")
addSearchPath()
方法设置源代码和资源的搜索路径步骤2:加载配置文件读取配置
require "config"
config.lua
配置文件用于定义初始化所使用的全局变量require()
方法表示引入一个文件,使用require()
方法加载文件的过程会检查文件的lua
语法,同时会完成被加载文件内部变量的初始化。步骤3:执行初始化
加载cocos/init.lua
文件,根据config.lua
配置文件对cocos2d-lua框架进行初始化。
require "cocos.init"
步骤4:加载app
目录下MyApp.lua
文件,创建App
对象并调用run()
函数。
local function main()
require("app.MyApp"):create():run()
end
class
的Create()
方法创建对象,并执行run()
方法。run()
函数用于配置第一个进入的场景,默认为MainScene
。app.MyApp
模块创建一个MyApp
实例,并调用实例的run()
方法,此时将启动执行MyApp
脚本。垃圾回收机制
local function main()
-- 运行一个完整的垃圾回收周期
collectgarbage("collect")
collectgarbage("setpause", 100)
collectgarbage("setstepmul", 5000)
end
collectgarbage("collect")
运行一个完整的垃圾回收周期
collectgarbage("count")
返回当前程序使用的内存总量,以KB
为单位。
collectgarbage("restart")
若垃圾收集器停止则重新运行
collectgarbage("step")
进行一次垃圾回收迭代,第二个参数值越大表示一次迭代的时间越长,如果本次迭代时垃圾回收的最后一次迭代则函数返回true
。
collectgarbage("stop")
停止运行垃圾收集器
collectgarbage("setpause", 100)
设置垃圾收集暂停时间变量的值,值由第二个参数指出,该值被用于控制垃圾收集器被Lua自动内存管理再次运行之前需要的等待时长。当其小于100时意味着收集器在新周期开始前不再等待。其值越大垃圾收集器被运行的频率越低,越不主动。当其值200时,收集器在总使用内存数量达到上次垃圾收集时的2倍再开启新的收集周期。因此,根据程序不同的特征,可以通过修改该值使得程序达到最佳的性能。
collectgarbage("setstepmul", 5000)
设置垃圾收集器步长倍增器的值,步长倍增器stepmul
用于控制垃圾收集器相对内存分配的速度。数值越大收集器工作越主动,同时也增加了垃圾收集每次迭代步长的大小。值小于100可能会导致垃圾器1个周期永远不能结束,建议不要这样设置。默认值为200,表示垃圾收集器运行的速率是内存分配的2倍。
错误捕获
local status, msg = xpcall(main, __G__TRACKBACK__)
if not status then
print(msg)
end
xpcall(调用函数, 错误捕获函数)
Lua提供xpcall
函数来捕获异常,当错误发生时,Lua会在栈释放前调用错误处理函数,因此可使用debug
库收集错误信息。常用debug
处理函数包括:
debug.debug
给出Lua的提示符,可手工查看错误发生时的情况。debug.traceback
控制器解释器用来构建错误信息的函数程序启动后,xpcall
(表示以“保护模式”调用函数)会被执行,它会调用main()
函数。如果发生错误,则会调用__G__TRACKBACK__()
函数。
config.lua
print()
输出信息。quick
框架,其中包括MVC框架。FPS
等显卡信息MyApp.lua
应用文件:app/MyApp.lua
local MyApp = class("MyApp", cc.load("mvc").AppBase)
function MyApp:onCreate()
math.randomseed(os.time())
end
return MyApp
MyApp
类继承自mvc
中的cc.mvc.AppBase
类,系统自动查找packages/mvc/AppBase.lua
文件,AppBase
是Quick
框架自带的一个MVC的应用程序基础类,此类为应用程序提供一些逻辑控制上的功能,如进入场景、切换场景等。class()
方法本身是Quick
框架定义的用于创建自定义lua
类的函数,function class(classname, super)
函数参数classname
表示类名,super
表示父类或创建对象实例的函数。MVC是一种组合设计模式,被广泛应用在带有图形交互的用户界面程序(GUI)开发中。MVC的宗旨在于分离关注点(SoC),将界面表现和业务逻辑分离。SoC原则在现代软件工程中是一个非常重要的设计理念。对于实际问题,要划分不同的关注点,且关注点之间必须隔离开来,这样才能达到 更好的代码重用,以获得鲁棒性、可适配性、可维护性。
Cocos2d本身并不是基于MVC的理念设计的,在Cocos2d中CCScene
、CCLayer
、CCSprite
等类都是CCNode
的子类,开发流程基本是这样的:
Touch
事件和加速计的改变。同时更新布景图层和精灵,让精灵运行一个或多个动作等。对于手游而言,界面UI的布局与显示都是由View
负责的,点击事件手势滑动等操作是由Controller
来处理的,游戏中需要的数据是由Model
负责的。
local MyApp = class("MyApp", cc.load("mvc").AppBase)
/src/packages/mvc/AppBase.lua
中定义了一个AppBase
基类,作为所有Quick游戏的Lua入口,由player新建的工程,有个app/MyApp.lua
文件就是继承自AppBase
类。
AppBase
功能类似于iOS工程中的 AppDelegate.m
实现的功能:
framework
提供程序退出接口scene
与 view
的接口,并约定其存放路径。local function main()
collectgarbage("collect")
collectgarbage("setpause", 100)
collectgarbage("setstepmul", 5000)
end
--[[
客户端本地存储
场景:游戏中需在本地存储数据,根据存储的数据类型调用接口
设置客户端本地数据库,本地的UserDefault.xml会存在相应数据。
--]]
-- 获取客户端本地存储数据
function GetClientUserData(key, dataType)
local type = string.lower(dataType)
if type == "bool" then
return cc.UserDefault:getInstance():getBoolForKey(key)
elseif type == "int" then
return cc.UserDefault:getInstance():getIntegerForKey(key)
elseif type == "float" then
return cc.UserDefault:getInstance():getFloatForKey(key)
elseif type=="double" then
return cc.UserDefault:getInstance():getDoubleForKey(key)
elseif type == "string" then
return cc.UserDefault:getInstance():getStringForKey(key)
end
end
-- 设置客户端本地存储数据
function SetClientUserData(key, value, dataType)
local type = string.lower(dataType)
if type == "bool" then
return cc.UserDefault:getInstance():setBoolForKey(key, value)
elseif type=="int" then
return cc.UserDefault:getInstance():setIntegerForKey(key, value)
elseif type=="float" then
return cc.UserDefault:getInstance():setFloatForKey(key, value)
elseif type=="double" then
return cc.UserDefault:getInstance():setDoubleForKey(key, value)
end
声音引擎:SimpleAudioEngine
音乐格式 iOS和Android均可采用MP3格式
AudioEngine.preload("bg.mp3") 预加载背景音乐
AudioEngine.playMusic("bg.mp3", true) 播放背景音乐,true为循环。
AudioEngine.stopMusic() 停止播放音乐
AudioEngine.pauseMusic() 暂停播放音乐
AudioEngine.resumeMusic() 恢复播放音乐
AudioEngine.isMusicPlaying() 判断音乐是否播放
AudioEngine.setMusicVolumn(0.5) 设置音乐音量
AudioEngine.getMusicVolumn() 获取音乐音量
音效格式 iOS可采用MP3或WAV,Android可采用OGG格式。
AudioEngine.preloadEffect("effect.mp3") 预加载音效
AudioEngine.playEffect("effect.mp3") 播放音效
AudioEngine.pauseAllEffect() 暂停所有音效的播放
AudioEngine.resumeAllEffect() 继续播放所有音效
AudioEngine.resumeEffect(id) 继续播放指定ID的音效
AudioEngine.stopEffect(id) 停止播放指定ID的音效
AudioEngine.stopAllEffect() 停止播放所有音效
AudioEngine.setEffectsMusicVolumn(0.5) 设置音效音量
AudioEngine.getEffectsVolumn() 获取音效音量
-- LUA使用方式
cc.SimpleAudioEngine:getInstance():playMusic("bg.mp3")
-- 重新设置为上次声音
local musicVolumn = cc.UserDefault:getInstance():getFloatForKey("MusicVolumn", 1)
cc.SimpleAudioEngine:getInstance():setMusicVolumn(musicVolumn)
cc.SimpleAudioEngine:getInstance():setEffectsMusicVolumn(musicVolumn)
玩法:初始化5个血量,随机生成爬向洞的昆虫,累积进入5个即结束游戏。
生命周期顺序流程
init()
初始化布景层调用,在类初始化时,仅会调用一次。onEnter()
进入布景层时调用,可能会发生多次。Cocos2dx类似于ObjectC一样,有两种方式来申请内存创建对象,一种是静态函数create()
,一种是在自身的init()
中,在这两种函数中申请内存创建对象能让程序正常运行,但是当对象将要去展现或被添加到另一个容器时,它会调用onEnter()
函数,所以最好不要在onEnter()
中做内存方面的操作。
onEnterTransitionDidFinish()
进入布景层且过渡动画结束时调用onExit()
退出布景层时调用onExitTransitionDidStart()
退出布景层且开始过渡动画时调用clearup()
布景层对象被清除时调用,整个布景层销毁时调用。简单来说
init()
->onEnter()
->onEnterTransitionDidFinish()
onExit()
->onExitTransitionDidStart()
->init()
onEnter
和onExit
在Lua中不会因为节点的add
和remove
而直接被调用, 当子节点被父节点的add
和remove
时,会发送enter
和exit
的消息,所以需要初始化节点的时候,监听消息并在收到消息后调用onEnter
或onExit
。