起因: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;
}
}
}