Cocos-2d about SwallowTouch, further explaining the touch event distribution mechanism

Source: Internet
Author: User

Problem Situation
Simulate a layer similar to game prompts:
1. The game home scene can be touched and interacted;
2. When a prompt is displayed, only the prompt information layer can be touched to interact with the user, and its background cannot continue to respond to the touch event.
3. After the information layer is removed from the home scene, the main scene of the game can continue to respond to touch events for interaction.
Here, the "prompt information layer" is called SwallowTouchLayer for the time being, and the game main scenario is called GameLayer.
Further describe the substantive issues of the above scenario:
Add a layer "swallow" to the original layer touch event
1. SwallowTouchLayer must be swallowTouches = YES;
2. SwallowTouchLayer touch event priority> GameLayer touch event priority
In order to solve the above problem, we first need to understand the distribution mechanism of touch events in cocos-2d, the problem is solved.
The following uses HellowWorld as an example to add a SwallowTouchLayer on HellowWorld.
Reference

 

Code Implementation
1. Add a new button in HellowWorldLayer. m.
CCMenuItem * addSwallowTouchLayerItem = [CCMenuItemFontitemWithString: @ "addSwallowTouchLayer" block: ^ (id sender ){
[SelfaddChild: [[SwallowTouchLayeralloc] init];
}];
CCMenu * menu = [CCMenumenuWithItems: itemAchievement, itemLeaderboard, addSwallowTouchLayerItem, nil];


2. Implement SwallowTouchLayer
SwallowTouchLayer. h
# Import <Foundation/Foundation. h>
# Import "cocos2d. h"

@ Interface SwallowTouchLayer: CCLayer
{
CCSprite * grayBackground;
CCMenu * menu;
}

@ End
SwallowTouchLayer. m
//
// SwallowTouchLayer. m
// SwallowTouch
//

# Import "SwallowTouchLayer. h"

@ Implementation SwallowTouchLayer
-(Id) init
{
If (self = [super init])
{
// Enable receiving touch events
Self. isTouchEnabled = YES;

// Add a grayscale background
GrayBackground = [CCSprite spriteWithFile: @ "swallowBackground.png"];
GrayBackground. position = ccp (240,160 );
[Self addChild: grayBackground];

// Initialize Menu
CCMenuItem * menuItem = [CCMenuItemToggle itemWithTarget: self
Selector: @ selector (removeTeaching)
Items: [CCMenuItemImage itemWithNormalImage: @ "Icon.png" selectedImage: nil], [CCMenuItemImage itemWithNormalImage: @ "Icon.png" selectedImage: nil],
Nil];
// Set the position of the first step.
MenuItem. position = ccp (0, 0 );

Menu = [CCMenu menuWithItems: menuItem, nil];
Menu. position = ccp (240,160 );

// Add a tutorial
[Self addChild: menu];
}
Returnself;
}

-(Void) onEnter
{
// Call the registerWithTouchDispatcher of the node itself and the child in super onEnter to add the touch proxy
[Super onEnter];

// Re-adjust the menu response priority so that it can respond to the touch event. This step can be omitted according to the actual situation.
[Menu setHandlerPriority: kCCMenuHandlerPriority-2];
}

-(Void) onExit
{
[[CCDirector shareddire] touchDispatcher] removeDelegate: self];
[Super onExit];
}

-(Void) dealloc
{
[Super dealloc];
}

// Remove yourself from the parent scenario
-(Void) removeTeaching
{
[Self removeFromParentAndCleanup: YES];
}

# Pragma mark-Swallow Touch Input
/*
* Register the CCLayer to CCTargetedTouchDelegate, and set its response priority to be greater than or equal
* Response priority of a priority object
*/
-(Void) registerWithTouchDispatcher
{
CCTouchDispatcher * touchDispatcher = [[CCDirector shareddire] touchDispatcher];
[TouchDispatcher addTargetedDelegate: self
Priority: kCCMenuHandlerPriority-1
SwallowsTouches: YES];
}

-(BOOL) ccTouchBegan :( UITouch *) touch withEvent :( UIEvent *) event
{
// If return NO, the message is not blocked.
ReturnYES;
}
@ End

