cocos2dx游戏引擎的重点是在于移动设备的跨平台开发,而移动设备上的游戏大部分都是通过屏幕触碰来进行的。比如主菜单的按钮触碰,打飞机中飞机的触碰移动,都需要用到触碰操作。想一想之前讲的菜单按钮CCMenu,菜单项的点击响应事件,其实就是触碰。

cocos2dx引擎中实现触碰的类CCTouchDelegate。而CCLayer类默认继承了CCTouchDelegate接口,所以CCLayer的子类无须再重新使用这些接口,这样就很方便地为我们提供了触摸操作相关的操作。

触碰事件主要分为两类:单点触碰 和 多点触碰

【本节内容】

一、单点触碰TargetedDelegate、以及参数CCTouch类。

二、多点触碰StandardDelegate、以及参数CCSet类。

三、两类触碰的区别。


【单点触碰】

单点触碰TargetedDelegate,顾名思义,就是只接受一个点的触摸响应事件。

在使用触碰之前,必须要先注册触碰委托。单点触碰的注册委托函数为addTargetedDelegate

1、开启单点触碰事件addTargetedDelegate

写在onEnter()中。

//
/**
* 开启单点触碰TargetedDelegate
* 注册触碰:addTargetedDelegate("触碰事件委托的对象","优先级","是否拦截触屏事件");
* 优先级的值越小,就越高越早被响应。
* 当第3个参数为true时,表示对本次触屏事件进行拦截,也就是说当触屏事件响应了本次触屏委托后,将不会再继续响应其他触碰委托。
*/
void HelloWorld::onEnter()
{
//注册触碰响应事件
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,false);
CCLayer::onEnter();//一定不要忘了调用父类的onEnter
}
//

2、关闭单点触碰事件removeDelegate

写在onExit()中。

//
/**
* 关闭单点触碰TargetedDelegate
* 注销触碰:removeDelegate("注销触碰事件委托的对象");
*/
void HelloWorld::onExit()
{
//注销触屏响应事件
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
CCLayer::onExit();//一定不要忘了调用父类的onExit
}
//

3、单点触碰响应函数

ccTouchBegan、ccTouchMoved、ccTouchEnded、ccTouchCancelled。

其中ccTouchBegan的返回值为bool类型:

当返回true时 ,表示继续响应ccTouchMoved、ccTouchEnded事件;

当返回false时,则不再继续响应这两个事件。

//
virtual bool ccTouchBegan(CCTouch* touch,CCEvent* event); //手指碰到屏幕时调用
virtual void ccTouchMoved(CCTouch* touch,CCEvent* event); //手指在屏幕上滑动时调用
virtual void ccTouchEnded(CCTouch* touch,CCEvent* event); //手指离开屏幕是调用
virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent); //取消触碰
//

4、关于CCTouch类

CCTouch类是用来存储用户触摸屏幕的过程中,其触摸点的相关信息。也就是保存了触碰的整个过程中,手指所在的位置坐标。

需要在.h中添加引用命名空间:using namespace cocos2d; 才可以使用。

常用操作如下:

//
class CCTouch : public CCObject
{
CCPoint getLocation(); //返回当前触点的坐标
CCPoint getPreviousLocation(); //返回前一个触点的坐标
CCPoint getStartLocation(); //返回开始触碰时的坐标
CCPoint getDelta(); //返回最近两个触点的偏移量坐标
};
//

5、代码实战

接下来将举个例子:使用单点触碰实现精灵的移动。

5.1、声明单点触碰响应函数

先在HelloWorld.h中,声明触碰响应函数,以及类的生命周期。

//
//触屏事件
virtual bool ccTouchBegan(CCTouch* touch,CCEvent* event);
virtual void ccTouchMoved(CCTouch* touch,CCEvent* event);
virtual void ccTouchEnded(CCTouch* touch,CCEvent* event); //生命周期
virtual void onEnter();
virtual void onExit();
//

5.2、开启、关闭单点触碰事件

在HelloWorld.cpp中编写开启和关闭触碰事件。

//
//开启触屏监听
void HelloWorld::onEnter()
{
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,false);
CCLayer::onEnter(); //一定不要忘了
} //关闭触屏监听
void HelloWorld::onExit()
{
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
CCLayer::onExit(); //一定不要忘了
}
//

5.3、创建测试精灵

