Cocos2d-x 可响应触碰事件的 CCSprite

起因:CCMenuItem 和拖拽放缩父层有冲突。下面直接上代码

Macros.h

//
//  Macros.h
//  TouchSpriteDemo
//
//  Created by kodeyang on 8/13/13.
//
//

#ifndef TouchSpriteDemo_Macros_h
#define TouchSpriteDemo_Macros_h

/**
 * 由层出景~
 */
#define SCENE_FUNC(__TYPE__) \
static CCScene* scene() \
{ \
CCScene* t_pScene = CCScene::create(); \
__TYPE__* t_pLayer = __TYPE__::create(); \
t_pScene->addChild(t_pLayer); \
return t_pScene; \
}

#endif
TouchSprite.h

//
//  TouchSprite.h
//  TouchSpriteDemo
//
//  Created by kodeyang on 13-2-23.
//
//

#ifndef __TouchSpriteDemo__TouchSprite__
#define __TouchSpriteDemo__TouchSprite__

#define UINT_OPACITY_HALF       128
#define UINT_OPACITY_FULL       255
#define UINT_OPACITY_CLICKED    254

#include "cocos2d.h"

using namespace cocos2d;

/**
 * 调整该类对象的 scale 值不会对触摸检测产生影响~
 * 为了避免不必要的转型,没有新增成员来标识该精灵是否被点击,
 * 采用了一种折中的方式来达到目的 —— 点击过的精灵我将其 Opacity 成员赋值为 254。
 */
class TouchSprite : public CCSprite, public CCTouchDelegate {
    
public:
    
    static TouchSprite* create(const char* in_pArrCharName);
    
public:
    
    virtual void onEnter();
    
    virtual void onExit();
    
    virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
    
    virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);
    
    virtual void ccTouchEnded(CCTouch* touch, CCEvent* event);
    
private:
    
    CCPoint m_oPntPosi;
};


#endif /* defined(__TouchSpriteDemo__TouchSprite__) */
TouchSprite.cpp

//
//  TouchSprite.cpp
//  TouchSpriteDemo
//
//  Created by kodeyang on 13-2-23.
//
//

#include "TouchSprite.h"

TouchSprite* TouchSprite::create(const char* in_pArrCharName) {
    TouchSprite* t_pTouchSprite = new TouchSprite();
    if (t_pTouchSprite && t_pTouchSprite->initWithFile(in_pArrCharName)) {
        t_pTouchSprite->autorelease();
        return t_pTouchSprite;
    }
    CC_SAFE_DELETE(t_pTouchSprite);
    return NULL;
}

void TouchSprite::onEnter() {
    CCDirector* t_pDirector = CCDirector::sharedDirector();
    t_pDirector->getTouchDispatcher()->addTargetedDelegate(this, 0, false);
    CCSprite::onEnter();
}

void TouchSprite::onExit() {
    CCDirector* t_pDirector = CCDirector::sharedDirector();
    t_pDirector->getTouchDispatcher()->removeDelegate(this);
    CCSprite::onExit();
}

bool TouchSprite::ccTouchBegan(CCTouch* in_pTouch, CCEvent* in_pEvent) {
    bool t_bTarget;
    
    float t_fX = getPositionX() - getContentSize().width * getAnchorPoint().x;
    float t_fY = getPositionY() - getContentSize().height * getAnchorPoint().y;
    float t_fW = getContentSize().width;
    float t_fH = getContentSize().height;
    
    CCRect t_oRect = CCRect(t_fX, t_fY, t_fW, t_fH);
    t_oRect.origin = CCPointZero;
    
    CCPoint t_oPntPosi = convertTouchToNodeSpace(in_pTouch);
    
    bool t_bIsTouched = t_oRect.containsPoint(t_oPntPosi);
    if (t_bIsTouched) {
//        printf("触发,x = %d, y = %d\n", (int)t_oPntPosi.x, (int)t_oPntPosi.y);
        setOpacity(UINT_OPACITY_HALF);
        m_oPntPosi = in_pTouch->getLocationInView();

        t_bTarget = true;
    } else {
//        printf("未触发,x = %d, y = %d\n", (int)t_oPntPosi.x, (int)t_oPntPosi.y);
        t_bTarget = false;
    }
    
    return t_bTarget;
}

void TouchSprite::ccTouchMoved(CCTouch* touch, CCEvent* event) {
    
}

