cocos 新手引導之事件穿透


游戲中新手引導 一般都是通過蒙版然后突出某一位置,並配合相應動畫來實現的。遮罩層有兩個需求,一是可以挖個洞,二是這個洞事件可以穿透,

其他區域不能穿透。如果事件不能穿透,那就需要做很多工作來處理相應的響應。穿透之后實際點的就是那個位置,只需要處理遮罩部分應該有的行為

 

研究了cocos2dx 3.1 的事件系統,發現雖然不能原生支持,但我們可以簡單擴展一下就能達到我們的目的

下邊是源代碼:

LayoutTouchBreak.h

class LayoutTouchBreak: public Layout
{
    DECLARE_CLASS_GUI_INFO

public:
    LayoutTouchBreak();
    LayoutTouchBreak(Layout* widget);

    static LayoutTouchBreak* create();
    static LayoutTouchBreak* createWithLayout( Layout* widget );


    ~LayoutTouchBreak();

    void setBreakArea( Rect& rect );

CC_CONSTRUCTOR_ACCESS:
    virtual bool init() override;

protected:
    virtual bool onTouchBegan(Touch *touch, Event *unusedEvent) override;
    virtual void onTouchMoved(Touch *touch, Event *unusedEvent) override;
    virtual void onTouchEnded(Touch *touch, Event *unusedEvent) override;
    virtual void onTouchCancelled(Touch *touch, Event *unusedEvent) override;

    virtual Widget* createCloneInstance() override;
private:

    //觸摸是否在穿透區域內
    bool touchInBreakArea(Touch *touch);

    // 觸摸事件如果在這個矩形區域內,則可以穿透 繼續傳遞下去
    Rect _breakArea;
};

 

 

LayoutTouchBreak.cpp

IMPLEMENT_CLASS_GUI_INFO(LayoutTouchBreak)

LayoutTouchBreak::LayoutTouchBreak()
{

}

LayoutTouchBreak::LayoutTouchBreak(Layout* widget)
{
    copySpecialProperties(widget);
}

LayoutTouchBreak::~LayoutTouchBreak()
{

}

LayoutTouchBreak* LayoutTouchBreak::create()
{
    LayoutTouchBreak* layoutTouchBreak = new LayoutTouchBreak();
    if (layoutTouchBreak && layoutTouchBreak->init())
    {
        layoutTouchBreak->autorelease();
        return layoutTouchBreak;
    }
    CC_SAFE_DELETE(layoutTouchBreak);
    return nullptr;
}

LayoutTouchBreak* LayoutTouchBreak::createWithLayout( Layout* widget )
{
    if (widget == nullptr)
    {
        return nullptr;
    }

    LayoutTouchBreak* l = create();
    if (l)
    {
        l->copyProperties(widget);
        l->copySpecialProperties(widget);
    }
    return l;
}

Widget* LayoutTouchBreak::createCloneInstance()
{
    return LayoutTouchBreak::create();
}


void LayoutTouchBreak::setBreakArea(Rect& rect)
{
    _breakArea = rect;
}

bool LayoutTouchBreak::onTouchBegan(Touch *touch, Event *unusedEvent)
{
    bool hitted = Layout::onTouchBegan(touch, unusedEvent);
    if (touchInBreakArea(touch))
    {
        _touchListener->setSwallowTouches(false);
    }
    else
    {
        _touchListener->setSwallowTouches(true);
    }
    return hitted;
}

void LayoutTouchBreak::onTouchMoved(Touch *touch, Event *unusedEvent)
{
    Layout::onTouchMoved(touch, unusedEvent);
    if (touchInBreakArea(touch))
    {
        _touchListener->setSwallowTouches(false);
    }
    else
    {
        _touchListener->setSwallowTouches(true);
    }
    
}

void LayoutTouchBreak::onTouchEnded(Touch *touch, Event *unusedEvent)
{
    Layout::onTouchEnded(touch, unusedEvent);
    if (touchInBreakArea(touch))
    {
        _touchListener->setSwallowTouches(false);
    }
    else
    {
        _touchListener->setSwallowTouches(true);
    }
}

void LayoutTouchBreak::onTouchCancelled(Touch *touch, Event *unusedEvent)
{
    Layout::onTouchCancelled(touch, unusedEvent);
    if (touchInBreakArea(touch))
    {
        _touchListener->setSwallowTouches(false);
    }
    else
    {
        _touchListener->setSwallowTouches(true);
    }
}

bool LayoutTouchBreak::init()
{
    return Layout::init();
}

bool LayoutTouchBreak::touchInBreakArea(Touch *touch)
{
    auto touchPos = touch->getLocation();
    Vec2 nsp = convertToNodeSpace(touchPos);
    if (_breakArea.containsPoint(nsp))
    {
        return true;
    }
    return false;
}

 

只要動態的根據 touch 的位置決定是否 吞並事件就好了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM