c++ - 创建了许多 CCSprit,但触发 ccTouchBegan 时总是给出最后一个

标签 c++ cocos2d-x

更新我更改为更简单的示例

好吧,现在我真的很困惑,我简化了这个类,因为我在网上读到的建议是比 CCSprite 更好地扩展 CCNode 并将其保留为 CCNode 的成员 这是基于 Hello cpp 的非常简单的示例。
问题再次出现,当触摸任何 Gem 实例时,我会打印最后添加的 Gem,为什么??
我希望每个 Touch 都会给我一个已被 bean 触摸的正确实例(我打印 id 和名称)

我正在使用 cocos2d-2.1rc0-x-2.1.3 c++ ,我有一些奇怪的东西,我创建了 10 个 CCSprites。 我有一个扩展 CCSprite 和 CCTargetedTouchDelegate 的类,如下所示:

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


};

helloWorldScene.cpp init() 方法

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

除了当我触摸屏幕并触发 Gem::ccTouchBegan 方法时,一切都运行良好。它总是给我最后一个CCSprite(我在屏幕上有大约50个 这是为什么 ?我在这里缺少什么?

最佳答案

由于每个 Gem 实例都扩展 CCTargetedTouchDelegate 并注册触摸调度程序,因此只有最高或最新添加的实例才会被触发。

那么正确的做法是在HelloWorld类中实现CCTargetedTouchDelegate,当触摸发生时,检查触摸点触摸了哪个Gem

这是一个用于检查触摸是否在某个节点中的方法:

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

关于c++ - 创建了许多 CCSprit,但触发 ccTouchBegan 时总是给出最后一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18188095/

相关文章:

c++ - 使用 COCOS2D-X 的文件 I/O

opengl-es - Opengl Shader,gl_FragColor的alpha组件是什么?

c++ - 声音分析库?

c++ - 当算法需要派生类的知识时,将算法与数据解耦

c++ - 我已经创建了一个 Sprite 并使用相同的引用将它们添加到场景中,现在,我如何在不使用标签的情况下删除它们?

android - 如何在 ./build_native.sh 文件中将 -fpermissive 参数传递给编译器?

c++ - cocos2d-x v3 c++ 投影 cocos2d::Sprite

c++ - 访问 COM 对象中的不透明数据成员

c++ - 在 constexpr 中使用 strcmp 的编译器差异

c++ - 析构函数可以在 const 对象上调用非常量函数吗?