MyException - 我的异常网
当前位置:我的异常网» 操作系统 » Cocos2d-x范例:单点触摸事件

Cocos2d-x范例:单点触摸事件

www.MyException.Cn  网友分享于:2014-07-26  浏览:0次
Cocos2d-x实例:单点触摸事件

为了让大家掌握Cocos2d-x中的事件机制,下面我们以触摸事件为例,使用事件触发器实现单点触摸事件。该实例如图8-3所示,场景中有三个方块精灵,显示顺序如图8-3所示,拖拽它们可以移动它们,事件响应优先级是按照它们的显示顺序。

下面我们再看看具体的程序代码,首先看一下HelloWorldScene.h文件,它的代码如下:

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
 
#include "cocos2d.h"
typedef enum                                                                                                                                         ①
{
    kBoxA_Tag = 102
   ,kBoxB_Tag
   ,kBoxC_Tag
} SpriteTags;                                                                                                                                 ②
 
 
class HelloWorld : public cocos2d::Layer
{
public:
   static cocos2d::Scene* createScene();
   virtual bool init();          
    virtualvoid onEnter();                                                                                                                      ③
    virtualvoid onExit();                                                                                                                         ④
   
    booltouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);                                          ⑤
   void touchMoved(cocos2d::Touch *touch, cocos2d::Event *event);                                       ⑥
   void touchEnded(cocos2d::Touch *touch, cocos2d::Event *event);                                       ⑦
 
   CREATE_FUNC(HelloWorld);
};
 
#endif // __HELLOWORLD_SCENE_H__

上述代码第①~②行是定义个枚举类型SpriteTags,枚举类型SpriteTags中定义了三个常量,这三个常量对应场景中的三个精灵的标签(Tag)属性。代码第③行声明了层声明周期的onEnter()函数,我们将在该函数中注册监听器和初始化设置。第④行代码是声明了层声明周期的onExit()函数,我们将在该函数中注销监听器和释放一些资源。代码第⑤~⑥行是声明单点触摸事件回调函数。

HelloWorldScene的实现代码HelloWorldScene.ccp文件,它的HelloWorld::init()代码如下:

bool HelloWorld::init()
{
    if( !Layer::init() )
    {
         returnfalse;
    }
 
    SizevisibleSize = Director::getInstance()->getVisibleSize();
    Pointorigin = Director::getInstance()->getVisibleOrigin();
 
    //贴图的纹理图片宽高必须是2的n次幂,128x128
    autobg = Sprite::create("BackgroundTile.png",
                                Rect(0,0, visibleSize.width, visibleSize.height));                                               ①
    //贴图的纹理参数,水平重复平铺,垂直重复平铺
    Texture2D::TexParamstp = {GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT};                 ②
    bg->getTexture()->setTexParameters(tp);                                                                             ③
    bg->setPosition(origin+ Point(visibleSize.width/2, visibleSize.height/2));
    addChild(bg,0);                                                                                                                                ④
 
    Sprite*boxA = Sprite::create("BoxA2.png");                                                                                   ⑤
    boxA->setPosition(origin+Point(visibleSize.width/2,visibleSize.height/2) + Point(-120, 120));
    addChild(boxA,10, kBoxA_Tag);
 
    Sprite*boxB = Sprite::create("BoxB2.png");
    boxB->setPosition(origin+Point(visibleSize.width/2,visibleSize.height/2));
    addChild(boxB,20, kBoxB_Tag);
 
    Sprite*boxC = Sprite::create("BoxC2.png");
    boxC->setPosition(origin+Point(visibleSize.width/2,visibleSize.height/2) + Point(120, 160));
    addChild(boxC,30, kBoxC_Tag);                                                                                         ⑥
 
    returntrue;
}

我们在HelloWorld::init()函数中初始化了场景中的背景和三个方块精灵。代码第①~④行是创建并添加背景,图8-3所示的背景是由一个128x128纹理图片(BackgroundTile.png)反复贴图上,这样可以减少内存消耗,在第①行代码中创建背景精灵对象,注意背景的大小仍然是整个屏幕。第②行代码是设置贴图的纹理的参数,Texture2D::TexParams类型是一个结构体。第③行代码是将参数设置到背景精灵的纹理上。第④行代码是添加背景精灵到当前层。

代码第⑤~⑥行是创建了三个方块精灵,在添加它到当前层的时候我们使用三个参数的addChild(Node* child,int localZOrder,int tag)函数,这样可以通过localZOrder参数指定精灵的显示顺序。

HelloWorldScene.ccp中的HelloWorld::onEnter()代码如下:
void HelloWorld::onEnter()
{
    Layer::onEnter();
    log("HelloWorldonEnter");
 
    autolistener = EventListenerTouchOneByOne::create();                                                             ①
   
    listener->setSwallowTouches(true);                                                                                      ②
    listener->onTouchBegan= CC_CALLBACK_2(HelloWorld::touchBegan, this);                         ③
    listener->onTouchMoved=  CC_CALLBACK_2(HelloWorld::touchMoved,this);                     ④
    listener->onTouchEnded=  CC_CALLBACK_2(HelloWorld::touchEnded,this);                     ⑤
 
    //添加监听器
    EventDispatcher*eventDispatcher = Director::getInstance()->getEventDispatcher();              ⑥
    eventDispatcher->addEventListenerWithSceneGraphPriority(listener,
                                                                            getChildByTag(kBoxA_Tag));                                  ⑦
    eventDispatcher->addEventListenerWithSceneGraphPriority(listener->clone(),
                                                                            getChildByTag(kBoxB_Tag));                                  ⑧
    eventDispatcher->addEventListenerWithSceneGraphPriority(listener->clone(),
                                                                            getChildByTag(kBoxC_Tag));                                 ⑨
 
}

