Quick-cocos2dx可拖动面板的实现方式

有的手游项目(比如传奇)有DIY界面的特色(面板可拖动,面板和技能快捷键可以自定义是否放在主界面上),本文意在介绍其在Quick-cocos2dx的实现方式.

案例需求:主界面上加2个按钮,按钮打开对应的面板,面板初始位置在屏幕中央,后打开的面板放在上方,当面板已经打开时点快捷按钮关闭面板。面板可拖动,被点击的面板置于所有已打开面板的上方。

效果图:

主界面文件:

--主界面文件:MainScene.lua
local currentModule = ...
local panelDelagate = import(".main.panels.delegate",currentModule)

local MainScene = class("MainScene", function()
    return display.newScene("MainScene")
end)

table.merge(MainScene,{
    z = {
        focus = 1,
    },
    lastFocus = nil,--保存上次点击的面板,用来切换ZOrder,注意当上次点击的面板删除时,这里要赋为nil
})

function MainScene:ctor()
    --初始化
    self.panels = {}--保持所有打开面板的表
--    cc.ui.UILabel.new({UILabelType = 2, text = "Hello, World", size = 64})
--        :align(display.CENTER, display.cx, display.cy)
--        :addTo(self)
    --背景
    local bg = display.newSprite("bg0822.png", 480, 320, nil):addTo(self)
    --按钮1
    local function toggleVIPPanelCB()
        self:togglePanel("vip")
    end
    cc.ui.UIPushButton.new({ normal = "vip.png", pressed = "vip.png" }):onButtonClicked(toggleVIPPanelCB):pos(900, 600):addTo(bg)
    --按钮2
    local function togglPicIdentifyPanelCB()
        self:togglePanel("picIdentify")
    end
    cc.ui.UIPushButton.new({ normal = "picIdentify.png", pressed = "picIdentify.png" }):onButtonClicked(togglPicIdentifyPanelCB):pos(800, 600):addTo(bg)
end         

function MainScene:showPanel(_panelName)
    --注意import放在函数中第二个参数需要加上...,表示当前模块位置
    local panel = import(".main.panels.".._panelName,currentModule).new():addTo(self,self.z.focus)--这里新创建的panel设置ZOrder为1,实现新创建的面板在最上方的效果
    self.panels[_panelName] = panel --将打开的面板放入表中
    panelDelagate.extend(panel,_panelName,self)--使面板支持拖动,以及点击时不同面板间ZOrder切换
    return panel
end

function MainScene:hidePanel(_panelName)
    --注意如果本次关闭的面板就是上次单击的面板,这里lastFocus需要赋为nil,不然拖动的时候会报错
    if self.lastFocus == self.panels[_panelName] then
        self.lastFocus = nil
    end
    if self.panels[_panelName] then
        self.panels[_panelName]:removeSelf()
        self.panels[_panelName] = nil --在表中移除面板
    end
end

function MainScene:togglePanel(_panelName)
    if self.panels[_panelName] then --根据存储面板表中表该面板是否存在,判断显示还是隐藏该面板
        self:hidePanel(_panelName)
    else
        self:showPanel(_panelName)
    end
end

return MainScene

面板文件:

--vip.lua
local vip = class("vip",function() return display.newNode() end)

function vip:ctor()
    self._supportMove = true
    --创建背景加到节点容器上,为了使背景和容器左下角重合设置背景锚点为0
    local bg = display.newSprite("black_2.png", 0, 0, nil):addTo(self):setAnchorPoint(0,0)
    --设置容器大小和背景一样(为了拖动面板),并将容器放到屏幕中央位置
    self:setContentSize(bg:getContentSize()):setAnchorPoint(0.5,0.5):pos(display.cx,display.cy)
    --背景内图片
    display.newSprite("panelVIP.png", bg:getContentSize().width/2, bg:getContentSize().height/2, nil):addTo(bg)
end

return vip

支持面板拖动文件:

local panelDelegate = {}

function panelDelegate.extend(target,name,parent)
    function target:supportPanelMoveable(rect, name)
        local panelOriginalPos = {}--触摸时面板坐标
        local beganTouchPos = {}--触摸时坐标
        target:setTouchEnabled(true)
        target:addNodeEventListener(cc.NODE_TOUCH_EVENT,function(event)
            if event.name == "began" then
                --上个面板ZOrder降低为0
                if parent.lastFocus then
                    parent.lastFocus:setLocalZOrder(0)
                end               
                --本次触摸的面板ZOrder置为为1
                target:setLocalZOrder(parent.z.focus)
                --保留本次触摸面板供下次使用
                parent.lastFocus = target
                --要支持拖动面板的_supportMove需要为true
                if target._supportMove then
                   panelOriginalPos = cc.p(target:getPosition())
                   beganTouchPos = cc.p(event.x,event.y)
                end
                return true
            elseif event.name == "moved" then
                --面板移动后坐标计算方式:面板在触摸按下时坐标 + (触摸当前坐标 - 触摸按下时坐标)
                if target._supportMove then
                    target:pos(panelOriginalPos.x + (event.x - beganTouchPos.x), panelOriginalPos.y + (event.y - beganTouchPos.y))
                end
            end
        end)

    end

    local rect = target._mainRect or cc.rect(0,0,target:getContentSize().width,target:getContentSize().height)
    target:supportPanelMoveable(rect,"main")
    return target
end

return panelDelegate

实现需求的3个文件都已附上详细的代码和注释,照着做一遍实验就可以完成了。

另外panelDelegate.extend函数内也可以通过创建Node设置为panel的大小,来作为遮罩后添加事件处理来实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ellis1970

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值