zoukankan      html  css  js  c++  java
  • cocos2d-x触屏事件(单点触屏)

    转自:http://blog.csdn.net/onerain88/article/details/7550009

    一般经常用到的触屏的情况有两种:一种是Layer统一接收触屏消息,然后由程序根据需要分发给不同位置的精灵;另一种情况是自定义一个可以接收触屏消息的Sprite,比如类似于Button功能的Sprite,这就需要在定义Sprite的时候就要定义好触屏所触发的操作!

    下面就两种情况分别记录一下基本用法:

    1.Layer接收触屏消息

    用法很简单,只需要覆写父类的4个方法(可以根据需要,但是ccTouchBegan()是必须要覆写的,并且其返回值对触屏事件的传递有影响,后面会总结),并在init()方法中将其添加到CCTouchDispacher中,代码如下

    class TouchableLayer: public CCLayer 
    {
    public:
        
        virtual bool init();
        
        LAYER_NODE_FUNC(TouchableLayer);
        
        virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
        virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
        virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
        virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
    };

    在Layer的init()中添加如下代码,这个Layer就可以接收到触屏消息了

    CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, true);

    如果想通过这种方式判断具体触摸的Sprite或者区域等信息,就需要自己写判断和分发消息的代码了!

    2.自定义可以接收触屏消息的Sprite

    这种稍微复杂一些,但是还是比较好理解的,首先要先继承CCSprite或者其父类,以满足精灵形状,位置等信息的要求,另外还需要继承触屏事件委托CCTargetedTouchDelegate,CCTargetedTouchDelegate中定义了接收触屏信息的回调虚函数,而这些虚函数,正是我们需要覆写的部分,代码如下

    class TouchableSprite: public CCSprite, public CCTargetedTouchDelegate
    {
        
    public:
        TouchableSprite();
        virtual ~TouchableSprite();
        
        static TouchableSprite *touchSpriteWithFile(const char *file);
        
        bool initWithFile(const char *file);
        
        virtual void onEnter();
        virtual void onExit();
        
        CCRect rect();
        bool containsTouchLocation(CCTouch *touch);
        
        virtual bool ccTouchBegan(CCTouch *touch, CCEvent *event);
        virtual void ccTouchMoved(CCTouch *touch, CCEvent *event);
        virtual void ccTouchEnded(CCTouch *touch, CCEvent *event);
    
    };

    重点在于判断自定义Sprite是否被点击,这时就需要得到精灵所在的矩形了,这时又有两种判断方式

    (1)得到触屏所在位置,然后根据精灵所在位置的矩形区域和触屏的点判断是否包含,如果包含,则说明触摸到了Sprite。这里写了一个得到精灵当前所在矩形的方法

    CCRect TouchableSprite::rect()
    {
        CCSize size = getContentSize();
        CCPoint pos = getPosition();
    
        return CCRectMake(pos.x - size.width / 2, pos.y - size.height / 2, size.width, size.height);
    }

    然后在每次点击的时候都需要将当前触屏位置转换为GL坐标的位置,然后和Sprite所在矩形做包含判断

    bool TouchableSprite::containsTouchLocation(cocos2d::CCTouch *touch)
    {
        CCPoint touchPoint = touch->locationInView(touch->view());
        touchPoint = CCDirector::sharedDirector()->convertToGL(touchPoint);
        
        return CCRect::CCRectContainsPoint(rect(), touchPoint);
    }

    (2)其实cocos2d为我们提供了一种相对简单的方法,但是原理类似,调用CCNode中定义的convertTouchToNodeSpaceAR()方法,将触屏点转化为相对于结点的相对坐标

    (ps:由于默认anchor点是中点,所以每一个Sprite上的相对坐标系是从(-width / 2, -height / 2)为左上角点坐标),所以上面的两个方法需要修改一下

    CCRect TouchableSprite::rect()
    {
        CCSize size = getTexture()->getContentSize();
    
        return CCRectMake(-size.width / 2, -size.height / 2, size.width, size.height);
    }
    bool TouchableSprite::containsTouchLocation(cocos2d::CCTouch *touch)
    {
        return CCRect::CCRectContainsPoint(rect(), convertTouchToNodeSpaceAR(touch));
    }

    3.触屏传递顺序

    另外需要主要的是

    virtual bool ccTouchBegan(CCTouch *touch, CCEvent *event);

    方法,其返回值是对此触屏消息有影响的,简单来说,如果返回false,表示不处理ccTouchMoved(),ccTouchEnded(),ccTouchCanceld()方法,而交由后续接收触屏消息的对象处理;如果返回true,表示会处理ccTouchMoved(),ccTouchEnded(),ccTouchCanceld()方法,并且消耗掉此触屏消息。

    总结如下:

    1.CCLayer 只有一层的情况:

    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    a.返回false,则ccTouchMoved(),ccTouchEnded()不会再接收到消息
    b.返回true,则ccTouchMoved(),ccTouchEnded()可以接收到消息
     
    2.CCLayer 有多层的情况:
    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    a.返回false,则本层的ccTouchMoved(),ccTouchEnded()不会再接收到消息,但是本层之下的其它层会接收到消息
    b.返回true,则本层的ccTouchMoved(),ccTouchEnded()可以接收到消息,但是本层之下的其它层不能再接收到消息
     
    3.有自定义接收触摸消息的精灵的情况:
    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    a.返回false,则此精灵的ccTouchMoved(),ccTouchEnded()不会再接收到消息,而此精灵所在的层会接收到触摸消息(如果精灵所在层没有设置接收触摸消息,则向下传递
    b.返回true,则此精灵的ccTouchMoved(),ccTouchEnded()会继续接收消息,并消耗此消息(即不再向所在层和其他层传递)

    4.自定义触屏事件

    1、判断触摸点是否在指定区域内

    HelloWorldScene.h

    public:
        CCRect mPlayBounds;
    
            virtual void registerWithTouchDispatcher();
            virtual bool ccTouchBegan(cocos2d::CCTouch* touch,     cocos2d::CCEvent* event);

    HelloWorldScene.cpp

    删除bool HelloWorld::init()下do代码块中的所有代码,替换为:

    CC_BREAK_IF(! CCLayer::init());
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    //实例化一个精灵
    CCSprite *mMainMenu = CCSprite::create("items.png", CCRectMake(0, 224, 300, 110));
    CC_BREAK_IF(!mMainMenu);
    //设置精灵的位置
    mMainMenu->setPosition(ccp(size.width / 2, size.height / 2));
    this->addChild(mMainMenu);
    
    //绘制一个矩形
    mPlayBounds = CCRectMake(size.width / 2 - 64, size.height / 2 + 18, 128, 36);
    //设置为可触摸
    this->setTouchEnabled(true);
            
    bRet = true;

    添加两个函数:

    void HelloWorld::registerWithTouchDispatcher()
    {
        //注册触摸监听
        CCDirector* pDirector = CCDirector::sharedDirector();
        pDirector->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
    }
    
    bool HelloWorld::ccTouchBegan(cocos2d::CCTouch* touch, cocos2d::CCEvent* event)
    {
        //取得触摸点
        CCPoint location = touch->getLocationInView();
        //将触摸点转换为GL坐标系的点
        location = CCDirector::sharedDirector()->convertToGL(location);
        
        //如果触摸点在矩形范围内则执行代码,切换场景
        if (mPlayBounds.containsPoint(location))
        {
            CCScene *scene = SecondScene::scene(); 
            CCDirector::sharedDirector()->replaceScene(CCTransitionJumpZoom::create(1.0f,scene));
        }
        return true;
    }
  • 相关阅读:
    实现货币金额中文大写转换的程序
    大数阶乘的计算(三)
    全国15亿人口中选1000个代表有多少种选法?
    DB Query Analyzer 中断SQL语句的执行
    Android_Preference存取数据
    Centos 学习笔记软件包管理
    Centos学习笔记文件搜索命令
    《计算机时代》2011年第12期刊登出《DB Query Analyzer中断SQL语句的执行》
    Centos学习笔记linux用户管理
    Centos学习笔记 linux 常用命令:压缩解压命令
  • 原文地址:https://www.cnblogs.com/sevenyuan/p/3154993.html
Copyright © 2011-2022 走看看