简易新手引导

来源:互联网 发布:淘宝 发送会员卡 编辑:程序博客网 时间:2024/05/17 03:48

前面介绍了ClippingNode的简单使用,补充说明setAlphaThreshold方法设定alpha阈值,只有模板(stencil)中像素的alpha值大于alpha阈值时,内容才会被绘制。默认为1,当为1时,模板全部绘制。若不是1,表示只绘制模板中alpha像素大于阈值的内容。
所以这里写图片描述当setAlphaThreshold(1.0f)时,stencil全部绘制(红框内的全部),setInverted(false)显示被模板裁剪下来的底板内容是一个右图大小的草地图片这里写图片描述,setInverted(true)显示剩余部分这里写图片描述

结合之前用到的屏蔽触摸的层,做一个简易的新手引导。
首先在MainScene中添加了2个Button

function MainScene:createUI()    local _size = cc.Director:getInstance():getWinSize()    local function btnClicked(sender,_type)        print('--btn click--')    end    local btn = ccui.Button:create('res/DS07.png','res/DS08.png','res/DS09.png')    self:addChild(btn)    btn:setPosition(_size.width/3,_size.height/3)    btn:addTouchEventListener(btnClicked)    local function btnClicked2(sender,_type)        print('--btn2 click--')    end    local btn2 = ccui.Button:create('res/DS10.png','res/DS11.png','res/DS12.png')    self:addChild(btn2)    btn2:setPosition(_size.width/3,_size.height/4.5)    btn2:addTouchEventListener(btnClicked2)end

运行->这里写图片描述

在新手引导时,需要玩家去点击Auto按钮,其他可以互动的控件全部不能响应,而且需要在视觉上将Auto按钮所在地方点亮,其他地方蒙蔽,那么可以结合之前的ClippingNode和屏蔽触摸层来实现。
新建一个Lua文件,代码:

local GuideShade = class('GuideShade',function () return cc.Node:create() end)function GuideShade:ctor(x,y)    self.x = x    self.y = y    self:createUI()    self:openTouch()endfunction GuideShade:createUI()    local stencil = cc.Sprite:create('res/mask.png')    self.r = stencil:getContentSize().width / 2     local clipping = cc.ClippingNode:create(stencil)    clipping:setInverted(true)    clipping:setAlphaThreshold(0.3)    self:addChild(clipping,-1)    clipping:setPosition(self.x,self.y)     local pb = require("app/views/Pingbilayer").new()    clipping:addChild(pb)    pb:setPosition(-self.x,-self.y)endfunction GuideShade:checkPointInCircle(c_x,c_y)    local d_x = math.abs(c_x - self.x)    local d_y = math.abs(c_y - self.y)    local distance = math.pow(d_x,2) + math.pow(d_y,2)    if math.sqrt(distance) < self.r then        return true    end    return falseendfunction GuideShade:openTouch()    local listener = cc.EventListenerTouchOneByOne:create()    local contain = false    local function onTouchBegan( touch,event )        local pos = touch:getLocation()        if self:checkPointInCircle(pos.x,pos.y) then            contain = true        else            contain = false        end        return true      end    local function onTouchMoved( touch,event )    end    local function onTouchEnded( touch,event )        local pos = touch:getLocation()        if contain and self:checkPointInCircle(pos.x,pos.y) then            print('--in circle--')        end    end    listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN)    listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED)    listener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED)    self:getEventDispatcher():addEventListenerWithSceneGraphPriority(listener,self)    local function onNodeEvent(event)        if event == 'exit' then            self:getEventDispatcher():removeEventListener(listener)        end         end    self:registerScriptHandler(onNodeEvent)endreturn GuideShade

在createUI方法中用到的模板:这里写图片描述,所以点亮的地方是一个圆形,参数x,y为这个圆在世界坐标系中的位置。剪裁节点添加了屏蔽触摸的层,那么在GuideShade这个Node之下的控件将无法监听到触摸事件。

将GuideShade添加到MainScene中

function MainScene:onEnter()    local _size = cc.Director:getInstance():getWinSize()    local sp=cc.Sprite:create('res/HelloWorld.png')    self:addChild(sp)    sp:setPosition(_size.width/2,_size.height/2)    self:createUI()    self:openTouch()    self:guide(_size)endfunction MainScene:guide(_size)    local guideLayer = require('app/views/GuideShade').new(_size.width/3,_size.height/3)    self:addChild(guideLayer)end

这里写图片描述
由于屏蔽了触摸,2个按钮都不能点击,function GuideShade:checkPointInCircle(c_x,c_y)判断了点击点是否在圆内,只有当触摸开始的点在圆内以及结束点也在圆内时,输出了–in circle–。

现在视觉上除了Auto按钮上方的圆点亮之外,其他地方都蒙灰了,且点击圆之外的地方,都没有反应(屏蔽层有反应),但是点击圆内的位置也没有反应,所以需要在引导时将要引导的数据传递过来,在点击圆内时响应原本Auto按钮的事件。
下面是MainScene中添加了模拟数据后的完整代码:

