我们依据上一次介绍的触屏事件和事件队列等知识来实现触屏的单击,双击,三连击事件。

下图为我们实现的效果图:

单击精灵跳跃一个高度,

双击精灵跳跃的高度比单击的高

三连击精灵跳跃的跟高

好了,開始动手吧。新建项目,删除多余的代码

接着在Classes文件夹下建立两个文件,这里我就命名为Human了

(在Classes上右键加入�新建项,选择头文件,名称Human.h,位置浏览到Classes文件夹下)

由于要实现精灵能接受触屏事件,所以我们不能用CCSprite ,须要自己写个类继承CCSprite和CCTouchDelegate

还记得CCTouchDelegate类吗??

OK   我们先实现头文件

#ifndef _Human_H_
#include "cocos2d.h"
USING_NS_CC;
class Human:public CCSprite,public CCTouchDelegate
{
public:
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
virtual void onEnter();
virtual void onExit();
//创建静态方法,用于创建Human精灵
static Human* create(const char *pszFileName);
private: }; #endif // !_Human_H_

重写的这5个方法应该不用解释了,上一节介绍过的

(教大家一个小技巧,比方我不记得触屏事件的名称或參数怎么写来着,没事,不用死机硬背的,鼠标放在CCTouchDelegate上F12,就能够看到它们都在,多点,单点等等,你复制一份就哦了。)

接着我们来实现CPP文件

#include "Human.h"
bool Human::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
CCLOG("ccTouchBegan");
return true;
}
void Human::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
{
CCLOG("ccTouchMoved");
}
void Human::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
CCLOG("ccTouchEnded");
}
void Human::onEnter()
{
//继承,重载方法的步骤我们实现了,接下来就是注冊
//第一步:将我们须要处理触屏事件的类加入�到事件队列中dispatcher
CCSprite::onEnter();
CCTouchDispatcher *dispatcher= CCDirector::sharedDirector()->getTouchDispatcher();
dispatcher->addTargetedDelegate(this,0,true);
}
void Human::onExit()
{
//第二步:卸载
CCTouchDispatcher *dispatcher= CCDirector::sharedDirector()->getTouchDispatcher();
dispatcher->removeDelegate(this);
}
Human* Human::create(const char *pszFileName)
{
Human *pobSprite = new Human();
if (pobSprite && pobSprite->initWithFile(pszFileName))
{
pobSprite->autorelease();
return pobSprite;
}
CC_SAFE_DELETE(pobSprite);
return NULL;
}

这里凝视非常具体了,或许大家写不出create方法里面的代码吧?写不出没关系,看得懂即可了,以后熟练了就能够写出来了,我们找到CCSprite中的create方法的实现代码。照着写即可了,主要将

 CCSprite *pobSprite = new CCSprite();

改为

Human *pobSprite = new Human();

F6编译一下看看是否出错?

成功了?那接着

bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}
Human *humanSprite=Human::create("Icon.png");
humanSprite->setPosition(ccp(240,30));
this->addChild(humanSprite);
return true;
}

这里不是CCSprite了,是我们自己定义的精灵,它能够接受触屏事件的响应

OK 执行,点击屏幕,看输出窗体

有个小问题,不一定点击精灵才触发事件,点击屏幕的不论什么地方都会触发事件,这不是我们想要的结果。

我们须要的是仅仅有触摸点在精灵图片的范围内才触发事件

OK,我们在新增一个方法  containsTouchLocation

//推断触摸点是否在精灵范围内
bool containsTouchLocation(CCTouch *pTouch);

实现

#ifndef _Human_H_
#include "cocos2d.h"
USING_NS_CC;
class Human:public CCSprite,public CCTouchDelegate
{
public:
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
virtual void onEnter();
virtual void onExit();
//创建静态方法,用于创建Human精灵
static Human* create(const char *pszFileName);
//推断触摸点是否在精灵范围内
bool containsTouchLocation(CCTouch *pTouch);
private: }; #endif // !_Human_H_

CPP

#include "Human.h"
bool Human::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
return true;
}
void Human::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
if (containsTouchLocation(pTouch))
{
CCLOG("ccTouchEnded");
}
} bool Human::containsTouchLocation(CCTouch *pTouch)
{
//首先须要获得精灵的大小,将它转换为一个CCRect(矩形)
CCSize spriteSize= this->getContentSize();
CCRect rect=CCRectMake(-spriteSize.width/2,-spriteSize.height/2,spriteSize.width,spriteSize.height);
//通过CCRect中的containsPoint,来推断这个矩形是否包括这个点
//这个点为我们的触摸点
if(!rect.containsPoint(this->convertTouchToNodeSpaceAR(pTouch)))
{
return false;
}
return true;
}
void Human::onEnter()
{
//继承,重载方法的步骤我们实现了,接下来就是注冊
//第一步:将我们须要处理触屏事件的类加入�到事件队列中dispatcher
CCSprite::onEnter();
CCTouchDispatcher *dispatcher= CCDirector::sharedDirector()->getTouchDispatcher();
dispatcher->addTargetedDelegate(this,0,true);
}
void Human::onExit()
{
//第二步:卸载
CCTouchDispatcher *dispatcher= CCDirector::sharedDirector()->getTouchDispatcher();
dispatcher->removeDelegate(this);
}
Human* Human::create(const char *pszFileName)
{
Human *pobSprite = new Human();
if (pobSprite && pobSprite->initWithFile(pszFileName))
{
pobSprite->autorelease();
return pobSprite;
}
CC_SAFE_DELETE(pobSprite);
return NULL;
}

