创建了许多CCSprits,但触发时ccTouchBegan提供了最后一个 [英] Created many CCSprits but when triggering ccTouchBegan gives the last one allways

查看:90
本文介绍了创建了许多CCSprits,但触发时ccTouchBegan提供了最后一个的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

UPDATE 我改为更简单的例子



好的,现在我真的很困惑,我简化了类,因为我在网上阅读建议是扩展CCNode更好,然后CCSprite
并保持它作为CCNode
的成员,这里是基于Hello cpp的非常simpleminded示例。

问题还原相同,当触摸任何宝石实例,我打印最后一个宝石添加,为什么?

i期望每个Touchwill给我正确的实例,有豆接触(我打印id和名称)



Im使用cocos2d-2.1rc0-x-2.1.3 c ++,我有一些奇怪,我创建了10个CCSprites。
i有类扩展CCSprite和CCTargetedTouchDelegate像这样:



Gem.cpp

  #includeGem.h
Gem :: Gem()
{

;

}
Gem ::〜Gem()
{
;
}

void Gem :: onEnter()
{

CCDirector * pDirector = CCDirector :: sharedDirector
pDirector-> getTouchDispatcher() - > addTargetedDelegate(this,0,true);
CCNode :: onEnter();

}
void Gem :: onExit()
{
CCDirector * pDirector = CCDirector :: sharedDirector
pDirector-> getTouchDispatcher() - > removeDelegate(this);
CCNode :: onExit();
}
bool Gem :: ccTouchBegan(CCTouch * touch,CCEvent * event)
{
CCPoint touchPoint = touch-> getLocation
CCLOG(Gem Touched!ImageName:%s | GemId:%sx:%f,y:%f myspriteX:%f,myspriteY:%f nodePosX:%f nodePosY:%f,this-> getImageName().c_str(),this-> getGemId().c_str(),touchPoint.x,touchPoint.y,getGemSprite() - > getPositionX(),getGemSprite() > getPositionX(),this-> getPositionY());
return true;
}
void Gem :: ccTouchMoved(CCTouch * touch,CCEvent * event)
{
CCPoint touchPoint = touch-> getLocation
}
void Gem :: ccTouchEnded(CCTouch * touch,CCEvent * event)
{

}
pre>

Gem.h

  class Gem:public CCNode CCTargetedTouchDelegate 
{
public:
Gem();

virtual〜Gem();

CC_SYNTHESIZE(std :: string,imageName,ImageName)
CC_SYNTHESIZE(std :: string,gemId,GemId)
CC_SYNTHESIZE(CCPoint,gemPos,GemPos)
CC_SYNTHESIZE(CCSprite *,gemSprite,GemSprite)

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);


};



