Cocos2d-x Learning Notes-event handling mechanism

Source: Internet
Author: User

Cocos2d-x Learning Notes-event handling mechanism one: event handling mechanism

An event is triggered to a complete response, consisting mainly of the following three parts:

    • Event Dispatcher Eventdispatcher;
    • Event Type Eventtouch, Eventkeyboard, etc.;
    • Event listeners Eventlistenertouch, Eventlistenerkeyboard, and so on.

In the Cocos2d-x v3.x, the thing about the event, nothing more than the three parts around the above, mastered the above three parts, also mastered the Cocos2d-x v3.x the essence of the event processing.

(1) Event Dispatcher:

The event dispatcher, which is the "chief officer" of all events, is responsible for dispatching and managing all event listeners, and when an event occurs, it is responsible for dispatching the corresponding event, and generally calling the Geteventdispatcher in the Director class to get an event scheduler that, when the game starts, A default Eventdispatcher object is created.

Event listeners have a corresponding relationship to an event. For example, keyboard events (Evemkeyboard) can only be handled by the keyboard event listener (Eventlistenerkeyboard), which requires a relationship to be established between them, and the process of establishing the relationship is called a "registered listener." Cocos2d-x provides an event dispatcher (Evemdispatcher) that is responsible for managing this relationship, specifically the event dispatcher is responsible for registering listeners, unregistering listeners, and event distribution. The Eventdispatcher class uses a singleton pattern design and obtains an event dispatcher object through the Director::getlnstance ()->geteventdispatcher () statement.

The Eventdispatcher class registers the event listener to the event dispatcher function as follows:

(1) void addeventlistenerwithfixedpriority (EventListener * listener, int fixedpriority) specifies a fixed event priority Registration listener, The event priority determines the priority of the event response, and the smaller the value, the higher the priority level.

(2) void addeventlistenerwithscenegraphpriority (EventListener * Listener, Node * node) displays the sprite priority as the event priority, and the parameter Node is the sprite object to touch.

When an event response is no longer in progress, you should unregister the event listener. The main logoff functions are as follows:

(1) void RemoveEventListener (EventListener * listener). Unregisters the specified event listener.

(2) void removecustomeventlisteners (const std:: string&* customeventname). Unregisters the custom event listener.

(3) void Removealleventlistener (). To log off all event listeners, It is important to note that after using the function, the menu does not respond to events because it also needs to accept touch events.

Attention:

(1) The event listener priority for Addeventlistenerwithscenegraphpriority is 0, and the priority of event listeners in Addeventlistenerwithfixedpriority cannot be set to 0. Because this is reserved for use by scenegraphpriority.

(2) In addition, it is very important, fixedpriority listener after the addition of the need to manually remove, and scenegraphpriority listener is bound to node, in the destructor of node will be removed. The removal method is dispatcher->removeeventlistener (listener);

(2) Event type:

The following types of events are defined in Cocos2d-x:

enum class Type{    TOUCH,          // 触摸事件    KEYBOARD,       // 键盘事件    ACCELERATION,   // 加速器事件    MOUSE,          // 鼠标事件    FOCUS,          // 焦点事件    CUSTOM          // 自定义事件}
(3) Event listener:

The event listener implements the logic corresponding to the various event firings, and the event listener is called by Eventdispatcher to respond to the callback function that is bound by the event listener. In Cocos2d-x, you define several event listeners as follows:

Enum class type{//Unknown event listener UNKNOWN,//single Touch event listener creation method and callback function parameter Touch_one_by_one, Eventlistenertouchon    Ebyone::create ();    typedef std::function<bool (touch*, event*) > Cctouchbegancallback;    typedef std::function<void (touch*, event*) > Cctouchcallback;    Multi-touch Event listener creation method with callback function parameter touch_all_at_once, eventlistenertouchallatonce::create ();    typedef std::function<void (const std::vector<touch*>&, event*) > Cctouchescallback;    Keyboard event Listener creation method and callback function parameter KEYBOARD, eventlistenerkeyboard::create ();    Std::function<void (Eventkeyboard::keycode, event*) > onkeypressed;    Std::function<void (Eventkeyboard::keycode, event*) > onkeyreleased;    Mouse event Listener creation method and callback function parameter MOUSE, eventlistenermouse::create ();    Std::function<void (eventmouse* event) > OnMouseDown;    Std::function<void (eventmouse* event) > onMouseUp;    Std::function<void (eventmouse* event) > onMouseMove; Std::function<void (eventmouse* event)> onmousescroll;    Accelerator Event Listener Creation method and callback function parameter acceleration, eventlisteneracceleration::create ();    Std::function<void (acceleration*, event*) > onaccelerationevent;    Focus Event Listener Creation method and callback function parameter focus, eventlistenerfocus::create ();    Std::function<void (ui::widget*, ui::widget*) > onfocuschanged;    Custom Event Listener creation method and callback function parameter custom eventlistenercustom::create ();           Std::function<void (eventcustom*) > _oncustomevent; }
Two: Single Touch Event processing method (1) Create a single touch event listener:
auto listener = EventListenerTouchOneByOne::create();
(2) Set listener callback function:
// 设置是否吞没事件,在onTouchBegan方法返回true时吞没,事件不会传递给下一个Node对象listener->setSwallowTouches(true);  listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::touchBegan, this);listener->onTouchMoved = CC_CALLBACK_2(HelloWorld::touchMoved, this);listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::touchEnded, this);
(3) Adding listeners
// 其中listener->clone()获得listener对象,使用clone()函数是因为每—事件监听器只能被注册一次,// addEventListenerWithSceneGraphPriority和addEventListenerWithFixedPriority会在注册事件监听器时设置一个注册标// 识,一旦设置了注册标识,该监听器就不能再用于注册其他事件监听了,因此需要使用listener->clone()克隆一个新的监听器对象,// 把这个新的监听器对象用于注册。_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, pLayer1);_eventDispatcher->addEventListenerWithSceneGraphPriority(listener->clone(), pLayer2);_eventDispatcher->addEventListenerWithSceneGraphPriority(listener->clone(), pLayer3);
    • The listener must be added to the EventListener in order to be valid;
    • Whenever a touch event occurs, the _eventdispatcher event dispatcher invokes the Ontouchbegan function of the listener listener based on the ZOrder order of the player (ZOrder a large priority call, and the same word joins the node first), According to the Ontouchbegan function return value processing, the specific processing rules see (4), and the corresponding player as an event passed into the Ontouchbegan function. This paragraph of the understanding can give an example, a Sprite object sprite ZOrder value is higher than a menu object menus, when tapping any place on the screen, the system first responds to the Sprite object is bound to the listener listener's callback function Ontouchbegan, If it returns false, it responds to the menu object's callback function, and if it returns true, no longer responds to the menu object's callback function
(4) Specific touch events
bool HelloWorld::TouchBegan(Touch *touch, Event *unused_event){    // 获取事件所绑定的对象    auto target = static_cast<Layer*>(unused_event->getCurrentTarget());    if (target == nullptr)    {        return false;    }     // 获取当前点击点相对绑定对象的局部坐标(Node坐标系)    // getLocation得到的是openGL坐标系,也就是世界坐标系    Vec2 locationInNode = target->convertToNodeSpace(touch->getLocation());    Size s = target->getContentSize();    Rect rect = Rect(0, 0, s.width, s.height);    // 点击范围判断检测    if (rect.containsPoint(locationInNode))    {        log("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y);        target->setOpacity(180);        return true;    }    return false;}

Key understanding:

    • Ontouchbegan (Touch *touch, event *event) is the function that is called the first time each touch event occurs and returns a bool value. Listener->setswallowtouches (True) if the engulfing event is set to true: if it returns true, the touch event has been found and processed by the target object, after which the ontouchmoved, The ONTOUCHENDCD and ontouchcancelled functions will then respond. The event dispatcher object, Eventdispatcher, will stop the distribution of this event, and other event listener objects in the event dispatcher will no longer be listening for that touch event and will no longer receive this user action data. If False is returned, then the ontouchmoved, ontouchended, and ontouchcancelled functions will not respond, and the vehicle distributor will continue to handle this event to other listeners that have added events.

    • As soon as a touch event occurs, the listener responds to the Ontouchbegan function of the high ZOrder value player, and the player passes in the Ontouchbegan function as the event events by unused_event-> Getcurrenttarget () gets.

Understanding of the setswallowtouches engulfing event:

    • As stated above, if a listener sets the engulfing event to true, when its Ontouchbegan returns true, it is tantamount to engulfing the listener with this touch event, and the event dispatcher object Eventdispatcher will stop distributing the event. Other event listener objects in the event dispatcher will no longer be listening to the touch event, and will no longer be able to receive the user operation data.

    • If a listener sets the engulfing event to false, even if Ontouchbegan returns True, the event dispatcher object Eventdispatcher will still distribute this touch event to other listeners in ZOrder order, responding to its Ontouchbegan function, The event dispatcher object Eventdispatcher stops the distribution of this event only if it encounters a listener that sets the engulfing event to true and the Ontouchbegan function returns True.

The way to judge whether to touch a target is to understand it so as to touch the object as an example of sprite PLayer1:

    • Listener is bound to the player via Addeventlistenerwithscenegraphpriority, and when the touch occurs, the player passes in the Ontouchbegan function as event events. The program can obtain the player size and the world coordinate of the touch coordinates, through the Converttonodespace function transfer to the node coordinates, the final judgment.

    • Touch->getlocation () Gets the touch coordinates of the world coordinate system (the world coordinate system refers to the lower left corner of the design resolution as the Origin point, the y-axis positive direction, and the right x-axis positive direction of the coordinate system (OpenGL coordinate system)). The Converttonodespace function converts the touch coordinates in the world coordinate system to the touch coordinates under the node coordinate system, in the lower left corner of the object, and uses the Converttonodespacear function to calculate the object anchor point as the origin.

    • Rect rect = rect (0, 0, S.width, s.height) to create a rectangular block, note that the rectangle block is an abstraction and does not create an actual rectangular block on the layer. Its containspoint is only in the mathematical sense to determine whether the locationinnode in this rectangular block.

Three: The single Touch event processing method in the layer

The object listening to an event is a layer, not a sprite, and the decision to touch an elf is more complex, but with simplicity, the following virtual function is declared first in the header file:

virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event);virtual void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event);virtual void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event);

