Cocos2d-x Lua运行流程

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。

Cocos2d-x Lua运行流程_第1张图片
Cocos2d-lua
Cocos2d-x Lua运行流程_第2张图片
Cocos2d-lua

主入口文件 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
  • 调用对应classCreate()方法创建对象,并执行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

  • DEBUG
    设置输出调试信息选项,即通过控制不同的print()输出信息。
    0 表示关闭
    1 表示打印少量调试信息
    2 表示打印标准完整的调试信息
  • CC_USE_FRAMEWORK
    设置是否使用quick框架,其中包括MVC框架。
  • CC_SHOW_FPS
    设置是否显示FPS等显卡信息
  • CC_DISABLE_GLOBAL
    设置是否允许定义全局字段
  • CC_DESIGN_RESOLUTION
    设置不同分辨率

默认应用 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文件,AppBaseQuick框架自带的一个MVC的应用程序基础类,此类为应用程序提供一些逻辑控制上的功能,如进入场景、切换场景等。
  • class()方法本身是Quick框架定义的用于创建自定义lua类的函数,function class(classname, super)函数参数classname表示类名,super表示父类或创建对象实例的函数。

MVC

MVC是一种组合设计模式,被广泛应用在带有图形交互的用户界面程序(GUI)开发中。MVC的宗旨在于分离关注点(SoC),将界面表现和业务逻辑分离。SoC原则在现代软件工程中是一个非常重要的设计理念。对于实际问题,要划分不同的关注点,且关注点之间必须隔离开来,这样才能达到 更好的代码重用,以获得鲁棒性、可适配性、可维护性。

Cocos2d-x Lua运行流程_第3张图片
MVC

Cocos2d本身并不是基于MVC的理念设计的,在Cocos2d中CCSceneCCLayerCCSprite等类都是CCNode的子类,开发流程基本是这样的:

  1. 通过应用程序代理类来初始化第一个即主场景
  2. 场景中实例化一个或多个布景图层,并将其添加进去。
  3. 布景图层中实例化一个或多个精灵,并将其添加进去。
  4. 场景处理用户输入,例如Touch事件和加速计的改变。同时更新布景图层和精灵,让精灵运行一个或多个动作等。
  5. 场景中运行一个游戏循环(一般是1/60更新一次),然后布景图层和精灵在游戏循环中做更新和游戏逻辑。

对于手游而言,界面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 提供程序退出接口
  • 提供创建 sceneview 的接口,并约定其存放路径。

垃圾收集

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个即结束游戏。

Cocos2d-x Lua运行流程_第4张图片
杀虫游戏
Cocos2d-x Lua运行流程_第5张图片
组织结构

布景层生命周期

生命周期顺序流程

  1. init() 初始化布景层调用,在类初始化时,仅会调用一次。
  2. onEnter() 进入布景层时调用,可能会发生多次。

Cocos2dx类似于ObjectC一样,有两种方式来申请内存创建对象,一种是静态函数create(),一种是在自身的init()中,在这两种函数中申请内存创建对象能让程序正常运行,但是当对象将要去展现或被添加到另一个容器时,它会调用onEnter()函数,所以最好不要在onEnter()中做内存方面的操作。

  1. onEnterTransitionDidFinish() 进入布景层且过渡动画结束时调用
  2. onExit() 退出布景层时调用
  3. onExitTransitionDidStart() 退出布景层且开始过渡动画时调用
  4. clearup() 布景层对象被清除时调用,整个布景层销毁时调用。

简单来说

  • 进入布景层时:init()->onEnter()->onEnterTransitionDidFinish()
  • 退出布景层时:onExit()->onExitTransitionDidStart()->init()

onEnteronExit在Lua中不会因为节点的addremove而直接被调用, 当子节点被父节点的addremove时,会发送enterexit的消息,所以需要初始化节点的时候,监听消息并在收到消息后调用onEnteronExit

你可能感兴趣的:(Cocos2d-x Lua运行流程)