在HelloWorld::init()中创建一个CCSprite精灵,用于测试触碰。

//
//添加一个CCSprite精灵
CCSprite* sp = CCSprite::create("Icon.png");
sp->setPosition( midPos );
this->addChild(sp, 0, 1); //tag标记为1
//

5.4、实现触碰响应函数

ccTouchBegan:将精灵的位置设置到触碰开始的位置。关键函数:touch->getLocation()

ccTouchMoved:对精灵的位置进行移动。            关键函数:touch->getDelta()

ccTouchEnded:将精灵的位置还原到触碰开始的位置。关键函数:touch->getStartLocation()

//
//触屏开始ccTouchBegan
bool HelloWorld::ccTouchBegan(CCTouch* touch,CCEvent * event)
{
CCLOG("ccTouchBegan"); //获取CCSprite精灵
CCSprite* sp = (CCSprite*)this->getChildByTag(1); //设置精灵的坐标为: 当前触点位置
CCPoint pTouch = touch->getLocation();
sp->setPosition( pTouch ); return true;
} //触屏移动ccTouchMoved
void HelloWorld::ccTouchMoved(CCTouch* touch,CCEvent* event)
{
CCLOG("ccTouchMoved"); //获取可视区域尺寸大小
CCSize mysize = CCDirector::sharedDirector()->getVisibleSize(); //获取CCSprite精灵
CCSprite* sp = (CCSprite*)this->getChildByTag(1); //实现精灵的触屏移动
CCPoint pos = touch->getDelta(); //获得触屏滑动的偏移量
CCPoint currentPos = sp->getPosition(); //获得精灵的当前坐标 currentPos = ccpAdd(currentPos, pos); //精灵+偏移量 后的坐标 sp->setPosition(currentPos); //设置触屏移动后的坐标
} //触屏结束ccTouchEnded
void HelloWorld::ccTouchEnded(CCTouch* touch,CCEvent* event)
{
CCLOG("ccTouchEnded"); //获取CCSprite精灵
CCSprite* sp = (CCSprite*)this->getChildByTag(1); //设置精灵的坐标为: 触屏开始时的触点位置
CCPoint touchStartPos = touch->getStartLocation();
sp->setPosition( touchStartPos );
}
//

6、运行结果


【多点触碰】

多点触碰StandardDelegate,可以支持多个点的同时触摸响应事件。

1、开启多点触碰

多点触碰的委托注册放在onEnter的生命函数中会造成程序异常退出。

所以注册多点触碰都需要重写如下函数:registerWithTouchDispatcher

开启多点触碰,除了注册触碰委托外,还需要调用setTouchEnabled(true)来启用触碰。

//
/**
* 注册多点触碰,重写registerWithTouchDispatcher。
* addStandardDelegate("触碰事件委托的对象","优先级")
*/
void HelloWorld::registerWithTouchDispatcher()
{
CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this,0);
} //在HelloWorld::init()中启用多点触碰
this->setTouchEnabled(true);
//

2、关闭多点触碰

与单点触碰的关闭类似,写在onExit()。

//
void HelloWorld::onExit()
{
//关闭触碰
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
CCLayer::onExit(); //一定不要忘了
}
//

3、多点触碰响应函数

ccTouchesBegan、ccTouchesMoved、ccTouchesEnded、ccTouchesCancelled。

其中ccTouchesBegan和单点触碰不同,返回值为void。

//
virtual void ccTouchesBegan(CCSet* touches, CCEvent* event); //触碰开始
virtual void ccTouchesMoved(CCSet* touches, CCEvent* event); //触碰移动
virtual void ccTouchesEnded(CCSet* touches, CCEvent* event); //触碰结束
virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent); //取消多点触屏
//

4、关于CCSet类

CCSet类是一个集合类,和C++中的Set是类似的。

在这里CCSet的数据元素类型为CCTouch,其主要存储的是多点触碰的触摸点CCTouch集合。

使用迭代器CCSetIterator进行CCSet集合中多个触点CCTouch的遍历。

//
for (CCSetIterator iter = touches->begin() ;iter != touches->end(); iter++)
{
//获取触点后,就和单点一样的处理了
CCTouch* touch = (CCTouch*)(*iter);
//......
}
//

5、代码实战

在电脑中无法看到多点触碰的效果,因为……电脑操作只有一个鼠标。

