原作者 herain_cs,原文链接 http://blog.csdn.net/herain_cs/article/details/8627995
对于CCLayer子类,想响应触屏事件比较简单,init的时候调用setTouchEnable并重载下列函数:
- virtual void registerWithTouchDispatcher(void);
- 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);
典型的registerWithTouchDispatcher实现是:
- void XXLayer::registerWithTouchDispatcher()
- {
- CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,true);
- }
做的事情就是注册触屏事件。
addTargetedDelegate的第一个参数是delegate,就是回调函数执行的对象;第二个参数priority和第三个参数bSwallowsTouches决定多个对象同时注册触屏事件时的行为。具体的意义是:
priority值越小,回调越早被调用。
bSwallowsTouches为true,则ccTouchBegan返回ture以后,其他的回调将不再被调用,就好像触屏事件被吃掉了一样。
ccTouchxx系列函数就是触屏事件的响应函数。
CCLayer提供了一个registerWithTouchDispatcher的默认实现,主要功能相当于
CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this,0)
也是注册触屏事件。但是addStandardDelegate和前面我们使用的addTargetedDelegate有诸多不同。
1.不支持bSwallowsTouches参数,在触屏动作发生时,所有注册了触屏事件的对象的回调函数都会被调用。
2.回调函数定义不同,它的回调函数定义是:
virtualvoid ccTouchesBegan(CCSet *pTouches,CCEvent *pEvent);
virtualvoid ccTouchesMoved(CCSet *pTouches,CCEvent *pEvent);
virtualvoid ccTouchesEnded(CCSet *pTouches,CCEvent *pEvent);
virtualvoid ccTouchesCancelled(CCSet *pTouches,CCEvent *pEvent);
回调函数的第一个参数是CCSet*,另外ccTouchesBegan也不像ccTouchBegan那样有一个bool型的返回值。
网上有人提到支持多点触摸时需要使用addStandardDelegate,暂时还没有研究过。
前面只说了注册事件,没有提注销。CCLayer是在onExit中帮我们做了这件事,子类就不用再处理了。
下面提供一个CCLayer子类响应触屏事件的实例,用cocos2dx template生成Hello world工程后,替换HelloWorldScene.h和HelloWorldScene.cpp即可测试这个例子,这个例子的重点在onEnter函数中,值得仔细思考下。
HelloWorldScene.h:
- #ifndef __HELLOWORLD_SCENE_H__
- #define __HELLOWORLD_SCENE_H__
- #include "cocos2d.h"
- #include "cocos-ext.h"
- USING_NS_CC;
- USING_NS_CC_EXT;
- class HelloWorld : public cocos2d::CCLayer
- {
- public:
- // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
- virtual bool init();
- // there's no 'id' in cpp, so we recommand to return the exactly class pointer
- static cocos2d::CCScene* scene();
- // a selector callback
- void menuCloseCallback(CCObject* pSender);
- // implement the "static node()" method manually
- CREATE_FUNC(HelloWorld);
- public:
- virtual void onEnter();
- virtual void registerWithTouchDispatcher();
- 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);
- private:
- // 菜单回调
- void menu1Callback(CCNode *pSender);
- void menu2Callback(CCNode *pSender);
- private:
- CCMenu *menu;
- CCScrollView *scrollView;
- };
- #endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp
- #include "HelloWorldScene.h"
- #include "SimpleAudioEngine.h"
- using namespace cocos2d;
- using namespace CocosDenshion;
- USING_NS_CC_EXT;
- CCScene* HelloWorld::scene()
- {
- // 'scene' is an autorelease object
- CCScene *scene = CCScene::create();
- // 'layer' is an autorelease object
- HelloWorld *layer = HelloWorld::create();
- // add layer as a child to scene
- scene->addChild(layer);
- // return the scene
- return scene;
- }
- // on "init" you need to initialize your instance
- bool HelloWorld::init()
- {
- //
- // 1. super init first
- if ( !CCLayer::init() )
- {
- return false;
- }
- setTouchEnabled(true);
- /
- // 3. add your codes below...
- // ask director the window size
- CCSize size = CCDirector::sharedDirector()->getWinSize();
- // CCScrollView
- scrollView = CCScrollView::create();
- CCLayer *layer = CCLayer::create();
- CCSprite *sprite1 = CCSprite::create("HelloWorld.png");
- CCSprite *sprite2 = CCSprite::create("HelloWorld.png");
- layer->setAnchorPoint(ccp(0, 0));
- layer->setPosition(ccp(0, 0));
- // Menu
- CCMenuItemSprite *menuItem1 = CCMenuItemSprite::create(sprite1, sprite1, this, menu_selector(HelloWorld::menu1Callback));
- float scale = 0.5;
- CCSize itemSize(sprite1->getTextureRect().size);
- menuItem1->setPosition(ccpAdd(CCPointZero, ccp(itemSize.width*scale / 2, itemSize.height*scale / 2)));
- menuItem1->setScale(scale);
- CCMenuItemSprite *menuItem2 = CCMenuItemSprite::create(sprite2, sprite2, this, menu_selector(HelloWorld::menu2Callback));
- // menuItem2->setPosition(ccpAdd(ccp(480, 0), ccp(size.width / 2, size.height / 2)));
- menuItem2->setPosition(ccp(itemSize.width*scale*3/2, itemSize.height*scale / 2));
- menuItem2->setScale(scale);
- menu = CCMenu::create(menuItem1, menuItem2, NULL);
- menu->setPosition(CCPointZero);
- layer->addChild(menu);
- layer->setContentSize(CCSizeMake(itemSize.width*2*scale, 320));
- scrollView->setPosition(ccp(0,0));
- scrollView->setContentOffset(CCPointZero);
- scrollView->setContentSize(CCSizeMake(640, 320));
- scrollView->setContainer(layer);
- scrollView->setDirection(kCCScrollViewDirectionHorizontal);
- this->addChild(scrollView);
- return true;
- }
- void HelloWorld::onEnter() {
- CCLayer::onEnter();
- //这里是重点,尝试注释掉它然后再执行程序,看左右拖动图片时行为有什么变化。
- menu->setHandlerPriority(1);
- }
- void HelloWorld::menuCloseCallback(CCObject* pSender)
- {
- CCDirector::sharedDirector()->end();
- #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
- exit(0);
- #endif
- }
- void HelloWorld::registerWithTouchDispatcher()
- {
- CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, false);
- }
- bool HelloWorld::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
- {
- return true;
- }
- void HelloWorld::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
- {
- CCLOG("move");
- }
- void HelloWorld::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
- {
- }
- void HelloWorld::ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
- {
- }
- void HelloWorld::menu1Callback(cocos2d::CCNode *pSender)
- {
- CCLOG("menu1Callback");
- }
- void HelloWorld::menu2Callback(cocos2d::CCNode *pSender)
- {
- CCLOG("menu2Callback");
- }