cocos2dx-lua制作新手引导

cocos2dx-lua制作新手引导

最近在项目中负责制作新手引导,有些想法分享一下。

常见的引导类型有点击和对话(剧情),甚至有些对话(剧情)不归属新手引导的范围,但是下文介绍的时候会涉及到剧情方面。

引导的整体逻辑

我的新手引导连贯性是使用事件派发实现,cocos2dx自带的事件派发是跟Node绑定的,所以你需要去找一个lua的事件派发(当然自己写一个更好)。下面的代码中sgEventDispatcher即为我使用的事件派发工具。

新手引导肯定是跟UI层有关联的,这个无法避免所以一定要设置合理的UI节点保证你引导的位置。我这里UI是使用cocosbuilder来拼接的,lua层解析使用的Viewbase基类。在设计UI时,我会在有引导的ccb中设置一个空的Node,并且命名为ccbNodeTutorial, 然后Viewbase解析的时候,如果检测到该节点就会在该Node的”enterTransitionFinish”事件里注册监听引导的监听函数,然后在”exitTransitionStart”取消注册。

function ViewBase:registerListener() 
    if not tutorialMgr:getTutorialOpenState() then
        return
    end
    self:onNodeEvent("enterTransitionFinish", function()
        if self.ccbNodeTutorial then
            sgEventDispatcher:registerEventListener("sgeNewTutorial", self.onEventAddTutorial, self)
            self:onNodeEvent("exitTransitionStart", self.unregisterListener, self)
            sgEventDispatcher:dispatchEvent("sgeStartTutorial")
        end
    end)
end

function ViewBase:unregisterListener()
    sgEventDispatcher:remove("sgeNewTutorial", self.onEventAddTutorial, self)
end

function ViewBase:onEventAddTutorial(event)
    if not tutorialMgr:checkCanCreateTutorialView(self) then
        return
    end
    app:showSwallowLayer()
    local node = display.newNode():addTo(self)
    performWithDelay(node, function()
        tutorialMgr:processNormalTutorial(self)
    end, delayTime)
end

然后在每次新手引导完成,或者是加载一个含有可引导节点的时候,或者达到指定的条件(比如等级达到), 都会派发一个新的引导事件,有时候会收到多次派发事件,需要做好筛选。

新手引导主要考虑的问题:

  1. 新手引导中途断开怎么办?
  2. 新手引导阻止触摸怎么实现?
  3. 新手引导一连串的引导怎么实现?
  4. 新手引导如果有特殊的触发条件?
  5. 新手引导如果有特殊场景的引导?

新手引导中途断开处理

新手引导设计一般是按照一定的时间轴进行的, 策划配表的时候可以按照一步一步来配置,但是每一步引导一般属于实现某个功能引导的一部分,可以按照对所属的功能引导把引导步数进行分组。配置示例:

    [1] = {index = 1, part = 1, type = 2, finish = 1, dialog = 901, receiver = "ccb/WelcomeScene.ccbi", },
    [2] = {index = 2, part = 2, type = 1, finish = 1, receiver = "ccb/Gate.ccbi", target = "ccbNodeEnterGate", targetCallback = "onBtnEnterGate", },

然后在存档的时候只存储分组的字段,每次进入游戏都是取出该分组的第一步进行引导。但是在实际引导过程中,我们需要知道当前的具体引导索引,必须设置一个字段来记录当前的引导索引。新手引导管理类的初始化方法,self.baseInfo.curTutorialPart即为存档的引导分组,self.curIndex即为当前引导的具体索引:

function Ref:ctor()
    self.baseInfo = data.baseInfo
    self.guiding = false
    self.pause = false
    self.tutorial = tutorialApi:getTutorialInfoByPart(self.baseInfo.curTutorialPart)
    -- 判断引导是否开启
    if self.tutorial == nil then
        self.state = stateOff
    else
        self.state = stateOn
        self.curIndex = self.tutorial.index
    end
    --注册监听
    sgEventDispatcher:registerEventListener("sgeStartTutorial", self.onEventStartTutorial, self)
    sgEventDispatcher:registerEventListener("sgeEndTutorial", self.onEventEndTutorial, self)
end

当引导完成时的处理:

