1. 程式人生 > >cocos2dx LUA使用ClippingNode來製作新手引導

cocos2dx LUA使用ClippingNode來製作新手引導

新手教程是遊戲開發必須的一部分,cocos2dx中也為我們提供了節點裁剪的類ClippingNode,在實際使用中還是有點麻煩,所以我自己包裝了個類。我是基於cocos2dx 3.3 的lua框架,其他版本的cocos2dx應該也差不多,思想一樣。具體實現如下:

-- 新手引導的類
local GuideClipLayer = class("GuideClipLayer",function()
return cc.Layer:create()
end)

GuideCilpLayer這個就是專門的切圖層,在使用時加到你遊戲介面的最上層。

GuideClipLayer.__index = GuideClipLayer --用於訪問  
  
-------------------------------------------------------------  
GuideClipLayer._visibleSize = nil -- 螢幕大小size  
GuideClipLayer._origin      = nil -- 原點  
GuideClipLayer._nodef      = nil -- 模板(可以響應觸控事件)  
GuideClipLayer._cutSprites	= {}-- 挖掉的那個圖(可以響應觸控事件)  
GuideClipLayer._cutNotListenSprites	= {} -- 挖掉的那個圖(不可以響應觸控事件)  
GuideClipLayer._enableClick	= false -- 響應點選事件
  
function GuideClipLayer:create(ResPaths,strKeys,needlisten,NotListenResPaths,strNotListenKeys) 
	if needlisten == nil then 
		needlisten = true
	end
    local layer = GuideClipLayer.new()  
    layer:ctor()  
    layer:addChild(layer:createClip(ResPaths,strKeys,NotListenResPaths,strNotListenKeys),1)  
	layer:addChild(layer:createistenLayer())  
    layer._enableClick = needlisten
    return layer  
end  
  
function GuideClipLayer:ctor()  

    self._nodef      = nil  
    self._cutSprites	= {} 
    self._cutNotListenSprites	= {}
    self._enableClick	= false 

    self._visibleSize = cc.Director:getInstance():getVisibleSize()  
    self._origin = cc.Director:getInstance():getVisibleOrigin()  
end  
  
function GuideClipLayer:createClip(ResPaths, strKeys,NotListenResPaths,strNotListenKeys)  
    local clip = cc.ClippingNode:create()--建立裁剪節點    
    clip:setInverted(true)--設定底板可見    
    clip:setAlphaThreshold(0.0)--設定透明度Alpha值為0    
  
    local layerColor = cc.LayerColor:create(cc.c4b(0,0,0,150))  
      
    clip:addChild(layerColor,8)-- 在裁剪節點新增一個灰色的透明層    
  
    -- 建立模板,也就是你要在裁剪節點上挖出來的那個”洞“是什麼形狀的 
    self._nodef = cc.Node:create()-- 建立模版      
	--響應點選事件挖孔
	for i = 1,#strKeys do 
		local nodeSprite= BUI:findNode(strKeys[i])	
		if nodeSprite == nil then 
			return
		end
		if ResPaths[i] == nil then 
			print("裁剪節點跟資源個數不對應")
		else
			self._cutSprites[i] = cc.Sprite:create(ResPaths[i]) -- 這裡使用的那個圖示 
			local Pos = cc.p(nodeSprite:getParent():convertToWorldSpace(cc.p(nodeSprite:getPosition())))
			self._cutSprites[i]:setPosition(Pos) -- 設定座標位置   
			self._nodef:addChild(self._cutSprites[i])-- 在模版上新增精靈  
		end
	end	
	
	if NotListenResPaths and strNotListenKeys then 
		for i = 1,#strNotListenKeys do 
			local nodeSprite= BUI:findNode(strNotListenKeys[i])	
			if nodeSprite == nil then 
				return
			end
			if NotListenResPaths[i] == nil then 
				print("不響應觸控事件裁剪節點跟資源個數不對應")
			else
				self._cutNotListenSprites[i] = cc.Sprite:create(NotListenResPaths[i]) -- 這裡使用的那個圖示 
				local Pos = cc.p(nodeSprite:getParent():convertToWorldSpace(cc.p(nodeSprite:getPosition())))
				self._cutNotListenSprites[i]:setPosition(Pos) -- 設定座標位置  
				self._nodef:addChild(self._cutNotListenSprites[i])-- 在模版上新增精靈  
			end
		end
	end
	local Pos = cc.p(0,0)
    self._nodef:setPosition(Pos) -- 設定的座標的座標位置上    
    clip:setStencil(self._nodef)-- 設定模版     

    return clip  
end 

--按鍵監聽
function GuideClipLayer:createistenLayer()  
	local listen_layer = cc.Layer:create()
	-- 註冊單點觸控
    local dispatcher = cc.Director:getInstance():getEventDispatcher()
    local listener = cc.EventListenerTouchOneByOne:create()--建立一個觸控監聽(單點觸控)  
	
	 -- 觸控開始
	local function onTouchBegan(touch, event)
		if not self._enableClick then 
			listener:setSwallowTouches(true)
			return true			
		end
		local pos = touch:getLocation() -- 獲取觸點的位置
        local posnodef = cc.p(self._nodef:getPosition())
		
		local enableSwTc = false
		for i=1 , #self._cutSprites do 
			local rect = self._cutSprites[i]:getBoundingBox()
			rect= {y = rect.y+posnodef.y, x = rect.x + posnodef.x, height = rect.height, width=rect.width}
			if cc.rectContainsPoint(rect,pos) then   
				enableSwTc = true
			end
		end
		
		if enableSwTc then   
			listener:setSwallowTouches(false)  -- 如果觸點處於rect中 則事件向下透傳 
		else  
			listener:setSwallowTouches(true)  
		end
		
		return true                     -- 必須返回true 後邊move end才會被處理
	end
		
	-- 觸控移動
	local function onTouchMoved(touch, event)
		-- print("Touch Moved")
	end

	-- 觸控結束
	local function onTouchEnded(touch, event)
		-- print("Touch Ended")
	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)

    dispatcher:addEventListenerWithSceneGraphPriority(listener, listen_layer)-- 將listener和listen_layer繫結,放入事件委託中  

    return listen_layer
	
end 

在使用中直接呼叫

ChipNode = bf.GuideClipLayer:create(ResPaths,strKeys,needlisten,NotListenResPaths,strNotListenKeys)
if ChipNode then
GameGuideChipLayer:addChild(ChipNode)
end

建立黑色覆蓋層.

實際使用中需配合cocos studio。

  1. ResPaths;要挖空的圖資源路徑(圖只要形狀)
  2. strKeys;cocos studio中確定位置用的節點關鍵字。
  3. needlisten;根據strKeys位置挖空的地方是否支援觸控響應。
  4. NotListenResPaths,strNotListenKeys;同1,2一樣,只是根據這個形狀圖挖空的地方不支援觸控響應。

效果圖如下:

20161102181450

圖中只有“牛牛”按鈕能響應觸控事件,其餘的切割部分不響應。