void TouchSprite::ccTouchEnded(CCTouch* pTouch, CCEvent* event) {
    CCPoint t_oPntLoc = pTouch->getLocationInView();
    if (m_oPntPosi.x == t_oPntLoc.x && m_oPntPosi.y == t_oPntLoc.y) {
        setOpacity(UINT_OPACITY_CLICKED);
    } else {
        setOpacity(UINT_OPACITY_FULL);
    }
}
TouchSpriteLayer.h

//
//  TouchSpriteLayer.h
//  TouchSpriteDemo
//
//  Created by kodeyang on 8/7/13.
//
//

#ifndef __TouchSpriteDemo__TouchSpriteLayer__
#define __TouchSpriteDemo__TouchSpriteLayer__

#include "cocos2d.h"
#include "Macros.h"

using namespace cocos2d;

class TouchSpriteLayer : public CCLayer {
    
public:
    
    SCENE_FUNC(TouchSpriteLayer);
    
    CREATE_FUNC(TouchSpriteLayer);
    
    virtual bool init();
    
    virtual void registerWithTouchDispatcher();
    
    virtual bool ccTouchBegan(CCTouch* in_pTouch, CCEvent* in_pEvent); //这个方法必须实现
    
    virtual void ccTouchEnded(CCTouch* in_pTouch, CCEvent* in_pEvent);
    
    virtual void ccTouchMoved(CCTouch* in_pTouch, CCEvent* in_pEvent);
    
private:
    
    void compute(const CCPoint& in_oPntDest, CCPoint& out_oPntResult);
    
private:    
    
    CCLayer* m_pLyrMain;
    
    CCSprite* m_pSpMain;
    
    // “显示窗口” 的半宽、半高~
    float m_fRestrictHalfWidth;
    float m_fRestrictHalfHeight;
    
    // 背景精灵的半宽、半高~
    float m_fSpMainHalfWidth;
    float m_fSpMainHalfHeight;
    
    CCPoint m_oPntPrevPosi;
    
};

#endif /* defined(__TouchSpriteDemo__TouchSpriteLayer__) */
TouchSpriteLayer.cpp

//
//  TouchSpriteLayer.cpp
//  TouchSpriteDemo
//
//  Created by kodeyang on 8/7/13.
//
//

#include "TouchSpriteLayer.h"
#include "TouchSprite.h"

#define TAG_SPRITE_0    100
#define TAG_SPRITE_1    101
#define TAG_SPRITE_2    102
#define TAG_SPRITE_3    103

bool TouchSpriteLayer::init() {
    
    if (!CCLayer::init()) {
        return false;
    }
    
    CCSize t_oSize = CCDirector::sharedDirector()->getWinSize();
    
    m_pLyrMain = CCLayer::create();
    m_pLyrMain->setPosition(ccp(t_oSize.width * 0.5f, t_oSize.height * 0.5f));
    this->addChild(m_pLyrMain);
    
	/**
	 * Begin of Auto-Generated Code
	 */
	m_pSpMain = CCSprite::create("bg.png");
	m_pSpMain->setPosition(CCPointZero);
	m_pLyrMain->addChild(m_pSpMain, 0);
    
	CCSprite* t_pSpsprite0 = TouchSprite::create("sprite0.png");
    t_pSpsprite0->setTag(TAG_SPRITE_0);
	t_pSpsprite0->setPosition(ccp(474, 397));
	m_pSpMain->addChild(t_pSpsprite0, 0);
    
	CCSprite* t_pSpsprite1 = TouchSprite::create("sprite1.png");
    t_pSpsprite1->setTag(TAG_SPRITE_1);
	t_pSpsprite1->setPosition(ccp(206, 653));
	m_pSpMain->addChild(t_pSpsprite1, 0);
    
	CCSprite* t_pSpsprite2 = TouchSprite::create("sprite2.png");
    t_pSpsprite2->setTag(TAG_SPRITE_2);
	t_pSpsprite2->setPosition(ccp(800, 583));
	m_pSpMain->addChild(t_pSpsprite2, 0);
    
	CCSprite* t_pSpsprite3 = TouchSprite::create("sprite3.png");
    t_pSpsprite3->setTag(TAG_SPRITE_3);
	t_pSpsprite3->setPosition(ccp(396, 115));
	m_pSpMain->addChild(t_pSpsprite3, 0);
	/**
	 * End of Auto-Generated Code
	 */
    
    // 保存半宽和半高~
    m_fSpMainHalfWidth = m_pSpMain->getContentSize().width * 0.5f;
    m_fSpMainHalfHeight = m_pSpMain->getContentSize().height * 0.5f;
    
    // 窗口的 h(如果屏幕顶部和底部有 banner,那么这里 “窗口的 h” 则为屏幕的 h 减去底部 h 再减去顶部 h)
    m_fRestrictHalfWidth = t_oSize.width * 0.5f;
    m_fRestrictHalfHeight = t_oSize.height * 0.5f;
    
    // 开启触控~
    this->setTouchEnabled(true);
    
    return true;
}

