Principle of cocos2d-x touch distributor

Source: Internet
Author: User

To implement touch events, cclayer has encapsulated a simple interface (inherited from the cctouchdelegate class) to respond to touch events.

 

First, there are two types of touch events: Standard touch proxy and target touch proxy. Let's first look at how to enable these two touch proxies.

1. Standard touch

You can call the settouchenable (true) method during layer initialization to implement standard touch, implement Event Callback Function, and process touch events.

 // optional     virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)      virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent)      virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)      virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent) 

 

The first parameter stores a set of touch points, the second parameter is left over by the cocos2d-iphone, there is no meaning in the cocos2d-x. Add the event processing code to the four touch Event Callback functions. Example:

Void touchlayer: cctouchesmoved (ccset * ptouches, ccevent * pevent) {If (ptouches-> count () = 1) {cctouch * Touch = dynamic_cast (ptouches-> anyobject ());
// Because the coordinate system of the touch point on different platforms and the parameters of the OpenGL rendering area may be different, the position of the touch point is usually related to the system, the following processing is required to obtain the position of the touch point in the game. ccpoint position = touch-> locationinview (); // obtain the position = ccdirector ctor: shareddirector () on the game screen () -> converttogl (position); // converts the left of the screen to the game coordinate. // handle the touch event here} else {// if there are more than one touch point, processing multi-touch events here }}

 

Let's take a look at what settouchenable has done so that the touch callback function can be called.

void CCLayer::setTouchEnabled(bool enabled){    if (m_bTouchEnabled != enabled)    {        m_bTouchEnabled = enabled;        if (m_bRunning)        {            if (enabled)            {                this->registerWithTouchDispatcher();            }            else            {                CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);            }        }    }}

Go to the registerwithtouchdispatcher method and check that the pdispatcher-> addstandarddelegate (this, 0) method is called, that is, the object is registered as a standard proxy.

For standard proxies, as long as the event distributor receives a user's touch event, it will be distributed to all subscribers, and when the system has multiple touch points, all the touch points are passed to the callback function. In many cases, each touch point is independent. We do not care whether there are other touch points on the screen.

 

2. Let's look at the target Proxy:

To use the target proxy for this layer, call cctouchdispatcher: shareddispatcher ()-> addtargeteddelegate (this, 0, true) to enable the target proxy (the second parameter is the priority, the third parameter is whether to swallow the touch ). Then reload the Event Callback Function:

// Note the return type, function name, and parameter differences. Virtual bool cctouchbegan (cctouch * ptouch, ccevent * pevent) // optional virtual void cctouchmoved (cctouch * ptouch, ccevent * pevent) virtual void cctouchended (cctouch * ptouch, ccevent * pevent) virtual void cctouchcancelled (cctouch * ptouch, ccevent * pevent)

The first parameter is cctouch *, which is no longer a set but a touch point. The cctouchbegan method returns a Boolean value indicating whether to capture the input touch point. If true is returned, the system processes the touch event in moved and ended. If you choose to swallow the touch during registration, and the touch event will not be distributed, the objects with lower priority cannot receive the touch.

 

Then, the touch proxy of an object is divided into the following steps:

1) This object inherits the ccstandardtouchdelegate/cctargetedtouchdelegate Interface

2) use addstandarddelegate/addtargeteddelegate to register yourself with the cctouchdispatcher.

3) callback function for handling heavy loads of events. (Note: In the start time of the target proxy touch, began must return true for the event to be accepted)

4) when you no longer need to receive touch events, use the removedelegate method to cancel the receipt of touch events.

 

3. Working Principle of the touch distributor

Let's take a look at the main members of ccdispatcher.