function Ref:onEventEndTutorial()
    self.guiding = false
    --检查引导是否完成
    if self:checkTutorialEndCondition() then
        self:processTutorialFinished()
    else
        --引导未完成重新进行该分组的引导
        self.tutorial = tutorialApi:getTutorialInfoByPart(self.baseInfo.curTutorialPart)
        self.curIndex = self.tutorial.index
        self:dispatchTutorialEvent()
    end
end

--处理引导完成
function Ref:processTutorialFinished()
    local lastTutorial = self:getCurrentTutorialInfo()
    self.curIndex = self.curIndex + 1
    if lastTutorial.finish == 1 then
        self.baseInfo.curTutorialPart = self.baseInfo.curTutorialPart + 1
    end
    if self:getCurrentTutorialInfo() ~= nil then
        self:dispatchTutorialEvent()
    else
        -- 特殊引导完成
        if lastTutorial.special == 1 then
            self.baseInfo.specialTutorial[lastTutorial.part] = 1
            self.curIndex = self.backUpIndex
            self:dispatchTutorialEvent()
        else
            self:tutorialAllFinished()
        end
    end
end

新手引导阻止触摸怎么实现?

在引导点击层中注册触摸监听事件,然后在onTouchBegan, onTouchEnded中处理

--[[
    创建一个全屏阻止触摸的层,点击在指定范围内才会响应onTouchEnded方法,调用点击的回到方法。
    self.swallow是因为有时候可能需要点击到下层,如果不需要可以去掉。
]]
function Ref:onTouchBegan(touch, event)
    local touchPoint = touch:getLocation()
    local touchPos = self:getParent():convertToNodeSpace(touchPoint)
    local swallow = self.swallow
    if not swallow then
        if cc.pGetDistance(touchPos, self.pos) > 50 then
                swallow = true
        else
            swallow = false
        end
    end
    return swallow
end

function Ref:onTouchEnded(touch, event)
    local touchPoint = touch:getLocation()
    local touchPos = self:getParent():convertToNodeSpace(touchPoint)
    if cc.pGetDistance(touchPos, self.pos) < 50 then
        self:processTutorialComplete()
    end
end

function Ref:processTutorialComplete()
    if self.callback then
        self.callback()
    end
    sgEventDispatcher:dispatchEvent("sgeEndTutorial")
    self:removeSelf()
end

新手引导一连串的引导怎么实现?

就是通过事件派发实现,但是有许多细节需要处理。比如两次引导之间如果快速点击出现问题怎么办?
我的解决方法是Node接收到合理的引导事件的时候创建一个全屏阻止触摸的layer,然后引导层出现之后移除该layer.

新手引导如果有特殊的触发条件?

local tutorialMap = 
{
    [1] = "onGuidingClick",
    [2] = "onGuidingStory",
}

-- 开始处理普通引导
function Ref:processNormalTutorial(view)
    if self:getIsGuidingTutorial() or self.pause or not self:checkTutorialStartCondition() then
        return
    end

    local tutorial = self:getCurrentTutorialInfo()
    if tutorial.voice then
        audio:preloadAudio(string.format(tutorialAudioPath,tutorial.voice))
    end

    local funcName = tutorialMap[tutorial.type]
    local callback = handler(self, self[funcName])
    local arg = callback(tutorial, view)
    self:pushTutorial(tutorial.type, arg)
end

在self:checkTutorialStartCondition()检查引导配置里配置的引导条件是否满足,比如等级,未达到等级则不能进行引导。

新手引导如果有特殊场景的引导?

这个也可以理解为正常引导流程以外的引导。依然走的是正常引导的流程,不过需要把之前的引导进度保存起来,特殊引导走完之后再恢复回来。因为修改的是内存中self.curIndex的值,所以不需要考虑特殊引导进行中游戏中断的情况。

-- 开始处理特殊引导
function Ref:processSpecialTutorial(view, type)
    if self.baseInfo.specialTutorial[type] ~= nil then
        return
    end
    self.backUpIndex = self.curIndex
    local specialTutorial = tutorialApi:getTutorialInfoByPart(type)
    self.curIndex = specialTutorial.index
    self.tutorial = self:getCurrentTutorialInfo()
    self.pause = false
    self:processNormalTutorial(view)
end
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值