/**
 * 必须要实现,必须要按如下这么写,不然触摸无法响应~
 * 这里说一下,正常的监听者模式需要:使用前注册,使用后移除!当我们继承和实现了 registerWithTouchDispatcher
 * 那么移除的操作会自动在OnExit时候执行,不需要我们去关心!
 */
void TouchSpriteLayer::registerWithTouchDispatcher() {
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
}


bool TouchSpriteLayer::ccTouchBegan(CCTouch* in_pTouch, CCEvent* in_pEvent) {
    m_oPntPrevPosi = convertTouchToNodeSpace(in_pTouch);
    return true;
}


void TouchSpriteLayer::ccTouchMoved(CCTouch* in_pTouch, CCEvent* in_pEvent) {
    CCPoint tmp_oPntTouchPosi = convertTouchToNodeSpace(in_pTouch);
    
    CCPoint tmp_oPntOffset = ccpSub(tmp_oPntTouchPosi, m_oPntPrevPosi);
    CCPoint tmp_oPntCurrPosi = m_pSpMain->getPosition();
    CCPoint tmp_oPntDest = ccpAdd(tmp_oPntCurrPosi, tmp_oPntOffset);
    
    CCPoint tmp_oPntResult;
    compute(tmp_oPntDest, tmp_oPntResult);
    m_pSpMain->setPosition(tmp_oPntResult);
    
    m_oPntPrevPosi = tmp_oPntTouchPosi;
}

void TouchSpriteLayer::ccTouchEnded(CCTouch* in_pTouch, CCEvent* in_pEvent) {
    
    // 处理触摸建筑事件~
    CCArray* t_pCcArrChildren = m_pSpMain->getChildren();
    for (int i = 0; i < t_pCcArrChildren->count(); i ++) {
        CCSprite* tmp_pSprite = (CCSprite*)t_pCcArrChildren->objectAtIndex(i);
        if (tmp_pSprite->getOpacity() == UINT_OPACITY_CLICKED) {
            tmp_pSprite->setOpacity(UINT_OPACITY_FULL);
            switch (tmp_pSprite->getTag()) {
                case TAG_SPRITE_0: {
                    printf("TAG_SPRITE_0\n");
                    break;
                }
                    
                case TAG_SPRITE_1: {
                    printf("TAG_SPRITE_1\n");
                    break;
                }
                    
                case TAG_SPRITE_2: {
                    printf("TAG_SPRITE_2\n");
                    break;
                }
                    
                case TAG_SPRITE_3: {
                    printf("TAG_SPRITE_3\n");
                    break;
                }
                    
                default:
                    break;
            }
        }
    }
}

void TouchSpriteLayer::compute(const CCPoint& in_oPntDest, CCPoint& out_oPntResult) {
    // 当前的放缩尺寸~
    float tmp_fCurrScale = m_pSpMain->getScale();
    float tmp_fLimitX = fabsf(m_fSpMainHalfWidth * tmp_fCurrScale - m_fRestrictHalfWidth);
    float tmp_fLimitY = fabsf(m_fSpMainHalfHeight * tmp_fCurrScale - m_fRestrictHalfHeight);
    
    // 横坐标~
    if (in_oPntDest.x > 0) {
        if (in_oPntDest.x <= tmp_fLimitX) {
            out_oPntResult.x = in_oPntDest.x;
        } else {
            out_oPntResult.x = tmp_fLimitX;
        }
    } else {
        if (in_oPntDest.x >= -tmp_fLimitX) {
            out_oPntResult.x = in_oPntDest.x;
        } else {
            out_oPntResult.x = -tmp_fLimitX;
        }
    }
    
    // 纵坐标~
    if (in_oPntDest.y > 0) {
        if (in_oPntDest.y <= tmp_fLimitY) {
            out_oPntResult.y = in_oPntDest.y;
        } else {
            out_oPntResult.y = tmp_fLimitY;
        }
    } else {
        if (in_oPntDest.y >= -tmp_fLimitY) {
            out_oPntResult.y = in_oPntDest.y;
        } else {
            out_oPntResult.y = -tmp_fLimitY;
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值