• cocos2dx基础篇(7) 触碰事件


        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、运行结果

    wKioL1PzS6fQI6SVAAb7815Wxrw807.gif


    【多点触碰】

        多点触碰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、运行结果

    wKiom1PzWOfTmCYbAAusxeY8uuc353.gif

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


    两类触碰的区别】

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

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

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

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

  • 相关阅读:
    .NET设计模式系列文章《转》
    sharpwebmail邮件管理系统开源 下载及使用方法
    POJ 1949 DP?
    POJ 1948 DP
    POJ 1945 暴搜+打表 (Or 暴搜+判重)
    POJ 1944 并查集(模拟)
    POJ 3259 Wormholes SPFA判负环
    POJ 3268 Dijkstra+priority_queue或SPFA
    POJ 3299 模拟
    POJ 3342 树形DP+Hash
  • 原文地址:https://www.cnblogs.com/lmx282110xxx/p/10798735.html
Copyright © 2020-2023  润新知