cocos2dx 3.2 新的事件分发机制 (观察者订阅者模式)

cocos2dx 3.2 新的事件分发机制 (观察者订阅者模式),第1张

概述cocox2dx 3.2的事件系统是基于观察者模式,又称订阅者模式来实现的。 观察者/订阅者模式 概述 观察者模式定义了一种一对多的依赖关系,多个观察者(订阅者)对象同时监听某一状态对象。这个对象的状态改变后,会通知所有(或者选择性的)观察者对象。 实现方式 参与实现该模式的模型包括触发者、响应者、事件分发器。程序运行中,触发者向事件分发器发送一种类型的状态改变消息,事件分发器获取到状态消息时,检

cocox2dx 3.2的事件系统是基于观察者模式,又称订阅者模式来实现的。

观察者/订阅者模式 概述 观察者模式定义了一种一对多的依赖关系,多个观察者(订阅者)对象同时监听某一状态对象。这个对象的状态改变后,会通知所有(或者选择性的)观察者对象。 实现方式 参与实现该模式的模型包括触发者、响应者、事件分发器。程序运行中,触发者向事件分发器发送一种类型的状态改变消息,事件分发器获取到状态消息时,检查是否有响应者已经订阅过此消息,如果有,则转发给相应的响应者去处理该消息。如果没有,则不做任何处理。 优缺点 优点: 1,减少了模块之间的耦合度。 2,程序运行中动态的决定是否响应某个事件。 3,代码层次更为清晰,模块独立性更好,有利于单元测试。 缺点: 事件分发器发送状态消息时,会涉及到响应者的排序,查询等 *** 作,当需要更新的状态比较多时,影响程序的性能,尤其是游戏中有每帧都有很多UI状态要改变时,比较影响实时性能。 cocos2dx 3.2的事件机制 cocos2dx 3.2中把触摸、键盘、鼠标、加速度、重力感应、焦点改变、以及用户自定义的消息事件类全部继承自了EventListener类,使用起来更为方便。
/** *  The base class of event Listener. *  If you need custom Listener which with different callback,you need to inherit this class. *  For instance,you Could refer to EventListeneracceleration,EventListenerKeyboard,EventListenertouchOneByOne,EventListenerCustom. */class EventListener : public Ref{public:    enum class Type    {        UNKNowN,touch_ONE_BY_ONE,touch_ALL_AT_ONCE,KEYBOARD,MOUSE,acceleration,FOCUS,#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)		GAME_CONTRolLER,#endif        CUSTOM    };    typedef std::string ListenerID;protected:    /** Constructor */    EventListener();    /** Initializes event with type and callback function */    bool init(Type t,const ListenerID& ListenerID,const std::function<voID(Event*)>& callback);
EventListener类中有三个开发者需要了解的类型: Type,即事件类型,是触摸消息还是键盘消息,或者是开发者自定义的消息。只有七种类型,分别是单点触摸,多点触摸,键盘事件,鼠标事件,重力加速度消息,焦点改变消息,以及开发者自定义消息。这里使用的CUSTOM消息,其实是跟2.x版本中的NotificationCenter使用效果是一样的。 ListenerID,是为了区分具体的响应者。除了CUSTOM类型以外,其他类型ListenerID和type都是唯一一个。CUSTOM类型,ListenerID是创建时开发者自己定义的,EventListener接收到带有ListnerID的CUSTOM类型消息时,会根据ListnerID查找相应的响应者处理,对应下面接口中的eventname。
EventListenerCustom* Eventdispatcher::addCustomEventListener(const std::string &eventname,const std::function<voID(EventCustom*)>& callback){    EventListenerCustom *Listener = EventListenerCustom::create(eventname,callback);    addEventListenerWithFixedPriority(Listener,1);    return Listener;}
callback,响应者的消息处理函数。 触摸事件的使用方式 3.x版本中的触摸分为两种类型,多点触摸:EventListenertouchAllAtOnce,单点触摸:EventListenertouchOneByOne。 EventListenertouchAllAtOnce
const std::string EventListenertouchAllAtOnce::ListENER_ID = "__cc_touch_all_at_once";
class EventListenertouchAllAtOnce : public EventListener{public:    static const std::string ListENER_ID;        static EventListenertouchAllAtOnce* create();    virtual ~EventListenertouchAllAtOnce();        /// OverrIDes    virtual EventListenertouchAllAtOnce* clone() overrIDe;    virtual bool checkAvailable() overrIDe;    //public:    std::function<voID(const std::vector<touch*>&,Event*)> ontouchesBegan;    std::function<voID(const std::vector<touch*>&,Event*)> ontouchesMoved;    std::function<voID(const std::vector<touch*>&,Event*)> ontouchesEnded;    std::function<voID(const std::vector<touch*>&,Event*)> ontouchesCancelled;

多点触摸继承自EventListener,TYPE为touch_ALL_AT_ONCE,Listener_ID为,__cc_touch_all_at_once,从ontouchesBegan方法中可以看出,这里是一次处理了多个触摸点的消息。 EventListenertouchOneByOne
const std::string EventListenertouchOneByOne::ListENER_ID = "__cc_touch_one_by_one";
class EventListenertouchOneByOne : public EventListener{public:    static const std::string ListENER_ID;        static EventListenertouchOneByOne* create();        virtual ~EventListenertouchOneByOne();        voID setSwallowtouches(bool needSwallow);    bool isSwallowtouches();        /// OverrIDes    virtual EventListenertouchOneByOne* clone() overrIDe;    virtual bool checkAvailable() overrIDe;    //public:    std::function<bool(touch*,Event*)> ontouchBegan;    std::function<voID(touch*,Event*)> ontouchmoved;    std::function<voID(touch*,Event*)> ontouchended;    std::function<voID(touch*,Event*)> ontouchCancelled;
单点触摸的实现方式也是继承自EventListener,TYPE为touch_ONE_BY_ONE,Listener_ID为__cc_touch_one_by_one,这里是将多个触摸消息按照触发顺序依次响应,例如如果同时在屏幕上按了四个点,则触摸响应函数会触发四次。ontouchBegan是需要注意的一个函数,返回值是bool,程序至少得实现这个函数,否则无法接收到触摸消息。返回值为false的时候,ontouchmoved,ontouchended,ontouchCancelled则不再执行,触摸消息直接传递给下一个接收者。2.x版本的触摸当这个函数返回true时表示吞噬触摸消息,不再往下传递。3.x版本需要设置setSwallowtouched为true,则触摸消息不再往下传递。在此事件中需要 处理两个按钮不能同时响应的问题。 触摸的另一个问题是如何控制触摸响应的顺序,触摸响应的顺序根响应的优先级有关。如下是创建触摸的两个通用函数:
    /** Adds a event Listener for a specifIEd event with the priority of scene graph.     *  @param Listener The Listener of a specifIEd event.     *  @param node The priority of the Listener is based on the draw order of this node.     *  @note  The priority of scene graph will be fixed value 0. So the order of Listener item     *          in the vector will be ' <0,scene graph (0 priority),>0'.     */    voID addEventListenerWithSceneGraPHPriority(EventListener* Listener,Node* node);    /** Adds a event Listener for a specifIEd event with the fixed priority.     *  @param Listener The Listener of a specifIEd event.     *  @param fixedPriority The fixed priority of the Listener.     *  @note A lower priority will be called before the ones that have a higher value.     *        0 priority is forbIDden for fixed priority since it's used for scene graph based priority.     */    voID addEventListenerWithFixedPriority(EventListener* Listener,int fixedPriority);
第一个接口,是根据node元素的绘制顺序来决定触摸优先级,元素越晚绘制,即元素的zorder越高,则优先级越高。即使动态改变了node元素的层级关系,触摸也能正常响应。接口注释中也写得比较清楚,接口会默认把元素的优先级设置为0。触摸分发时,先分发优先级小于0的,然后再分发等于0的,即是根据元素层级关系来分发,最后分发大于0的。元素移除时,会自动移除相关联的触摸监听者。 第二个接口,是直接设置了触摸响应的优先级,可以设置除了0之外的优先级。优先级越低,触摸响应越早。即按照优先级从小到大的顺序分发。 触摸使用示例:
auto touchListener = EventListenertouchOneByOne::create();		touchListener->ontouchBegan = CC_CALLBACK_2(RoomLayer::ontouchBegan,this);		touchListener->ontouchended = CC_CALLBACK_2(RoomLayer::ontouchend,this);		touchListener->ontouchCancelled = CC_CALLBACK_2(RoomLayer::ontouchCancle,this);		touchListener->setSwallowtouches(true);		_eventdispatcher->addEventListenerWithSceneGraPHPriority(touchListener,btn);

开发者自定义事件使用示例: 这是监听游戏从后台进入前台时的消息,其他的事件消息类似使用方式。
	auto toForegroundListener = EventListenerCustom::create(EVENT_COME_TO_FOREGROUND,[this](EventCustom* event)	{		ontouchended(nullptr,nullptr);	});	_eventdispatcher->addEventListenerWithSceneGraPHPriority(toForegroundListener,this);
总结

以上是内存溢出为你收集整理的cocos2dx 3.2 新的事件分发机制 (观察者/订阅者模式)全部内容,希望文章能够帮你解决cocos2dx 3.2 新的事件分发机制 (观察者/订阅者模式)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1027371.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存