上述代码第①行是创建一个单点触摸事件监听器对象。第②行代码是设置是否吞没事件,如果设置为true,那么在onTouchBegan函数返回 true 时吞没事件,事件不会传递给下一个Node对象。第③行代码是设置监听器的onTouchBegan属性回调函数。第④行代码是设置监听器的onTouchMoved属性回调函数。第⑤行代码是设置监听器的onTouchEnded属性回调函数。

代码第⑥~⑨行是添加监听器,其中第⑦行使用精灵显示优先级添加事件监听器,其中参数getChildByTag(kBoxA_Tag)是通过精灵标签Tag实现获得精灵对象。第⑧行和第⑨行代码是为另外两精灵添加事件监听器,其中listener->clone()获得listener对象,使用clone()函数是因为每一个事件监听器只能被添加一次,addEventListenerWithSceneGraphPriority和addEventListenerWithFixedPriority会在添加事件监听器时设置一个注册标识,一旦设置了注册标识,该监听器就不能再用于注册其它事件监听了,因此我们需要使用listener->clone()克隆一个新的监听器对象,把这个新的监听器对象用于注册。

HelloWorldScene.ccp中的触摸事件回调函数代码如下:

bool HelloWorld::touchBegan(Touch*touch, Event* event)                                                            ①
{
    //获取事件所绑定的 target
    autotarget = static_cast<Sprite*>(event->getCurrentTarget());                                                    ②
    PointlocationInNode = target->convertToNodeSpace(touch->getLocation());                         ③
    Sizes = target->getContentSize();                                                                                          ④
    Rectrect = Rect(0, 0, s.width, s.height);                                                                                         ⑤
 
    //点击范围判断检测
    if(rect.containsPoint(locationInNode))                                                                                         ⑥
    {
         log("spritex = %f, y = %f ", locationInNode.x, locationInNode.y);
         log("spritetag = %d", target->getTag());
         target->runAction(ScaleBy::create(0.06f,1.06f));                                                             ⑦
         returntrue;                                                                                                                                     ⑧
    }
    returnfalse;
}
 
void HelloWorld::touchMoved(Touch*touch, Event *event)                                                           ⑨
{
    log("onTouchMoved");
    autotarget = static_cast<Sprite*>(event->getCurrentTarget());
    target->setPosition(target->getPosition()+ touch->getDelta());                                                   ⑩
}
 
void HelloWorld::touchEnded(Touch*touch, Event *event)                                                           ⑪
{
    log("onTouchEnded");
    autotarget = static_cast<Sprite*>(event->getCurrentTarget());
    log("spriteonTouchesEnded.. ");
 
    PointlocationInNode = target->convertToNodeSpace(touch->getLocation());
    Sizes = target->getContentSize();
    Rectrect = Rect(0, 0, s.width, s.height);
    //点击范围判断检测
    if(rect.containsPoint(locationInNode))
    {
         log("spritex = %f, y = %f ", locationInNode.x, locationInNode.y);
         log("spritetag = %d", target->getTag());
         target->runAction(ScaleTo::create(0.06f,1.0f));
    }
}

上代码第①行是定义回调函数touchBegan。第②行代码是获取事件所绑定的精灵对象,其中event->getCurrentTarget()语句返回值是Node对象,static_cast<Sprite*>是强制类型转换为Sprite对象。第③行代码是获取当前触摸点相对于target对象的本地坐标。第④行代码是获得target对象的尺寸。第⑤行代码是通过target对象的尺寸创建Rect变量。第⑥行代码rect.containsPoint(locationInNode)是判断是否触摸点在target对象范围。第⑦行代码是放大target对象。第⑧行代码返回true,表示可以回调第⑨行touchMoved函数和第⑪行touchEnded函数。第⑩行代码是移动target对象的位置。

HelloWorldScene.ccp中的HelloWorld::onExit()代码如下:

void HelloWorld::onExit()
{
    Layer::onExit();
    log("HelloWorldonExit");
    Director::getInstance()->getEventDispatcher()->removeAllEventListeners();
}

上述HelloWorld::onExit()函数是退出层时候回调,我们在这个函数中注销所有的监听事件。

提示 多点触摸事件是与具体的平台有关系的,在Win32平台下我们无法测试多点触摸。事实上多点触摸和单点触摸开发流程基本相似,这里我们就不再赘述了。


更多内容请关注Cocos2d-x系列图书《Cocos2d-x实战(卷Ⅰ):C++开发》
本书交流讨论网站:http://www.cocoagame.net
欢迎加入cocos2d-x技术讨论群:257760386、327403678


文章评论

科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
总结2014中国互联网十大段子
总结2014中国互联网十大段子
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
我是如何打败拖延症的
我是如何打败拖延症的
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
10个调试和排错的小建议
10个调试和排错的小建议
程序员和编码员之间的区别
程序员和编码员之间的区别
那些争议最大的编程观点
那些争议最大的编程观点
程序员都该阅读的书
程序员都该阅读的书
每天工作4小时的程序员
每天工作4小时的程序员
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
旅行,写作,编程
旅行,写作,编程
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
漫画:程序员的工作
漫画:程序员的工作
 程序员的样子
程序员的样子
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
我的丈夫是个程序员
我的丈夫是个程序员
Java程序员必看电影
Java程序员必看电影
老程序员的下场
老程序员的下场
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
一个程序员的时间管理
一个程序员的时间管理
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
为什么程序员都是夜猫子
为什么程序员都是夜猫子
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
程序员必看的十大电影
程序员必看的十大电影
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
程序员应该关注的一些事儿
程序员应该关注的一些事儿
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
代码女神横空出世
代码女神横空出世
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
如何成为一名黑客
如何成为一名黑客
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
中美印日四国程序员比较
中美印日四国程序员比较
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有