quick-cocos2d-x 学习系列之十三 触摸
quick-cocos2d-x 学习系列之十三 触摸 现在智能机基本都是触摸屏,除了键盘爱好者们耍键盘。我们要通过这小小的触摸屏上完成整个游戏逻辑的控制,需要对这巴掌大地方进行详细控制了。 1.单点触摸测试创建精灵函数 function createTouchableSprite(p) local sprite = display.newScale9Sprite(p.image) sprite:setContentSize(p.size) local cs = sprite:getContentSize() local label = cc.ui.UILabel.new({ UILabelType = 2, text = p.label, color = p.labelColor}) label:align(display.CENTER) label:setPosition(cs.width / 2,label:getContentSize().height) sprite:addChild(label) sprite.label = label return sprite end 划BOX框 function drawBoundingBox(parent,target,color) local cbb = target:getCascadeBoundingBox() local left,bottom, width,height = cbb.origin.x,cbb.origin.y, cbb.size.width,cbb.size.height local points = { {left, bottom}, {left + width,bottom},bottom + height}, {left, bottom + height}, } local box = display.newPolygon(points,{borderColor = color}) parent:addChild(box,1000) end 1.1响应触摸事件调用该函数: self.sprite = createTouchableSprite({ image = "WhiteButton.png", size = cc.size(500,300), label = "TOUCH ME !", labelColor = cc.c3b(255,0,0)}) :pos(display.cx,display.cy) :addTo(self) drawBoundingBox(self, self.sprite,cc.c4f(0,1.0, 1.0)) -- 启用触摸 self.sprite:setTouchEnabled(true) self.sprite:addNodeEventListener(cc.NODE_TOUCH_EVENT,function(event) -- event.name 是触摸事件的状态:began,moved,ended,cancelled -- event.x,event.y 是触摸点当前位置 -- event.prevX,event.prevY 是触摸点之前的位置 local label = string.format("sprite: %s x,y: %0.2f,%0.2f",event.name,event.x,event.y) self.sprite.label:setString(label) -- 返回 true 表示要响应该触摸事件,并继续接收该触摸事件的状态变化 return true end) 单点触摸是最直接的使用方式了。
1.2事件穿透和事件捕获--创建底层触摸层 self.parentButton = createTouchableSprite({ image = "WhiteButton.png", size = cc.size(600,500),display.cy) :addTo(self) self.parentButton.name = "parentButton" drawBoundingBox(self,self.parentButton, 1.0)) self.parentButton:setTouchEnabled(true) --给该触摸层增加监听 self.parentButton:addNodeEventListener(cc.NODE_TOUCH_EVENT,function(event) local label = string.format("parentButton: %s x,event.y) self.parentButton.label:setString(label) return true end)
--在底层创建button1,button1 响应触摸后,会吞噬掉触摸事件 self.button1 = createTouchableSprite({ image = "GreenButton.png", size = cc.size(400,160), label = "TOUCH ME !"}) :pos(300, 400) :addTo(self.parentButton) cc.ui.UILabel.new({text = "SWALLOW = YESn事件在当前对象处理后被吞噬",size = 24}) :align(display.CENTER, 200,90) :addTo(self.button1) drawBoundingBox(self, self.button1,cc.c4f(1.0, 1.0))
self.button1:setTouchEnabled(true) self.button1:setTouchSwallowEnabled(true)-- 是否吞噬事件,默认值为 true self.button1:addNodeEventListener(cc.NODE_TOUCH_EVENT,function(event) local label = string.format("button1: %s x,event.y) self.button1.label:setString(label) return true end)
-- 在底层创建button2,响应触摸后,不会吞噬掉触摸事件 self.button2 = createTouchableSprite({ image = "PinkButton.png", 200) :addTo(self.parentButton) cc.ui.UILabel.new({text = "SWALLOW = NOn事件会传递到下层对象",90) :addTo(self.button2) drawBoundingBox(self,self.button2, 1.0)) self.button2:setTouchEnabled(true) self.button2:setTouchSwallowEnabled(false) -- 当不吞噬事件时,触摸事件会从上层对象往下层对象传递,称为“穿透” self.button2:addNodeEventListener(cc.NODE_TOUCH_EVENT,event.y) self.button2.label:setString(label) return true end)
事件穿透通过函数setTouchSwallowEnabled来实现。 如下函数设置是否捕捉触摸 self.parentButton:setTouchCaptureEnabled(button:isButtonSelected())
1.3在事件捕获阶段决定是否接受事件-- 这个标志变量用于在触摸事件捕获阶段决定是否接受事件 self.isTouchCaptureEnabled_ = true --parentButton 是 button1 的父节点 self.parentButton = createTouchableSprite({ image = "WhiteButton.png",display.cy) :addTo(self) drawBoundingBox(self, 1.0)) self.parentButton.label2 = cc.ui.UILabel.new({text = "",size = 24,color = cc.c3b(0,255)}) :align(display.CENTER, 300,60) :addTo(self.parentButton) self.parentButton:setTouchEnabled(true) self.parentButton:addNodeEventListener(cc.NODE_TOUCH_EVENT,event.y) self.parentButton.label:setString(label) printf("%s %s [TARGETING]","parentButton",event.name) if event.name == "ended" or event.name == "cancelled" then print("-----------------------------") else print("") end return true end) -- 可以动态捕获触摸事件,并在捕获触摸事件开始时决定是否接受此次事件 self.parentButton:addNodeEventListener(cc.NODE_TOUCH_CAPTURE_EVENT,function(event) if event.name == "began" then print("-----------------------------") end local label = string.format("parentButton CAPTURE: %s x,event.y) self.parentButton.label2:setString(label) printf("%s %s [CAPTURING]",event.name) if event.name == "began" or event.name == "moved" then return self.isTouchCaptureEnabled_ end end) -- button1响应触摸后,会吞噬掉触摸事件 self.button1 = createTouchableSprite({ image = "GreenButton.png", 400) :addTo(self.parentButton) cc.ui.UILabel.new({text = "SWALLOW = YESn事件在当前对象处理后被吞噬",90) :addTo(self.button1) drawBoundingBox(self,self.button1, 1.0)) self.button1:setTouchEnabled(true) self.button1:setTouchSwallowEnabled(true) -- 是否吞噬事件,默认值为 true self.button1:addNodeEventListener(cc.NODE_TOUCH_EVENT,event.y) self.button1.label:setString(label) printf("%s %s [TARGETING]","button1",event.name) if event.name == "ended" or event.name == "cancelled" then print("-----------------------------") else print("") end return true end) -- button2响应触摸后,不会吞噬掉触摸事件 self.button2 = createTouchableSprite({ image = "PinkButton.png",event.y) self.button2.label:setString(label) printf("%s %s [TARGETING]","button2",event.name) return true end) -- 即便父对象在捕获阶段阻止响应事件,但子对象仍然可以捕获到事件,只是不会触发事件 self.button2:addNodeEventListener(cc.NODE_TOUCH_CAPTURE_EVENT,function(event) printf("%s %s [CAPTURING]",event.name) return true end) -- 放置一个开关按钮在屏幕上 local labels = {} labels[true] = "父对象【可以】捕获触摸事件" labels[false] = "父对象【不能】捕获触摸事件" local images = {on = "CheckBoxButton2On.png",off = "CheckBoxButton2Off.png"} self.captureEnabledButton = cc.ui.UICheckBoxButton.new(images) :setButtonLabel(cc.ui.UILabel.new({text= labels[true],size = 24})) :setButtonLabelOffset(40,0) :setButtonSelected(true) :onButtonStateChanged(function(event) local button = event.target button:setButtonLabelString(labels[button:isButtonSelected()]) end) :onButtonClicked(function(event) local button = event.target self.isTouchCaptureEnabled_ = button:isButtonSelected() end) :pos(display.cx - 160,display.top- 80) :addTo(self) cc.ui.UILabel.new({ text = "事件处理流程:n1. 【捕获】阶段:从父到子n2. 【目标】阶段n3. 【传递】阶段:尝试传递给下层对象", size= 24}) :align(display.CENTER_TOP,display.cx,display.top - 120) :addTo(self)
其中NODE_TOUCH_EVENT和 NODE_TOUCH_CAPTURE_EVENT 表示两种事件。 在NODE_TOUCH_CAPTURE_EVENT的处理函数中返回真假,然后决定是否调用NODE_TOUCH_EVENT的处理函数。 1.4容器的触摸区域由子对象决定创建一个node,在node上增加几个精灵,精灵的局域决定的触摸的范围。
-- touchableNode 是启用触摸的 Node self.touchableNode = display.newNode() self.touchableNode:setPosition(display.cx,display.cy) self:addChild(self.touchableNode) -- 在 touchableNode 中加入一些 sprite local count = math.random(3,8) local images = {"WhiteButton.png", "BlueButton.png","GreenButton.png", "PinkButton.png"} for i = 1,count do local sprite = display.newScale9Sprite(images[math.random(1,4)]) sprite:setContentSize(cc.size(math.random(100,200),math.random(100,200))) sprite:setPosition(math.random(-200,math.random(-200,200)) self.touchableNode:addChild(sprite) end self.stateLabel = cc.ui.UILabel.new({text = ""}) self.stateLabel:align(display.CENTER,display.top - 100) self:addChild(self.stateLabel) -- 启用触摸 self.touchableNode:setTouchEnabled(true) -- 添加触摸事件处理函数 self.touchableNode:addNodeEventListener(cc.NODE_TOUCH_EVENT,function(event) local label = string.format("touchableNode: %s x,event.y) self.stateLabel:setString(label) return true end) drawBoundingBox(self, self.touchableNode, 1.0))
2.多点触摸
2.1响应触摸事件
-- createTouchableSprite() 定义在 includes/functions.lua 中 self.sprite = createTouchableSprite({ image = "WhiteButton.png",600),self.sprite, 1.0)) local labelPoints = cc.ui.UILabel.new({text = "",size = 24}) :align(display.CENTER_TOP,display.top - 120) :addTo(self) -- 启用触摸 self.sprite:setTouchEnabled(true) -- 设置触摸模式 self.sprite:setTouchMode(cc.TOUCH_MODE_ALL_AT_ONCE)-- 多点 --self.sprite:setTouchMode(cc.TOUCH_MODE_ONE_BY_ONE) -- 单点(默认模式) -- 添加触摸事件处理函数 self.sprite:addNodeEventListener(cc.NODE_TOUCH_EVENT,cancelled,added(仅限多点触摸),removed(仅限多点触摸) -- event.points 包含所有触摸点,按照 events.point[id] = {x = ?,y = ?} 的结构组织 local str = {} for id,point in pairs(event.points) do str[#str + 1] = string.format("id: %s,x: %0.2f,y: %0.2f",point.id,point.x,point.y) end local pointsCount = #str table.sort(str) labelPoints:setString(table.concat(str,"n")) if event.name == "began" or event.name == "added" then self.touchIndex = self.touchIndex + 1 for id,point in pairs(event.points) do local cursor = display.newSprite("Cursor.png") :pos(point.x,point.y) :scale(1.2) :addTo(self) self.cursors[id] = cursor end elseif event.name == "moved" then for id,point in pairs(event.points) do local cursor = self.cursors[id] local rect = self.sprite:getBoundingBox() if cc.rectContainsPoint(rect,cc.p(point.x, point.y)) then -- 检查触摸点的位置是否在矩形内 cursor:setPosition(point.x,point.y) cursor:setVisible(true) else cursor:setVisible(false) end end elseif event.name == "removed" then for id,point in pairs(event.points) do self.cursors[id]:removeSelf() self.cursors[id] = nil end else for _,cursor in pairs(self.cursors) do cursor:removeSelf() end self.cursors = {} end local label = string.format("sprite: %s,count = %d,index = %d",pointsCount,self.touchIndex) self.sprite.label:setString(label) if event.name == "ended" or event.name == "cancelled" then self.sprite.label:setString("") labelPoints:setString("") end -- 返回 true 表示要响应该触摸事件,并继续接收该触摸事件的状态变化 return true end) cc.ui.UILabel.new({ text = "注册多点触摸后,目标将收到所有触摸点的数据nadded 和 removed 指示触摸点的加入和移除", size= 24}) :align(display.CENTER,display.top - 80) :addTo(self)
2.2在事件捕获阶段决定是否接受事件-- 这个标志变量用于在触摸事件捕获阶段决定是否接受事件 self.isTouchCaptureEnabled_ = true --parentButton 是 button1 的父节点 self.parentButton = createTouchableSprite({ image = "WhiteButton.png",function(event) local label = string.format("parentButton: %s",event.name) self.parentButton.label:setString(label) printf("%s %s [TARGETING]",function(event) if event.name == "began" then print("-----------------------------") end local label = string.format("parentButton CAPTURE: %s",event.name) self.parentButton.label2:setString(label) printf("%s %s [CAPTURING]", 1.0)) self.button1:setTouchEnabled(true) self.button1:setTouchMode(cc.TOUCH_MODE_ALL_AT_ONCE)-- 多点 self.button1:setTouchSwallowEnabled(true) -- 是否吞噬事件,默认值为 true self.button1:addNodeEventListener(cc.NODE_TOUCH_EVENT,function(event) local label = string.format("button1: %s count: %d",table.nums(event.points)) self.button1.label:setString(label) printf("%s %s [TARGETING]", 1.0)) self.button2:setTouchEnabled(true) self.button2:setTouchMode(cc.TOUCH_MODE_ALL_AT_ONCE)-- 多点 self.button2:setTouchSwallowEnabled(false) -- 当不吞噬事件时,触摸事件会从上层对象往下层对象传递,称为“穿透” self.button2:addNodeEventListener(cc.NODE_TOUCH_EVENT,table.nums(event.points)) self.button2.label:setString(label) printf("%s %s [TARGETING]",display.top - 120) :addTo(self)
2.3容器的触摸区域由子对象决定-- touchableNode 是启用触摸的 Node self.touchableNode = display.newNode() self.touchableNode:setPosition(display.cx,display.top - 100) self:addChild(self.stateLabel) -- 启用触摸 self.touchableNode:setTouchEnabled(true) self.touchableNode:setTouchMode(cc.TOUCH_MODE_ALL_AT_ONCE)-- 多点 -- 添加触摸事件处理函数 self.touchableNode:addNodeEventListener(cc.NODE_TOUCH_EVENT,function(event) local str = {} for id,point.y) end self.stateLabel:setString(table.concat(str,"n")) return true end) drawBoundingBox(self,self.touchableNode, 1.0)) -- app:createNextButton(self) app:createTitle(self, "多点触摸测试 - 容器的触摸区域由子对象决定") (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |