本篇博客添加数据和声音,先来完成声音的添加,同样需要将对声音的处理单独的写在一个模块中,留下接口函数给外部调用,我们新建一个lua文件专门来处理声音。

SoundDeal = {audioEngine = cc.SimpleAudioEngine:getInstance()}

EffectType = {
    Crash = "sound/crash.mp3",
    Newhigh = "sound/newhigh.mp3",
    Yes = "sound/point.mp3",
    Start = "sound/start.mp3",
    Tap = "sound/tap.mp3"
}

function SoundDeal:playBg()
    self.audioEngine:playMusic("sound/bg.mp3",true)
    self.audioEngine:setMusicVolume(1)
end

function SoundDeal:stopBg()
    self.audioEngine:stopMusic()
end

function SoundDeal:preloadEffect()
    self.audioEngine:preloadEffect(EffectType.Crash)
    self.audioEngine:preloadEffect(EffectType.Newhigh)
    self.audioEngine:preloadEffect(EffectType.Yes)
    self.audioEngine:preloadEffect(EffectType.Start)
    self.audioEngine:preloadEffect(EffectType.Tap)
    self.audioEngine:setEffectsVolume(1)
end

function SoundDeal:playEffect(type)
    self.audioEngine:playEffect(type)
end

上边的这个模块和我们之前写的模块不太一样,SoundDeal没有local的声明,说明是一个全局的变量,全局的含义就是说只要执行了这个SoundDeal.lua文件,那么在程序的其他地方就可以使用SoundDeal这个全局变量,执行SoundDeal.lua文件的过程就涉及到把全局变量放到全局表中,这样大家都可以找到。所以在模块文件的最后我们也没有使用return语句返回这个变量,因为不需要,全局都可以使用。EffectType同样是全局的,这个表中定义了声音的类型对应于声音的路径,然后留下了几个接口函数,preloadEffect函数在程序一开始就调用,用来加载音效,playBg同样也是开始调用,用来播放背景音乐,调用playEffect的时候需要传入一个音效的类型,在你需要的地方播放对应的音效,这里只列出声音文件的实现,至于在甚么地方调用逻辑很清楚了吧。以播放背景音乐为例,首先在FlashScene中引入模块,然后在create函数中调用。俩处代码如下。

--使用require引入模块
require("Cocos2d")
require("Cocos2dConstants")
require("SoundDeal")

-create留下给外部调用的接口
function FlashScene:create()
    --new函数的作用是调用了构造函数ctor,然后将表FlashScene的所有元素复制到了一张新的表中,最后返回这张表
    local flashScene = FlashScene:new()
    local layer = flashScene:createLayer()
    flashScene:addChild(layer)

    --加载音效
    SoundDeal:preloadEffect()
    --播放背景声音
    SoundDeal:playBg()

    return flashScene
end

这样的话声音的处理就完成了,感觉lua是不是很方便啊,比c++省很多的内容,一个小模块就能搞定。接下来处理数据,代码中有一个变量rate是用来控制小车的运动速度的,我们将这个变量以及分数和其他的一些变量单独放到一个模块中,这样便于处理,同样留一些给外部调用的接口。

require("SoundDeal")

GlobalData = {
    rate = math.pi*cc.Director:getInstance():getWinSize().height*0.2,
    score = 0,
    hightScore = cc.UserDefault:getInstance():getIntegerForKey("hightScore",0),
}

--重置数据
function GlobalData:reset()
    self.rate = math.pi*cc.Director:getInstance():getWinSize().height*0.2
    self.score = 0
    self.hightScore = cc.UserDefault:getInstance():getIntegerForKey("hightScore")
end

--设置分数和速率
function GlobalData:setScore()
    self.score = self.score+1
    if self.score > self.hightScore then
        self.hightScore = self.score
        cc.UserDefault:getInstance():setIntegerForKey("hightScore",self.score)
        SoundDeal:playEffect(EffectType.Newhigh)
    else
        SoundDeal:playEffect(EffectType.Yes)
    end

    local score = self.score
    if score > 5 then
        self.rate = math.pi*cc.Director:getInstance():getWinSize().height*0.25
    end
    if score > 10 then
        self.rate = math.pi*cc.Director:getInstance():getWinSize().height*0.3
    end
    if score > 20 then
        self.rate = math.pi*cc.Director:getInstance():getWinSize().height*0.4
    end
    if score > 30 then
        self.rate = math.pi*cc.Director:getInstance():getWinSize().height*0.5
    end
    if score > 50 then
        self.rate = math.pi*cc.Director:getInstance():getWinSize().height*0.6
    end
end

重置数据在游戏结束的时候调用,而设置分数和速率在俩辆小车错开的时候调用。这样的话声音和数据处理的代码也完成了,调用的地方相信不用我说了。既然添加了分数,我们就来做一个分数的UI,显示现在玩家的得分情况。

function MainGameScene:createLayer()
    local layer = cc.Layer:create()

    --添加背景图片
    self:addBg(layer)

    --运行游戏主逻辑
    self:mainLogic(layer)

    --实现与用户的交互
    self:userInteraction(layer)

    --ui
    self:setUI(layer)

    return layer
end

--设置UI,比如分数
function MainGameScene:setUI(layer)
    self.score = cc.Label:createWithBMFont("fonts/number.fnt","0")
    self.score:setPosition(cc.p(self.size.width/2,self.size.height/2))
    layer:addChild(self.score)
end

当小车相错而过的时候设置score的string就可以了,游戏结束的时候重置UI的显示。代码的添加在collision和gameOver函数中。这样的话一个简单的小游戏主逻辑就大体完成了,大家可以根据自己的爱好添加不同的东西,自由发挥吧!下篇博客为我们的游戏接入第三方库——微信分享。

Lua小游戏别撞车——声音和数据的处理