zoukankan      html  css  js  c++  java
  • 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 的位置决定是否 吞并事件就好了

  • 相关阅读:
    SQLServer数据库中开启CDC导致“事务日志空间被占满,原因为REPLICATION”的原因分析和解决办法
    译:SQL Server的Missing index DMV的 bug可能会使你失去理智---慎重看待缺失索引DMV中的信息
    SQLServer中间接实现函数索引或者Hash索引
    MySQL缓存分类和配置
    MySQL系统变量配置基础
    MySQL索引统计信息更新相关的参数
    Sql Server优化---统计信息维护策略
    SQL Server 用角色(Role)管理数据库权限
    sp_executesql 或者 EXECUTE 执行动态sql的权限问题
    关于T-SQL重编译那点事,内联函数和表值函数在编译生成执行计划的区别
  • 原文地址:https://www.cnblogs.com/dou-ya/p/4290745.html
Copyright © 2011-2022 走看看