Cocos2d-lua 是 Cocos2d-x引擎添加了Lua綁定的版本静尼。使用C++和Cocos2d-x引擎開(kāi)發(fā)時(shí)殿托,編寫(xiě)的代碼是直接調(diào)用Cocos2d-x引擎的API支鸡,因?yàn)镃ocos2d-x引擎也是使用C++編寫(xiě)的暖侨,所以無(wú)需進(jìn)行語(yǔ)言轉(zhuǎn)換椭住。而使用Lua和Cocos2d-x編碼時(shí),編寫(xiě)的代碼必須通過(guò)LuaEngine引擎執(zhí)行字逗,LuaEngine引擎封裝了Cocos2d-x引擎的API京郑,所以相當(dāng)于使用Lua腳本在調(diào)用Cocos2d-x的API。
主入口文件 main.lua
main.lua
啟動(dòng)文件是Cocos2d-lua項(xiàng)目默認(rèn)主入口葫掉,項(xiàng)目啟動(dòng)時(shí)默認(rèn)首先執(zhí)行main.lua
文件些举。
運(yùn)行流程
步驟0:設(shè)置 編譯后的客戶端開(kāi)始執(zhí)行時(shí),使用FileUtils
加載Luac
文件的提示是否顯示俭厚。
cc.FileUtils:getInstance():setPopupNotify(true)
步驟1:將源代碼src
目錄和資源res
目錄添加到文件搜索路徑
cc.FileUtils:getInstance():addSearchPath("src/")
cc.FileUtils:getInstance():addSearchPath("res/")
- 通過(guò)
addSearchPath()
方法設(shè)置源代碼和資源的搜索路徑
步驟2:加載配置文件讀取配置
require "config"
-
config.lua
配置文件用于定義初始化所使用的全局變量 -
require()
方法表示引入一個(gè)文件户魏,使用require()
方法加載文件的過(guò)程會(huì)檢查文件的lua
語(yǔ)法,同時(shí)會(huì)完成被加載文件內(nèi)部變量的初始化。
步驟3:執(zhí)行初始化
加載cocos/init.lua
文件叼丑,根據(jù)config.lua
配置文件對(duì)cocos2d-lua框架進(jìn)行初始化关翎。
require "cocos.init"
步驟4:加載app
目錄下MyApp.lua
文件,創(chuàng)建App
對(duì)象并調(diào)用run()
函數(shù)幢码。
local function main()
require("app.MyApp"):create():run()
end
- 調(diào)用對(duì)應(yīng)
class
的Create()
方法創(chuàng)建對(duì)象笤休,并執(zhí)行run()
方法。 -
run()
函數(shù)用于配置第一個(gè)進(jìn)入的場(chǎng)景症副,默認(rèn)為MainScene
店雅。 - 通過(guò)載入的
app.MyApp
模塊創(chuàng)建一個(gè)MyApp
實(shí)例,并調(diào)用實(shí)例的run()
方法贞铣,此時(shí)將啟動(dòng)執(zhí)行MyApp
腳本闹啦。
垃圾回收機(jī)制
local function main()
-- 運(yùn)行一個(gè)完整的垃圾回收周期
collectgarbage("collect")
collectgarbage("setpause", 100)
collectgarbage("setstepmul", 5000)
end
collectgarbage("collect")
運(yùn)行一個(gè)完整的垃圾回收周期
collectgarbage("count")
返回當(dāng)前程序使用的內(nèi)存總量,以KB
為單位辕坝。
collectgarbage("restart")
若垃圾收集器停止則重新運(yùn)行
collectgarbage("step")
進(jìn)行一次垃圾回收迭代窍奋,第二個(gè)參數(shù)值越大表示一次迭代的時(shí)間越長(zhǎng),如果本次迭代時(shí)垃圾回收的最后一次迭代則函數(shù)返回true
酱畅。
collectgarbage("stop")
停止運(yùn)行垃圾收集器
collectgarbage("setpause", 100)
設(shè)置垃圾收集暫停時(shí)間變量的值琳袄,值由第二個(gè)參數(shù)指出,該值被用于控制垃圾收集器被Lua自動(dòng)內(nèi)存管理再次運(yùn)行之前需要的等待時(shí)長(zhǎng)纺酸。當(dāng)其小于100時(shí)意味著收集器在新周期開(kāi)始前不再等待窖逗。其值越大垃圾收集器被運(yùn)行的頻率越低,越不主動(dòng)餐蔬。當(dāng)其值200時(shí)碎紊,收集器在總使用內(nèi)存數(shù)量達(dá)到上次垃圾收集時(shí)的2倍再開(kāi)啟新的收集周期。因此樊诺,根據(jù)程序不同的特征仗考,可以通過(guò)修改該值使得程序達(dá)到最佳的性能。
collectgarbage("setstepmul", 5000)
設(shè)置垃圾收集器步長(zhǎng)倍增器的值词爬,步長(zhǎng)倍增器stepmul
用于控制垃圾收集器相對(duì)內(nèi)存分配的速度秃嗜。數(shù)值越大收集器工作越主動(dòng),同時(shí)也增加了垃圾收集每次迭代步長(zhǎng)的大小缸夹。值小于100可能會(huì)導(dǎo)致垃圾器1個(gè)周期永遠(yuǎn)不能結(jié)束痪寻,建議不要這樣設(shè)置。默認(rèn)值為200虽惭,表示垃圾收集器運(yùn)行的速率是內(nèi)存分配的2倍橡类。
錯(cuò)誤捕獲
local status, msg = xpcall(main, __G__TRACKBACK__)
if not status then
print(msg)
end
xpcall(調(diào)用函數(shù), 錯(cuò)誤捕獲函數(shù))
Lua提供xpcall
函數(shù)來(lái)捕獲異常,當(dāng)錯(cuò)誤發(fā)生時(shí)芽唇,Lua會(huì)在棧釋放前調(diào)用錯(cuò)誤處理函數(shù)顾画,因此可使用debug
庫(kù)收集錯(cuò)誤信息取劫。常用debug
處理函數(shù)包括:
-
debug.debug
給出Lua的提示符,可手工查看錯(cuò)誤發(fā)生時(shí)的情況研侣。 -
debug.traceback
控制器解釋器用來(lái)構(gòu)建錯(cuò)誤信息的函數(shù)
程序啟動(dòng)后谱邪,xpcall
(表示以“保護(hù)模式”調(diào)用函數(shù))會(huì)被執(zhí)行,它會(huì)調(diào)用main()
函數(shù)庶诡。如果發(fā)生錯(cuò)誤惦银,則會(huì)調(diào)用__G__TRACKBACK__()
函數(shù)。
配置文件 config.lua
- DEBUG
設(shè)置輸出調(diào)試信息選項(xiàng)末誓,即通過(guò)控制不同的print()
輸出信息扯俱。
0 表示關(guān)閉
1 表示打印少量調(diào)試信息
2 表示打印標(biāo)準(zhǔn)完整的調(diào)試信息 - CC_USE_FRAMEWORK
設(shè)置是否使用quick
框架,其中包括MVC框架喇澡。 - CC_SHOW_FPS
設(shè)置是否顯示FPS
等顯卡信息 - CC_DISABLE_GLOBAL
設(shè)置是否允許定義全局字段 - CC_DESIGN_RESOLUTION
設(shè)置不同分辨率
默認(rèn)應(yīng)用 MyApp.lua
應(yīng)用文件: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
類迅栅,系統(tǒng)自動(dòng)查找packages/mvc/AppBase.lua
文件,AppBase
是Quick
框架自帶的一個(gè)MVC的應(yīng)用程序基礎(chǔ)類晴玖,此類為應(yīng)用程序提供一些邏輯控制上的功能读存,如進(jìn)入場(chǎng)景、切換場(chǎng)景等呕屎。 -
class()
方法本身是Quick
框架定義的用于創(chuàng)建自定義lua
類的函數(shù)让簿,function class(classname, super)
函數(shù)參數(shù)classname
表示類名,super
表示父類或創(chuàng)建對(duì)象實(shí)例的函數(shù)秀睛。
MVC
MVC是一種組合設(shè)計(jì)模式拜英,被廣泛應(yīng)用在帶有圖形交互的用戶界面程序(GUI)開(kāi)發(fā)中。MVC的宗旨在于分離關(guān)注點(diǎn)(SoC)琅催,將界面表現(xiàn)和業(yè)務(wù)邏輯分離。SoC原則在現(xiàn)代軟件工程中是一個(gè)非常重要的設(shè)計(jì)理念虫给。對(duì)于實(shí)際問(wèn)題藤抡,要?jiǎng)澐植煌年P(guān)注點(diǎn),且關(guān)注點(diǎn)之間必須隔離開(kāi)來(lái)抹估,這樣才能達(dá)到 更好的代碼重用缠黍,以獲得魯棒性、可適配性药蜻、可維護(hù)性瓷式。
Cocos2d本身并不是基于MVC的理念設(shè)計(jì)的,在Cocos2d中CCScene
语泽、CCLayer
贸典、CCSprite
等類都是CCNode
的子類,開(kāi)發(fā)流程基本是這樣的:
- 通過(guò)應(yīng)用程序代理類來(lái)初始化第一個(gè)即主場(chǎng)景
- 場(chǎng)景中實(shí)例化一個(gè)或多個(gè)布景圖層踱卵,并將其添加進(jìn)去廊驼。
- 布景圖層中實(shí)例化一個(gè)或多個(gè)精靈据过,并將其添加進(jìn)去。
- 場(chǎng)景處理用戶輸入妒挎,例如
Touch
事件和加速計(jì)的改變绳锅。同時(shí)更新布景圖層和精靈,讓精靈運(yùn)行一個(gè)或多個(gè)動(dòng)作等酝掩。 - 場(chǎng)景中運(yùn)行一個(gè)游戲循環(huán)(一般是1/60更新一次)鳞芙,然后布景圖層和精靈在游戲循環(huán)中做更新和游戲邏輯。
對(duì)于手游而言期虾,界面UI的布局與顯示都是由View
負(fù)責(zé)的原朝,點(diǎn)擊事件手勢(shì)滑動(dòng)等操作是由Controller
來(lái)處理的,游戲中需要的數(shù)據(jù)是由Model
負(fù)責(zé)的彻消。
local MyApp = class("MyApp", cc.load("mvc").AppBase)
/src/packages/mvc/AppBase.lua
中定義了一個(gè)AppBase
基類竿拆,作為所有Quick游戲的Lua入口,由player新建的工程宾尚,有個(gè)app/MyApp.lua
文件就是繼承自AppBase
類丙笋。
AppBase
功能類似于iOS工程中的 AppDelegate.m
實(shí)現(xiàn)的功能:
- 程序前后臺(tái)切換事件的接收和分發(fā)
- 為
framework
提供程序退出接口 - 提供創(chuàng)建
scene
與view
的接口,并約定其存放路徑煌贴。
垃圾收集
local function main()
collectgarbage("collect")
collectgarbage("setpause", 100)
collectgarbage("setstepmul", 5000)
end
本地存儲(chǔ)
--[[
客戶端本地存儲(chǔ)
場(chǎng)景:游戲中需在本地存儲(chǔ)數(shù)據(jù)御板,根據(jù)存儲(chǔ)的數(shù)據(jù)類型調(diào)用接口
設(shè)置客戶端本地?cái)?shù)據(jù)庫(kù),本地的UserDefault.xml會(huì)存在相應(yīng)數(shù)據(jù)牛郑。
--]]
-- 獲取客戶端本地存儲(chǔ)數(shù)據(jù)
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
-- 設(shè)置客戶端本地存儲(chǔ)數(shù)據(jù)
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
聲音系統(tǒng)
聲音引擎:SimpleAudioEngine
音樂(lè)格式 iOS和Android均可采用MP3格式
AudioEngine.preload("bg.mp3") 預(yù)加載背景音樂(lè)
AudioEngine.playMusic("bg.mp3", true) 播放背景音樂(lè)怠肋,true為循環(huán)。
AudioEngine.stopMusic() 停止播放音樂(lè)
AudioEngine.pauseMusic() 暫停播放音樂(lè)
AudioEngine.resumeMusic() 恢復(fù)播放音樂(lè)
AudioEngine.isMusicPlaying() 判斷音樂(lè)是否播放
AudioEngine.setMusicVolumn(0.5) 設(shè)置音樂(lè)音量
AudioEngine.getMusicVolumn() 獲取音樂(lè)音量
音效格式 iOS可采用MP3或WAV,Android可采用OGG格式淹朋。
AudioEngine.preloadEffect("effect.mp3") 預(yù)加載音效
AudioEngine.playEffect("effect.mp3") 播放音效
AudioEngine.pauseAllEffect() 暫停所有音效的播放
AudioEngine.resumeAllEffect() 繼續(xù)播放所有音效
AudioEngine.resumeEffect(id) 繼續(xù)播放指定ID的音效
AudioEngine.stopEffect(id) 停止播放指定ID的音效
AudioEngine.stopAllEffect() 停止播放所有音效
AudioEngine.setEffectsMusicVolumn(0.5) 設(shè)置音效音量
AudioEngine.getEffectsVolumn() 獲取音效音量
-- LUA使用方式
cc.SimpleAudioEngine:getInstance():playMusic("bg.mp3")
-- 重新設(shè)置為上次聲音
local musicVolumn = cc.UserDefault:getInstance():getFloatForKey("MusicVolumn", 1)
cc.SimpleAudioEngine:getInstance():setMusicVolumn(musicVolumn)
cc.SimpleAudioEngine:getInstance():setEffectsMusicVolumn(musicVolumn)
殺蟲(chóng)游戲
玩法:初始化5個(gè)血量笙各,隨機(jī)生成爬向洞的昆蟲(chóng),累積進(jìn)入5個(gè)即結(jié)束游戲础芍。
布景層生命周期
生命周期順序流程
-
init()
初始化布景層調(diào)用杈抢,在類初始化時(shí),僅會(huì)調(diào)用一次仑性。 -
onEnter()
進(jìn)入布景層時(shí)調(diào)用惶楼,可能會(huì)發(fā)生多次。
Cocos2dx類似于ObjectC一樣诊杆,有兩種方式來(lái)申請(qǐng)內(nèi)存創(chuàng)建對(duì)象歼捐,一種是靜態(tài)函數(shù)create()
,一種是在自身的init()
中晨汹,在這兩種函數(shù)中申請(qǐng)內(nèi)存創(chuàng)建對(duì)象能讓程序正常運(yùn)行豹储,但是當(dāng)對(duì)象將要去展現(xiàn)或被添加到另一個(gè)容器時(shí),它會(huì)調(diào)用onEnter()
函數(shù)宰缤,所以最好不要在onEnter()
中做內(nèi)存方面的操作颂翼。
-
onEnterTransitionDidFinish()
進(jìn)入布景層且過(guò)渡動(dòng)畫(huà)結(jié)束時(shí)調(diào)用 -
onExit()
退出布景層時(shí)調(diào)用 -
onExitTransitionDidStart()
退出布景層且開(kāi)始過(guò)渡動(dòng)畫(huà)時(shí)調(diào)用 -
clearup()
布景層對(duì)象被清除時(shí)調(diào)用晃洒,整個(gè)布景層銷毀時(shí)調(diào)用。
簡(jiǎn)單來(lái)說(shuō)
- 進(jìn)入布景層時(shí):
init()
->onEnter()
->onEnterTransitionDidFinish()
- 退出布景層時(shí):
onExit()
->onExitTransitionDidStart()
->init()
onEnter
和onExit
在Lua中不會(huì)因?yàn)楣?jié)點(diǎn)的add
和remove
而直接被調(diào)用朦乏, 當(dāng)子節(jié)點(diǎn)被父節(jié)點(diǎn)的add
和remove
時(shí)球及,會(huì)發(fā)送enter
和exit
的消息,所以需要初始化節(jié)點(diǎn)的時(shí)候呻疹,監(jiān)聽(tīng)消息并在收到消息后調(diào)用onEnter
或onExit
吃引。