Cocos2d-x 3.2 EventListener在子精灵中不工作

Cocos2d-x 3.2 EventListener not working in child Sprite

本文关键字:精灵 工作 EventListener Cocos2d-x      更新时间:2023-10-16

简单地说,我有两个精灵,其中一个是另一个的子精灵。与每个精灵相关的事件侦听器,如所述。

如果两个精灵都是层的子节点,那么一切都很好。

现在我需要第二个精灵是第一个精灵的子节点。但在这种情况下,第二个精灵通常不会响应事件。

我很恐慌,不知道出了什么问题,也不知道怎么解决。请帮助。

下面是一个简化的例子:

. h

    #ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
class HelloWorld : public cocos2d::Layer
{
public:
    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::Scene* createScene();
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  
    // a selector callback
    void menuCloseCallback(cocos2d::Ref* pSender);
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
};
class PlaySprite : public cocos2d::Sprite
{
public:
    virtual bool init();
    CREATE_FUNC(PlaySprite);
    void addEvent();
    bool touchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
};
class InPlaySprite : public cocos2d::Sprite
{
public:
    virtual bool init();
    CREATE_FUNC(InPlaySprite);
    void addEvent();
    bool touchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
};
#endif // __HELLOWORLD_SCENE_H__

. cpp

    #include "HelloWorldScene.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();
    // 'layer' is an autorelease object
    auto 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()
{
    if ( !Layer::init() )
    {
        return false;
    }
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    // add a "close" icon to exit the progress. it's an autorelease object
    auto closeItem = MenuItemImage::create(
                                           "CloseNormal.png",
                                           "CloseSelected.png",
                                           CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
    closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
                                origin.y + closeItem->getContentSize().height/2));
    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu, 1);
    /////////////////////////////
    // 3. add your codes below...

    auto sprite1 = PlaySprite::create();
    this->addChild(sprite1);
    auto sprite2 = InPlaySprite::create();
    // !!!
    sprite1->addChild(sprite2);
    return true;
}

void HelloWorld::menuCloseCallback(Ref* pSender)
{
    Director::getInstance()->end();
}

bool PlaySprite::init()
{
    if(!Sprite::init())
        return false;
    // to do
    Size visibleSize = Director::getInstance()->getVisibleSize();
    this->setTexture("1.png");
    this->setPosition(visibleSize.width / 2, visibleSize.height / 2);
    this->addEvent();
    return true;
}
void PlaySprite::addEvent()
{
    auto listener = EventListenerTouchOneByOne::create();
    listener->setSwallowTouches(true);
    listener->onTouchBegan = [=](Touch* touch, Event* event)
        {
            return this->touchBegan(touch, event);
        };
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
}
bool PlaySprite::touchBegan(Touch* touch, Event* event)
{
    auto target = (Sprite* ) event->getCurrentTarget();
    auto rect = this->getBoundingBox();
    if(rect.containsPoint(touch->getLocation()))
    {
        this->setTexture("1d.png");
        return true;
    }
    return false;
}

bool InPlaySprite::init()
{
    if(!Sprite::init())
        return false;
    // to do
    Size visibleSize = Director::getInstance()->getVisibleSize();
    this->setTexture("2.png");
    this->setPosition(150.0f, 150.0f);
    this->addEvent();
    return true;
}
void InPlaySprite::addEvent()
{
    auto listener = EventListenerTouchOneByOne::create();
    listener->setSwallowTouches(true);
    listener->onTouchBegan = [=](Touch* touch, Event* event)
        {
            return this->touchBegan(touch, event);
        };
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
}
bool InPlaySprite::touchBegan(Touch* touch, Event* event)
{
//  auto target = (Sprite* ) event->getCurrentTarget();
    auto rect = this->getBoundingBox();
    if(rect.containsPoint(touch->getLocation()))
    {
        this->setTexture("2d.png");
        return true;
    }
    return false;
}

类PlaySprite和InPlaySprite是非常相似的,因为这是一个非常简单的例子。

我认为你的问题是,当你调用

时,你正在吞食父精灵中的触摸事件。
listener->setSwallowTouches(true);

如果您在PlaySprite::addEvent()内部调用false,我怀疑事情会为您解决。