下面就讲解一个多点触碰的例子吧,至于效果,自己将代码移植到手机上看吧。。。

5.1、声明多点触碰响应函数

先在HelloWorld.h中,声明多点触碰响应函数,以及类的生命周期。

//
//触屏事件
virtual void registerWithTouchDispatcher(void);
virtual void ccTouchesBegan(CCSet* touches,CCEvent* event);
virtual void ccTouchesMoved(CCSet* touches,CCEvent* event);
virtual void ccTouchesEnded(CCSet* touches,CCEvent* event); //生命周期
virtual void onExit();
//

5.2、开启、关闭多点触碰事件

在HelloWorld.cpp中编写开启和关闭多点触碰事件。

//
//在init中开启多点触碰
bool HelloWorld::init()
{
//.....
//开启多点触屏。注意这句话必须要写,否则无法多点触屏
this->setTouchEnabled(true);
//.....
} //注册多点触屏
void HelloWorld::registerWithTouchDispatcher()
{
CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this,0);
} //注销多点触屏
void HelloWorld::onExit()
{
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
CCLayer::onExit(); //不要忘了写!
}
//

5.3、创建测试精灵

在HelloWorld::init()中创建两个CCSprite精灵,用于测试触碰。

//
//添加两个CCSprite精灵,用于多点触屏
CCSprite* sp1 = CCSprite::create("Icon.png");
sp1->setPosition( ccp( 100, 160 ) );
this->addChild(sp1, 0, 1); CCSprite* sp2 = CCSprite::create("Icon_gray.png");
sp2->setPosition( ccp( 200, 160) );
this->addChild(sp2, 0, 2);
//

5.4、实现多点触碰响应函数

ccTouchesMoved中:将精灵的位置设置到触点位置,sp1精灵设置到第0个触点位置;sp2精灵设置到第1个触点位置。

关键函数:

(1)CCTouch* touch = (CCTouch*)(*iter)

(2)touch->getID()

//
//触屏开始,返回值是void
void HelloWorld::ccTouchesBegan(CCSet* touches,CCEvent* event)
{
CCLOG("ccTouchesBegan");
} //触屏移动
void HelloWorld::ccTouchesMoved(CCSet* touches,CCEvent* event)
{
CCLOG("ccTouchesMoved"); //创建CCSet的迭代器CCSetIterator
CCSetIterator iter = touches->begin(); //遍历多点触点集合touches
for( ;iter != touches->end(); iter++)
{
//获取触点后,就和单点一样的处理了
CCTouch* touch = (CCTouch*)(*iter); if( touch->getID() == 0) //控制精灵sp1
{
CCSprite* sp1 = (CCSprite*)this->getChildByTag(1);
sp1->setPosition( touch->getLocation() );
}
else if( touch->getID() == 1) //控制精灵sp2
{
CCSprite* sp2 = (CCSprite*)this->getChildByTag(2);
sp2->setPosition( touch->getLocation() );
}
}
} //触屏结束
void HelloWorld::ccTouchesEnded(CCSet* touches,CCEvent* event)
{
CCLOG("ccTouchesEnded");
}
//

6、运行结果

想要看到多点触碰的效果,就把程序移植到手机上吧。


两类触碰的区别】

(1)单点使用的监听类是CCtargetedTouchDelegate,而多点使用CCtangardTouchDelegate。

(2)多点触控还需要多一个步骤,就是单独写个函数来注册多点触控:registerWithTouchDispatcher。

(3)多点触控要有开启才能用。 this->setTouchEnabled(true)。

(4)多点触控中的ccTouchesBegan不是布尔型。

