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 = YES\n事件在当前对象处理后被吞噬",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 = NO\n事件会传递到下层对象",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 = YES\n事件在当前对象处理后被吞噬",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, "多点触摸测试 - 容器的触摸区域由子对象决定")

quick-cocos2d-x 学习系列之十三 触摸的更多相关文章

  1. 详解使用postMessage解决iframe跨域通信问题

    这篇文章主要介绍了详解使用postMessage解决iframe跨域通信问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  2. HTML5数字输入仅接受整数的实现代码

    这篇文章主要介绍了HTML5数字输入仅接受整数的实现代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码

    这篇文章主要介绍了HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  4. 浅谈html5之sse服务器发送事件EventSource介绍

    本篇文章主要介绍了浅谈html5之sse服务器发送事件EventSource介绍,具有一定的参考价值,有兴趣的可以了解一下

  5. HTML5 拖放(Drag 和 Drop)详解与实例代码

    本篇文章主要介绍了HTML5 拖放(Drag 和 Drop)详解与实例代码,具有一定的参考价值,有兴趣的可以了解一下

  6. 移动端html5模拟长按事件的实现方法

    这篇文章主要介绍了移动端html5模拟长按事件的实现方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  7. ios – 在applicationWillEnterForeground触发时更改UIView

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  8. ios – Swift中的非响应流委托

    所以我在Swift中使用套接字并试图将应用程序与我的服务器连接起来.我让应用程序连接到服务器的IP地址,并在服务器上使用netcat进行测试.在执行期间,应用程序的控制台输出显示它已成功连接到服务器.但是,流委托似乎没有响应.当我输入netcat时,app控制台没有打印任何内容.我已经搜索了很长一段时间,发现我的实现与其他实现非常相似.也许我在这里遗漏了一些我看不到的东西.任何想到这个问题的人都将不胜感激!

  9. ios – UIScrollView内容不允许用户交互

    我有一个启用了分页的UIScrollView,如下所示:在UIScrollView中,我添加了几个UIWebViews,并将其启用的交互设置为是这样的.它打破了UIScrollView上的分页和所有触摸.如果我将用户交互设置为NO,则页面有效,但我无法在UIWebView中突出显示文本.我试着像下面那样对UIScrollView进行子类化,但是会出现同样的情况.任何的想法?

  10. ios – UIScrollView中的UIControll未接收到触摸事件

    我在我的项目中使用SevenSwitch.我需要将它添加到UIScrollView中,但是当我将它添加到滚动视图中时,控件似乎无法接收触摸事件.我尝试了子类滚动视图并覆盖下面的代码:还补充说:但仍然无法接收触摸事件.如何阻止scrollview阻止UIControl接收触摸?

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部