local MainScene = class("MainScene", cc.load("mvc").ViewBase)local _data = {['1'] = {normal = nil,pressed = nil,disabled = nil,event = nil,name = nil},               ['2'] = {normal = nil,pressed = nil,disabled = nil,event = nil,name = nil}}function MainScene:ctor()    self:enableNodeEvents()endfunction MainScene:onEnter()    local _size = cc.Director:getInstance():getWinSize()    local sp=cc.Sprite:create('res/HelloWorld.png')    self:addChild(sp)    sp:setPosition(_size.width/2,_size.height/2)    self:createUI()    self:openTouch()    self:guide(_size)endfunction MainScene:createUI()    local _size = cc.Director:getInstance():getWinSize()    local function btnClicked(sender,_type)        print('--btn click--')    end    local btn = ccui.Button:create('res/DS07.png','res/DS08.png','res/DS09.png')    self:addChild(btn)    btn:setPosition(_size.width/3,_size.height/3)    btn:addTouchEventListener(btnClicked)    local function btnClicked2(sender,_type)        print('--btn2 click--')    end    local btn2 = ccui.Button:create('res/DS10.png','res/DS11.png','res/DS12.png')    self:addChild(btn2)    btn2:setPosition(_size.width/3,_size.height/4.5)    btn2:addTouchEventListener(btnClicked2)    _data['1'].normal = 'res/DS07.png'    _data['1'].pressed = 'res/DS08.png'    _data['1'].disabled = 'res/DS09.png'    _data['1'].event = btnClicked    _data['2'].normal = 'res/DS10.png'    _data['2'].pressed = 'res/DS11.png'    _data['2'].disabled = 'res/DS12.png'    _data['2'].event = btnClicked2endfunction MainScene:openTouch()    local listener = cc.EventListenerTouchOneByOne:create()    local function onTouchBegan( touch,event )        print("--touchBegan--")        return true      end    local function onTouchMoved( touch,event )        print("--touchMoved--")    end    local function onTouchEnded( touch,event )        print("--touchEnded--")    end    listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN)    listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED)    listener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED)    self:getEventDispatcher():addEventListenerWithSceneGraphPriority(listener,self)    local function onNodeEvent(event)        if event == 'exit' then            self:getEventDispatcher():removeEventListener(listener)        end         end    self:registerScriptHandler(onNodeEvent)endfunction MainScene:guide(_size)    local guideLayer = require('app/views/GuideShade').new(_size.width/3,_size.height/3,_data)    self:addChild(guideLayer)endreturn MainScene

_data中保存了2个按钮的数据,那么在创建GuideShade时传入这个数据,在开始结束都点在圆内时响应按钮的事件。

    local function onTouchEnded( touch,event )        local pos = touch:getLocation()        if contain and self:checkPointInCircle(pos.x,pos.y) then            print('--in circle--')            local func = self._data['1'].event            if func then                func()            end        end    end

点圆可以看到这里写图片描述
输出了–btn click–,原来点击Auto会输出2个–btn click–是因为,在回调函数中没有对事件进行判断,在点击到按钮的began和ended时都调用了回调函数,所以输出有2个,如果点到按钮之后moved会输出更多。而且回调函数有2个参数。在点击圆之后只是调用了这个回调函数,只输出了一次,并且没有2个参数,无法获得按钮以及事件,sender参数是可以通过_data记录并在调用回调函数时使用,在_data中添加一个sender,

local _data = {['1'] = {normal = nil,pressed = nil,disabled = nil,event = nil,name = nil,sender = nil},               ['2'] = {normal = nil,pressed = nil,disabled = nil,event = nil,name = nil,sender = nil}}_data['1'].sender = btnprint('--in circle--')local func = self._data['1'].eventlocal sender = self._data['1'].senderif func then    func(sender)end

这里用的是一个圆形的模板,那么就有一个体验不好的地方,如果点击的点在圆内,但是在按钮外边,仍然能响应事件,这里需要做优化。另外,原本点击按钮时,有按钮的点击效果,现在没有这个按下去的效果,因为根本不是真正的点中了按钮,不过在_data中记录有这个按钮的资源,可以再创建一个按钮摆放在那个位置。
如果_data中记录有按钮本身,那么可以有个更好的办法,在GuideShade中,

function GuideShade:createUI()    local stencil = cc.Sprite:create('res/mask.png')    self.r = stencil:getContentSize().width / 2     local clipping = cc.ClippingNode:create(stencil)    clipping:setInverted(true)    clipping:setAlphaThreshold(0.3)    self:addChild(clipping,-1)    clipping:setPosition(self.x,self.y)     local pb = require("app/views/Pingbilayer").new()    clipping:addChild(pb)    pb:setPosition(-self.x,-self.y)    local sender = self._data['1'].sender    local btn = sender:clone()    self:addChild(btn)    btn:setPosition(self.x,self.y)end

createUI方法中直接clone了按钮并摆放在原本按钮上方,这个clone出的按钮和原来的按钮用同一个回调函数,并且2个参数都能获取
这里写图片描述
这里写图片描述
这样不仅有按钮的点击效果,有按下去的感觉,而且在回调函数中能获取按钮和事件2个参数。不过这样也有一个缺点,就是看起来整个按钮都在圆形的上方,视觉效果不好。在实际开发中,还需要根据需求选择合适的方案。

0 0