这里都有凝视了,

第一,先获得精灵的大小(ContentSize)将其转换为CCRect(矩形)

第二,利用CCRect中的containsPoint方法来推断这个矩形是否包括这个点,包括返回true否则反之

(这里须要把触摸点的位置转换为相对当前精灵节点的相对位置

我们介绍坐标系统的时候貌似仅仅提到过UIKIT坐标,OPGL坐标,事实上还有个相对坐标和世界坐标

我们在讲完这个实列之后再介绍,如今先这样写着)

这里另一句

CCRect rect=CCRectMake(-spriteSize.width/2,-spriteSize.height/2,spriteSize.width,spriteSize.height);

非常纳闷为什么是 -spriteSize.width/2

刚開始我也非常郁闷,根本看不懂,后来直接盯着这段代码不眨眼盯了半小时,瞬间懂了,

我们学习坐标系统都知道默认锚点是在中心点吧?精灵也是

我们得求出左下角点的x和y坐标,然后后面两个參数都懂的

如果精灵是40X40的图片,锚点在中心,所以中心点为0,0坐标   然后四个角的坐标如上图。

如今我们要的出左下角的坐标,瞬间懂了吗??



如今我们差点儿相同完毕一半了,事实上我们在CCTouchEnded方法中完毕我们的跳跃效果,可是这仅仅是单击跳跃,多连击还是得我们自己实现

#ifndef _Human_H_
#include "cocos2d.h"
USING_NS_CC;
class Human:public CCSprite,public CCTouchDelegate
{
public:
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
virtual void onEnter();
virtual void onExit();
//创建静态方法,用于创建Human精灵
static Human* create(const char *pszFileName);
//推断触摸点是否在精灵范围内
bool containsTouchLocation(CCTouch *pTouch);
//构造方法,初始化变量
Human();
//单击调用
void SignleClicked(float dt);
//双击
void DoubleClicked(float dt);
//三连击
void ThreeClicked();
private:
//记录点击的次数
int clickedCount;
}; #endif // !_Human_H_

这里添加�了些方法

//构造方法,初始化变量
Human::Human():clickedCount(0)
{}
//单击调用
void Human::SignleClicked(float dt){
if (clickedCount==1)
{
clickedCount=0;
CCActionInterval* jumpto= CCJumpBy::create(1.4f,CCPointZero,50,1);
this->runAction(jumpto);
} }
//双击
void Human::DoubleClicked(float dt){
if (clickedCount==2)
{
clickedCount=0;
CCActionInterval* jumpto= CCJumpBy::create(1.4f,CCPointZero,120,1);
this->runAction(jumpto);
}
}
//三连击
void Human::ThreeClicked(){
clickedCount=0;
CCActionInterval* jumpto= CCJumpBy::create(1.4f,CCPointZero,220,1);
this->runAction(jumpto);
}

方法的实现大致是这样,推断变量的值,假设是1则运行单击跳跃高度为50,后面的不说了

接着我们在ccTouchEnded函数中用延迟的一个方法来实现各种点击

void  Human::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
if (!containsTouchLocation(pTouch))
{
return;
}
//假设点击在精灵上,则运行
if (clickedCount==2)
{
ThreeClicked();
}
else if (clickedCount==1)
{
//延迟0.25秒运行双击
scheduleOnce(schedule_selector(Human::DoubleClicked),0.25f);
clickedCount++;
}
else
{
//延迟0.25秒运行单击
scheduleOnce(schedule_selector(Human::SignleClicked),0.25f);
clickedCount++;
}
}

这里逻辑有点转只是来,

如果,我们点击一次,它将会运行最后的else   ,而单击的方法要在0.25秒后才运行可是此时变量的值已经为1了

然后我们在0.25秒的时间内在继续点击,它将运行第二个IF中的语句,同理,双击的方法也要在0.25秒后运行,可是此时变量的值已经是2了

这个大家多断点,自己多想想,说不清楚



OK,截止我们的多连击已经搞定了





总结一下:

首先,我们学会了怎样制定自己的精灵

怎样使自己的精灵能处理触屏事件

理解怎样完毕处理触屏事件的几个步骤

怎样推断触摸点是否是点击在指定的矩形区域中,这个非常重要哦

利用计时器延迟巧妙实现处理多连击事件

(还有哪些不懂的代码,自己能够先baidu一下)



附源代码





