有的手游项目(比如传奇)有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的大小,来作为遮罩后添加事件处理来实现