Principles
1. When you click the addSwallowTouch button in HellowWorldLayer,
[SelfaddChild: [[SwallowTouchLayeralloc] init]; add SwallowTouchLayer.

2. In the init Function
Self. isTouchEnabled = YES; enable the touch event. Set a breakpoint here, run the program, and trace the running essence:
2.1 response to the CCLayer setIsTouchEnable message:
-(Void) setIsTouchEnabled :( BOOL) enabled
{
If (isTouchEnabled _! = Enabled)
 
{
IsTouchEnabled _ = enabled; // here, the attribute is changed from NO to YES.
If (isRunning _)
{
If (enabled)
[Self registerWithTouchDispatcher];
Else
{
CCDirector * director = [CCDirector shareddire];
[[Director touchDispatcher] removeDelegate: self];
}
}
}
}

2.2 At this time, SwallowTouchLayer is only initialized and not added to the scene, so isRunnig _ is NO, so in fact, in the init function, although self. isTouchEnabled = YES; but only attribute modification does not actually register the touch event to the message distribution list (registerWithTouchDispatcher is not executed)

3. initialize the yellow background and menu buttons in the init function and add binding events for the buttons.
Selector: @ selector (removeTeaching)
RemoveTeaching removes SwallowTouchLayer from the parent scenario.

4. The above is only the initialization of SwallowTouchLayer. When [self addChild:...] In HellowWorld;
Add SwallowTouchLayer to the scene. The OnEnter () is called first to enter the scene message response function.

5. First, [super onEnter]; call the onEnter function of the parent CCLayer:

-(Void) onEnter
{
# Ifdef _ CC_PLATFORM_IOS
// Register 'parent' nodes first
// Since events are propagated in reverse order
If (isTouchEnabled _)
[Self registerWithTouchDispatcher]; // This function has been rewritten in SwallowTouchLayer.

# Elif defined (_ CC_PLATFORM_MAC)
CCDirector * director = [CCDirector shareddire];
CCEventDispatcher * eventDispatcher = [director eventDispatcher];
 
If (isMouseEnabled _)
[EventDispatcher addMouseDelegate: self priority: [self mouseDelegatePriority];

If (isKeyboardEnabled _)
[EventDispatcher addKeyboardDelegate: self priority: [self keyboardDelegatePriority];

If (isTouchEnabled _)
[EventDispatcher addTouchDelegate: self priority: [self touchDelegatePriority];
# Endif

// Then iterate over all the children
[Super onEnter]; // continue to find the parent class CCNode and call onEnter
}
Details:
(1) because we have modified isTouchEnable to YES in the init function, we call the register touch message delivery registerWithTouchDispatcher.
We have rewritten this function in SwallowTouchLayer. In this function
CCTouchDispatcher * touchDispatcher = [[CCDirectorsharedDirector] touchDispatcher];
[TouchDispatcheraddTargetedDelegate: self
Priority: kCCMenuHandlerPriority-1
SwallowsTouches: YES];

Bind the touch event proxy (the CCLayer complies with TargetedTouchDelegate by default), and the priority (touch response priority) is set to the highest (KCCMenuHandlerPriority =-128, the smaller the value, the higher the priority)
Set swallowTouches to YES, that is, in the touch response layer, stop processing the touch event and stop handing it to another layer for further processing.

(2) [super onEnter]; find the onEnter of CCNode
-(Void) onEnter
{
[Children _ makeObjectsPerformSelector: @ selector (onEnter)];
[Self resumeSchedulerAndActions];

IsRunning _ = YES;
}

Let all children respond to onEnter; make sure to run (isRunning _ = YES); at this time, the response to the onEnter event of CCLayer is complete.
6. In 4, we only learned the first step [super onEnter] In onEnter of SwallowTouchLayer;
-(Void) onEnter
{
// 1. Call registerWithTouchDispatcher of the node itself and the child in super onEnter to add the touch proxy
[SuperonEnter];

// 2. re-adjust the menu response priority so that it can respond to the touch event. You can skip this step according to the actual situation.
[MenusetHandlerPriority: kCCMenuHandlerPriority-2]; //-130
}
Step 2: Adjust the touch priority and set the menu button to the highest priority.
We still remember to call the registerWithTouchDispacher of SwallowTouchLayer in [super onEnter]; we set the response priority of SwallowTouchLayer to kCCMenuHandlerPriority-1; (-129)
Therefore, the highest-128 touch priority response in the Cocos-2d; and we set the SwallowTouchLayer priority to-129, and set the menu priority to-130;
SwallowTouch = YES by default in menu; we have set SwallowTouchLayer's registerWithTouchDispacher; the function also sets SwallowTouch to YES;
Therefore, when the menu is touched, the menu has the highest priority, so the first response is returned. Then, the Swallow touch is dropped,
When the touch screen is not in the menu, the menu does not receive the touch, the SwallowTouchLayer receives the touch, the response is then Swallow, so HellowWorld does not respond to the touch, it seems that all the buttons at the HelloWorld layer are invalid.
(For details about Swallow, refer to the previous article Cocos-2d CCLayer touch response CCTouchDelegate and CCStandardTouchDelegate and CCTargetedTouchDelegate)

7. Click the menu button to remove SwallowTouchLayer.
Remove the touch proxy when onExit exits this layer.
HelloWorldLayer can continue to interact and respond to the touch.

8. Description:
This is just a small example. It demonstrates that SwallowTouchLayer preferentially intercepts touch responses. Of course, we can add touchBegan, touchMove, and touchEnd proxy methods in SwallowTouchLayer to implement the unique touch method of SwallowTouchLayer.


 

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.