helloWorldScene.cpp init()方法

  bool HelloWorld :: init()
{
bool bRet = false;
//////////////////////////////////////////////// ////////////////////////////
// super init first
///////// ////////////////////////////////////////////////// ///////////////

if(!CCLayer :: init())
return false;

CCSize m_winSize;
CCSize visibleSize;
CCP origin origin;
m_winSize = CCDirector :: sharedDirector() - > getWinSize();
visibleSize = CCDirector :: sharedDirector() - > getVisibleSize();
origin = CCDirector :: sharedDirector() - > getVisibleOrigin();

CCSpriteFrameCache :: sharedSpriteFrameCache() - > addSpriteFramesWithFile(sprites.plist,sprites.png);
CCSpriteBatchNode * gameBatchNode = CCSpriteBatchNode :: create(sprites.png/ *,200 * /);
CCSprite * bg = CCSprite :: create(grideFinal.png);
// bg-> setAnchorPoint(ccp(0,0));
bg-> setPosition(ccp(visibleSize.width / 2 + origin.x,visibleSize.height / 2 + origin.y));
this-> addChild(bg,1);

Gem * gem1 = new Gem();
gem1-> retain();
gem1> setGemId(gem1);
gem1-> setImageName(img_1);
gem1-> setGemSprite(CCSprite :: createWithSpriteFrameName(gem1.png));
Gem * gem2 = new Gem();
gem2-> retain();
gem2-> setGemId(gem2);
gem2-> setImageName(img_2);
gem2-> setGemSprite(CCSprite :: createWithSpriteFrameName(gem2.png));

gem1-> setAnchorPoint(ccp(0,0));
gem2-> setAnchorPoint(ccp(0,0));

gem1-> setPosition(ccp(0,0));
gem2-> setPosition(ccp(gem1-> getGemSprite() - > getContentSize()。width,40)

gem1-> getGemSprite() - > setAnchorPoint(ccp(0,0));
gem2-> getGemSprite() - > setAnchorPoint(ccp(0,0));
gem1-> getGemSprite() - > setPosition(ccp(0,0));
gem2-> getGemSprite() - > setPosition(ccp(gem1-> getGemSprite() - > getContentSize()。width,40)
// gameBatchNode-> addChild(gem1-> getGemSprite(),4,44);
// gameBatchNode-> addChild(gem2-> getGemSprite(),4,45);
this-> addChild(gameBatchNode);

bg-> addChild(gem1-> getGemSprite(),50);
bg-> addChild(gem2-> getGemSprite(),50);
bg-> addChild(gem1,50);
bg-> addChild(gem2,50);

bRet = true;


return bRet;
}

每一件事情都很好,除非我触摸屏幕并触发Gem :: ccTouchBegan方法。它总是给我最后一个CCSprite(和我有50在屏幕上
为什么是这里?这里丢失了什么?

解决方案

因为每个 Gem 实例扩展 CCTargetedTouchDelegate 并注册触摸调度器,所以只会触发最高或最新添加。



那么正确的方法是在中实现 CCTargetedTouchDelegate HelloWorld class,当触摸发生时,检查哪个 Gem 被触摸点触摸。



用于检查触摸是否在某个节点:

  bool Gem :: isTouchInside(CCTouch * pTouch)
{
CCPoint touchLocation = pTouch-> getLocation();
CCRect rect =
CCRectApplyAffineTransform(CCRectMake(0,
0,
this-> getContentSize ,
this-> getContentSize()。height),
this-> nodeToWorldTransform());
return rect.containsPoint(touchLocation);
}


UPDATE i changed to more simpler example

Ok , now i really puzzled i simplified the class as as i was reading on the net the suggestion was to extend CCNode better then CCSprite and keep it as member of the CCNode so here is the very simpleminded example based on the Hello cpp.
the problem remine the same , when touching any of the Gem instances i get printed the last Gem added , why ??
i expect that each Touchwill give me the correct instance that have bean touched ( i print id and name )

Im using cocos2d-2.1rc0-x-2.1.3 c++ , and i have something strange i created 10 CCSprites. i have class that extend CCSprite and CCTargetedTouchDelegate like this :

Gem.cpp

#include "Gem.h"
Gem::Gem()
{

   ;

}
Gem::~Gem()
{
    ;
}

void Gem::onEnter()
{

    CCDirector* pDirector = CCDirector::sharedDirector();
    pDirector->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
    CCNode::onEnter();

}
void Gem::onExit()
{  
    CCDirector* pDirector = CCDirector::sharedDirector();
    pDirector->getTouchDispatcher()->removeDelegate(this);
    CCNode::onExit();    
} 
bool Gem::ccTouchBegan(CCTouch* touch, CCEvent* event)
{       
    CCPoint touchPoint = touch->getLocation();   
    CCLOG("Gem Touched! ImageName:%s |GemId:%s  x:%f ,y:%f myspriteX:%f, myspriteY:%f nodePosX:%f nodePosY:%f",this->getImageName().c_str(),this->getGemId().c_str(),touchPoint.x,touchPoint.y,getGemSprite()->getPositionX(),getGemSprite()->getPositionY(),this->getPositionX(),this->getPositionY());
    return true;
}
void Gem::ccTouchMoved(CCTouch* touch, CCEvent* event)
{
    CCPoint touchPoint = touch->getLocation();  
}
void Gem::ccTouchEnded(CCTouch* touch, CCEvent* event)
{

}

Gem.h

class Gem :public CCNode , public CCTargetedTouchDelegate 
{
public:
    Gem();

    virtual ~Gem();

    CC_SYNTHESIZE(std::string,imageName,ImageName)
    CC_SYNTHESIZE(std::string,gemId,GemId)
    CC_SYNTHESIZE(CCPoint,gemPos,GemPos)
    CC_SYNTHESIZE(CCSprite*,gemSprite,GemSprite)

    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);


};

The helloWorldScene.cpp init() method

bool HelloWorld::init()
{
       bool bRet = false;
        //////////////////////////////////////////////////////////////////////////
        // super init first
        //////////////////////////////////////////////////////////////////////////

       if(!CCLayer::init())
        return false;

        CCSize m_winSize;
        CCSize visibleSize;
        CCPoint origin;
        m_winSize = CCDirector::sharedDirector()->getWinSize();
        visibleSize = CCDirector::sharedDirector()->getVisibleSize();
        origin = CCDirector::sharedDirector()->getVisibleOrigin();

        CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("sprites.plist","sprites.png");
        CCSpriteBatchNode* gameBatchNode  = CCSpriteBatchNode::create("sprites.png"/*,200*/);
        CCSprite *bg= CCSprite::create("grideFinal.png");
        //bg->setAnchorPoint(ccp(0,0));
        bg->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
        this->addChild(bg,1);

        Gem* gem1 = new Gem();
        gem1->retain();
        gem1->setGemId("gem1");
        gem1->setImageName("img_1");
        gem1->setGemSprite(CCSprite::createWithSpriteFrameName("gem1.png"));
        Gem* gem2 = new Gem();
        gem2->retain();
        gem2->setGemId("gem2");
        gem2->setImageName("img_2");
        gem2->setGemSprite(CCSprite::createWithSpriteFrameName("gem2.png"));

        gem1->setAnchorPoint(ccp(0,0));
        gem2->setAnchorPoint(ccp(0,0));

        gem1->setPosition(ccp(0,0));
        gem2->setPosition(ccp(gem1->getGemSprite()->getContentSize().width,40));

        gem1->getGemSprite()->setAnchorPoint(ccp(0,0));
        gem2->getGemSprite()->setAnchorPoint(ccp(0,0));
        gem1->getGemSprite()->setPosition(ccp(0,0));
        gem2->getGemSprite()->setPosition(ccp(gem1->getGemSprite()->getContentSize().width,40));
        //gameBatchNode->addChild(gem1->getGemSprite(),4,44);
        //gameBatchNode->addChild(gem2->getGemSprite(),4,45);
        this->addChild(gameBatchNode);

        bg->addChild(gem1->getGemSprite(),50);
        bg->addChild(gem2->getGemSprite(),50);
        bg->addChild(gem1,50);
        bg->addChild(gem2,50);

        bRet = true;


    return bRet;
}

Every thing is woring fine except when i touch the screen and trigger Gem::ccTouchBegan method. its always gives me the last CCSprite ( and i have like 50 on the screen why is that ? what im missing here ?

解决方案

Because every Gem instance extend CCTargetedTouchDelegate and register touch dispatcher, only the highest or latest added will be triggered.

So what the correct way is implement CCTargetedTouchDelegate in HelloWorld class, and when touch occur, check which Gem is touched by touch point.

Here is a method used for checking if touch is in some node:

bool Gem::isTouchInside(CCTouch* pTouch)
{
    CCPoint touchLocation = pTouch->getLocation();
    CCRect rect =
    CCRectApplyAffineTransform(CCRectMake(0 ,
                                          0 ,
                                          this->getContentSize().width,
                                          this->getContentSize().height),
                               this->nodeToWorldTransform());
    return rect.containsPoint(touchLocation);
}

这篇关于创建了许多CCSprits,但触发时ccTouchBegan提供了最后一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