Then open the layer touch response in the main program

this->setTouchEnabled(true);                                // 打开触摸监听this->setTouchMode(Touch::DispatchMode::ONE_BY_ONE);        // 设置为单点触摸模式
Four: Multi-touch

This section analyzes some of the details of using multi-touch and how to handle it. First, the target is a clickable object that implements several functions, and when clicked on the's really into image, the object can be dragged until the finger is released.

(1) In the first case, multiple touchpoint clicked on the same target.

    • Suppose 3 fingers are pressed on the same target, and 3 fingers are dragged in different directions at the same time. As you can see in the drag process, the target's position is constantly beating under 3 fingers, jumping from the finger to the other finger. Reason: A target can also accept multiple touch messages at the same time, if only want to accept a touch message, in Ontouchbegan, when the judgment has been clicked, if it is directly return false.

(2) In the second case, a touchpoint click on multiple target.

    • What if you now have a finger on the 3 overlapping target? Which one will be dragged or 3 dragged at the same time? The answer is that the one with the highest priority is dragged, and if they have the same priority, then the first registered one is dragged. Cause: A touchpoint Once the Ontouchbegan of a target returns true, it will not continue to be passed to the other target, Eventdispatcher is the callback by priority.

(3) In the third case, multiple touchpoint are clicked on multiple target.

    • What happens when you press 3 fingers at 3 overlapping target and move in a different direction? If you do not make the first question of the kind of modification, there will be the first problem, 3 points control the same target, if done, 3 points are prepared to drag a target, without a block B, so b there is no point in the situation.

Cocos2d-x Learning Notes-event handling mechanism

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.