Cocos2D-X2.2.3学习笔记8(处理精灵单击、双击和三连击事件)的更多相关文章

  1. Vue学习笔记-组件通信-子传父(自定义事件)

    props用于父组件向子组件传递数据,还有一种比较常见的是子组件传递数据或事件到父组件中.我们应该如何处理呢?这个时候,我们需要使用自定义事件来完成.什么时候需要自定义事件呢?当子组件需要向父组件传递 ...

  2. STM32学习笔记(九) 外部中断,待机模式和事件唤醒

    学会知识只需要不段的积累和提高,但是如何将知识系统的讲解出来就需要深入的认知和系统的了解.外部中断和事件学习难度并不高,不过涉及到STM32的电源控制部分,还是值得认真了解的,在本文中我将以实际代码为 ...

  3. 【Android开发学习笔记】【第十课】运动事件 之——触摸屏

    概念 触摸屏 (TouchScreen) 和 滚动球(TrackBall)是Android 中除了键盘之外的主要输入设备. 而这两个事件都可以用运动事件(MotionEvent)用于接收他们的信息 直 ...

  4. 【MFC学习笔记-作业9-基于单击响应的计算平均成绩】【】

    要求..单击出现 一个输入成绩的框,点确定后,计算平均成绩 意义很大~ 完成对话框   再写个鼠标点击的响应部分 鼠标点击的响应部分为难点.... void CWj1401_0302140107_9V ...

  5. 【学习笔记】锋利的jQuery(三)事件和动画

    一.jQuery事件 1,加载事件 $(document).ready(function(){...}) //等同于$(function(){..}) $(window).load(function( ...

  6. python学习笔记(3)--IDLE双击运行后暂停

    本来想找一个python的IDE什么的,用过pycharm,vs装python插件,软件都太大了,习惯了用sublime写html,js这样的简直受不了. 一直坚持用着python自带的IDLE,不过 ...

  7. Python3+Selenium3+webdriver学习笔记5(模拟常用键盘和鼠标事件)

    #!/usr/bin/env python# -*- coding:utf-8 -*- from selenium import webdriverfrom selenium.webdriver.co ...

  8. web前端学习(二)html学习笔记部分(8)--服务器推送事件3

    1.2.22  html5服务器推送事件 1.2.22.1  html5服务器推送事件介绍 服务器推送事件(Server-sent Events)是HTML5规范中的一个组成部分,可以用来从服务器端实 ...

  9. 吴裕雄--天生自然python学习笔记:python 用pygame模块检测键盘事件和鼠标事件

    用户可通过键盘输入来操控游戏中角色的运动,取得键盘事件的方法有以下两种 : 常用的按键与键盘常数对应表 : 按下右箭头键,蓝色小球会 向 右移动:按住右箭头键不放 , 球体会快速 向 右移 动, 若到 ...

随机推荐

  1. C++的四种cast操作符的区别--类型转换

    Q:什么是C风格转换?什么是static_cast, dynamic_cast 以及 reinterpret_cast?区别是什么?为什么要注意? A:转换的含义是通过改变一个变量的类型为别的类型从而 ...

  2. MinGW 使用 msvcr90.dll

    MinGW 编译出来的程序总是使用 VC6 的 msvcrt.dll ,VC8,9,10有很多新的API(仅限于c runtime),想使用怎么办? 比如:boost 对 MinGW 最低要求就是 m ...

  3. linux之SQL语句简明教程---Alias

    接下来,我们讨论 alias (别名) 在 SQL 上的用处.最常用到的别名有两种: 栏位别名及表格别名. 简单地来说,栏位别名的目的是为了让 SQL 产生的结果易读.在之前的例子中,每当我们有营业额 ...

  4. javascript 兼容各个浏览器的事件

  5. Android系统环境变量配置

    ANDROID_HOME D:\Program Files\Android-sdk D:\AndroidSDK\android-sdk ANDROID_SDK_HOME %ANDROID_HOME% ...

  6. 自写Date工具类

    以前写项目的时候总是在使用到了时间的转换的时候才在工具类中添加一个方法,这样很容易导致代码冗余以及转换的方法注释不清晰导致每次使用都要重新看一遍工具类.因此整理出经常使用的一些转换,用作记录,以便以后 ...

  7. javaweb一周总结(菜鸟)

    我的试用期开始了. 这是我的第一篇博客,这也是我作为java工程师的第六天,主要是为了记录一周内出现的问题以及一些工作上的解答,吐槽一句工作的确和想的不一样之后直接记录下吧. 由于拥有工作平台看不到底 ...

  8. javascript中this,call,apply详解

    javascript是一门解释型的语言,与很多面向对象语言相比有着不同特性,所以不能用面向对象的原理来理解this这个关键字. 在JS中,要真正理解this倒底指向哪个对象,必须先了解JS的作用域和原 ...

  9. Android_CodeWiki_02

    1.使用TransitionDrawable实现渐变效果  private void setImageBitmap(ImageView imageView, Bitmap bitmap) { // U ...

  10. requirejs + vue 项目搭建2

    上篇是年后的项目搭建的,时间比较仓促,感觉有点low 1.gulp-vue 文件对公用js的有依赖,以后别的同事拿去搭其他项目,估计会被喷 2.不支持vue-loader一样写模版语言和es6语法 最 ...