cocos2dx基础篇(7) 触碰事件的更多相关文章

  1. cocos2dx基础篇(3) 常用重要类

    ---------------------------------------- 入口类main.cpp 主要控制类AppDelegate.cpp -------------------------- ...

  2. cocos2dx基础篇(14) 滚动视图CCScrollView

    [3.x]     (1)去掉 "CC"     (2)滚动方向         > CCScrollViewDirection 改为强枚举 ScrollView::Dire ...

  3. cocos2dx基础篇(12) 编辑框之一CCTextFieldTTF

    前面我们讲了精灵贴图.标签.菜单.按钮.感觉似乎少了点什么?UI控件里是不是应该还有一个很重要的控件--编辑框.在手机网游中,启动游戏,过了开场动画后,基本上显示的第一个界面应该就是游戏的登录界面了吧 ...

  4. cocos2dx基础篇(5) 按钮

    这篇是直接复制的别人的,太多了,难得写... [本节内容] CCMenu.CCMenuItem其具体的六个子类 [菜单CCMenu] 菜单CCMenu是用来装载菜单按钮的图层,图层中的子节点只能够是菜 ...

  5. Android触碰事件

    OnTouchListener使用 public class ViewActivity extends Activity implements View.OnTouchListener { @Over ...

  6. cocos2dx基础篇(13) 编辑框之二CCEditBox

    [3.x] (1)去掉"CC" (2)设置虚拟键盘的编辑类型 > EditBoxInputMode 变为强枚举 EditBox::EditBoxInputMode // SI ...

  7. 【Cocos2d入门教程二】Cocos2d-x基础篇

    上一章已经学习了环境的搭建.这一章对基础概念进行掌握.内容大概有: 1.导演 2.场景 3.节点 4.层 4.精灵 1.导演(Director) 导演存在的主要作用: a.环境设定(帧率 初始化ope ...

  8. cocos2dx基础篇(15) 列表视图CCTableView

    [3.x] (1)去掉 "CC" (2)TableViewCell 中: > unsigned int getIdx() 返回类型改为 ssize_t(类型为 long) ( ...

  9. js 基础篇(点击事件轮播图的实现)

    轮播图在以后的应用中还是比较常见的,不需要多少行代码就能实现.但是在只掌握了js基础知识的情况下,怎么来用较少的而且逻辑又简单的方法来实现呢?下面来分析下几种不同的做法: 1.利用位移的方法来实现 首 ...

随机推荐

  1. redis 加锁与释放锁(分布式锁1)

    使用Redis的 SETNX 命令可以实现分布式锁 SETNX key value 返回值 返回整数,具体为 - 1,当 key 的值被设置 - 0,当 key 的值没被设置 分布式锁使用 impor ...

  2. 【CF1187C】Vasya And Array

    题目大意:给定一个长度为 N 的数组,以及 M 个区间,给出的区间有两个性质,性质一是给定区间中的元素单调不减,性质二是给定区间中的元素存在相邻单调减的元素对,求构造一个符合给定区间条件的序列,若不存 ...

  3. 【洛谷P3128】Max Flow

    题目大意:给定一棵 N 个节点的无根树,有 M 个操作,每次选定一条树链,将这条链上所有点的点权 +1,最后求树上点的最大点权是多少. 题解:树上差分算法的应用. 发现操作有 M 次,但是询问只有一次 ...

  4. Java使用freemarker导出word文档

    通过freemarker,以及JAVA,导出word文档. 共分为三步: 第一步:创建模板文件 第二步:通过JAVA创建返回值. 第三步:执行 分别介绍如下: 第一步: 首先创建word文档,按照想要 ...

  5. SVN各种错误提示产生原因及处理方法大全

    SVN各种错误提示产生原因及处理方法大全 SVN各种错误提示产生原因及处理方法大全 1. svn: Server sent unexpected return value (500 Internal ...

  6. jprofiler 监听远程java项目

    1.下载.安装windows和linux版的jprofile.注意:若监控的是springboot.springcloud项目,切记本地和服务器上的jprofile要版本保持一致,本人亲自踩过坑. 官 ...

  7. #5 DIV2 A POJ 3321 Apple Tree 摘苹果 构建线段树

    Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 25232   Accepted: 7503 Descr ...

  8. R_Studio(学生成绩)绘制频率分布直方图、分布饼图、折线比较图

    对“Gary.csv”中的成绩数据进行分布分析 (1)按0-59,60-69,70-79,80-89,90-100分组绘制高级语言程序设计成绩的频率分布直方图. (2)按0-59,60-69,70-7 ...

  9. Java基础教程免费分享

    这是我自己早前听课时整理的Java全套知识,适用于初学者,也可以适用于中级进阶的人,你们可以下载,我认为是比较系统全面的,可以抵得上市场上90%的学习资料.讨厌那些随便乱写的资料还有拿出来卖钱的人!在 ...

  10. 二、linux下apache2.2.11+php5.6.3的环境配置

    参考文献:http://www.92csz.com/study/linux/16.htm 本节部分操作会直接使用上一节(http://www.cnblogs.com/yxpblog/p/4627509 ...