// Register the standard touch event void addstandarddelegate (cctouchdelegate * pdelegate, int npriority); // register the target touch event void addtargeteddelegate (optional * pdelegate, int npriority, bool priority ); // cancel touch dispatch void removedelegate (cctouchdelegate * pdelegate); void dispatch (void); // reset the event priority void setpriority (INT npriority, cctouchdelegate * pdelegate) of the specified object ); // dispatch event void touches (ccset * ptouches, ccevent * pevent, unsigned int uindex); protected: ccarray * m_ptargetedhandlers; // record that the target touch event object ccarray * m_pstandardhandlers is registered; // record that the standard touch event object is registered

 

After the touch distributor receives touch events from the system, it also needs to distribute them to the touch processing objects one by one. The code for event distribution is mainly concentrated in the touches method.

// Dispatch eventsvoid cctouchdispatcher: touches (ccset * ptouches, ccevent * pevent, unsigned int uindex ){//......... // 1. Processing touch events with targets if (utargetedhandlerscount> 0) {cctouch * ptouch; ccsetiterator setiter; // 1.1 traverse each touch event received from the system for (setiter = ptouches-> begin (); setiter! = Ptouches-> end (); ++ setiter) {ptouch = (cctouch *) (* setiter); cctargetedtouchhandler * phandler = NULL; ccobject * pobj = NULL; // 1.2 traverse the object of each registered target touch event and distribute the event ccarray_foreach (m_ptargetedhandlers, pobj) {phandler = (cctargetedtouchhandler *) (pobj); If (! Phandler) break; bool bclaimed = false; // first process the touch start time if (uindex = cctouchbegan) {bclaimed = phandler-> getdelegate ()-> cctouchbegan (ptouch, pevent); If (bclaimed) {phandler-> getclaimedtouches ()-> addobject (ptouch);} else if (phandler-> getclaimedtouches ()-> containsobject (ptouch )) {// re-process the move, stop, and cancel events // moved ended canceled bclaimed = true; Switch (shelper. m_type) {Case cctouchmoved: phandler-> getd Elegate ()-> cctouchmoved (ptouch, pevent); break; Case cctouchended: phandler-> getdelegate ()-> cctouchended (ptouch, pevent); phandler-> getclaimedtouches () -> removeobject (ptouch); break; Case cctouchcancelled: phandler-> getdelegate ()-> cctouchcancelled (ptouch, pevent); phandler-> invoke ()-> removeobject (ptouch ); break;} // if this touch is captured and registered with a swallowed touch, set the "swallowed touch event" If (bclaimed & phandler-> isswallowstou Ches () {If (bneedsmutableset) {pmutabletouches-> removeobject (ptouch) ;}}}// 2. handle standard touch events if (ustandardhandlerscount> 0 & pmutabletouches-> count ()> 0) {ccstandardtouchhandler * phandler = NULL; ccobject * pobj = NULL; // traverse the object ccarray_foreach (m_pstandardhandlers, pobj) {phandler = (ccstandardtouchhandler *) (pobj); If (! Phandler) {break;} switch (shelper. m_type) {Case cctouchbegan: phandler-> getdelegate ()-> aggregate (pmutabletouches, pevent); break; Case cctouchmoved: phandler-> getdelegate ()-> aggregate (pmutabletouches, pevent); break; Case cctouchended: phandler-> getdelegate ()-> decrypt (signature, pevent); break; case when: phandler-> getdelegate ()-> cctouchescancelled (pmutableto Uches, pevent); break ;}}}//...... // Delete a touch event marked as swallowed up}

In each touch point in the touch set, each object registered to the distributor is asked according to the priority.

The priority of the target proxy with the lowest priority (positive infinity) is higher than that of the standard proxy with the highest priority (negative infinity.

For the target proxy, only true is returned in the Start event, and subsequent events (move, stop, and cancel) will continue to be distributed to the target object.

If swallowed, the captured point will be swallowed up. The swallowed point will immediately remove the touch set and will not be distributed to subsequent targets.

 

It is worth noting that the object that receives the touch is not necessarily displayed on the screen. The Touch distributor and the drawing in the engine are independent of each other, so you can remove the touch distributor from it as soon as you don't need it.

Principle of cocos2d-x touch distributor

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.