cocos2d中如何停止一个模态层下的所有CCTouch? [英] How to stop all CCTouch under a modal layer in cocos2d?

查看:21
本文介绍了cocos2d中如何停止一个模态层下的所有CCTouch?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 cocos2d 游戏中,我有一个设置"按钮,它启动一个模态层,旨在锁定它下面的所有内容.为此,我使用了锁定所有 CCMenuItems 的菜单状态方法和覆盖层的组合;两者都在代码下面.

In my cocos2d game I have a "Settings" button which launches a modal layer and is meant to lock everything under it. To do this, I use a combination of a menu status method which locks all CCMenuItems and I use a coverlayer; both of which are below in code.

问题是这两种解决方案似乎都不适用于 CCScrollLayers.当我单击按钮(启动模式)时,CCScrollLayer 仍然可以滚动,这不是我想要的.

The problem is that neither solution seems to work on CCScrollLayers. When I click the button (which launches the modal) the CCScrollLayer can still be scrolled which is not what i want.

我想:

  1. 按下按钮禁用所有触摸并禁用包括 CCScrollLayers 在内的所有元素
  2. 启动模态(仅允许对模态进行触摸)

我试过了:

  1. 使用CCTargetedTouchDelegate
  2. 使用Touch吞下所有触摸
  1. Using Touch to swallow all touches using the CCTargetedTouchDelegate

[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0swallowsTouches:YES];

  1. 我试过了

self.isTouchEnabled = NO 在启动模态的层上

  1. 我已尝试调整 MenuStatus 方法,使其适用于 CCScrollLayers,但似乎不起作用.
  1. I've tried adapting the MenuStatus method so that it works for CCScrollLayers but it does not seem to work.

我不确定我做错了什么.我的代码现在如下.

I'm not sure what I'm doing wrong. My code now follows.

// My main layer which launches the Settings Modal Layer

#pragma mark - Lock/Unlock layers

-(void) doSettings
{    
    [self lockLayers];
    SettingsModalLayer *sml = [[[SettingsModalLayer alloc] init] autorelease];
    [sml showSettingsOnLayer:self closeBlock:^{[self unlockLayers];}];
}

-(void) lockLayers
{
    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
    [self MenuStatus:NO Node:self];   
}

-(void) unlockLayers
{
    [self MenuStatus:YES Node:self];
}


// Disabled/Enable layers
-(void) MenuStatus:(BOOL)_enable Node:(id)_node
{
    for (id result in ((CCNode *)_node).children) {        


        if ([result isKindOfClass:[CCMenu class]]) {
            for (id result1 in ((CCMenu *)result).children) {
                if ([result1 isKindOfClass:[CCMenuItem class]]) {
                    ((CCMenuItem *)result1).isEnabled = _enable;
                }
            } // next
        } 

    } // next

}


-(void) registerWithTouchDispatcher {
    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:INT_MIN+1 swallowsTouches:YES];
}

- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"Event: %@", event);
    for( UITouch *touch in touches )
    {
        CGPoint location = [touch locationInView: [touch view]];

        location = [[CCDirector sharedDirector] convertToGL: location];        
        CCLayer *gl = (CCLayer *)[self getChildByTag:4];
        [gl setIsTouchEnabled:NO];

    }
}
-(void) ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event
{

}


-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
    [self removeFromParentAndCleanup:YES];    
}

-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{

    return YES;
}



// Settings Modal Layer

-(void) showSettingsOnLayer:(CCLayer *)layer closeBlock:(void (^)())noBlock 
{
    CoverLayer *coverLayer = [[CoverLayer alloc] init];
    [layer addChild:coverLayer z:1000];
    [coverLayer runAction:[CCFadeTo actionWithDuration:kAnimationTime opacity:155]]; // smooth fade-in to dim with semi-transparency

... // Other stuff goes here

}


    // CoverLayer
    // This is meant to stop all touches, but it doesn't really work on CCScrollLayer

#define kDialogTag 1234
#import "CoverLayer.h"



// class that implements a black colored layer that will cover the whole screen 
// and eats all touches except within the dialog box child

@implementation CoverLayer
- (id)init {
    self = [super init];
    if (self) {
        [self initWithColor:ccc4(0,0,0,0) 
                      width:[CCDirector sharedDirector].winSize.width 
                     height:[CCDirector sharedDirector].winSize.height];
        self.isTouchEnabled = YES;
    }
    return self;
}

- (void)dealloc {
    [[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
    [super dealloc];
}


- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event 
{
    CGPoint touchLocation = [self convertTouchToNodeSpace: touch];
    CCNode *dialogBox = [self getChildByTag: kDialogTag];

    // eat all touches outside of dialog box
    return !CGRectContainsPoint(dialogBox.boundingBox, touchLocation);
}

推荐答案

您只需要了解 priority 如何与 CCTouchDispatcher 一起工作.具有最小优先级值的层将首先接收触摸事件.现在您只需要相应地调整优先级即可.

You just need to understand how priority works with CCTouchDispatcher. Layer which has minimum priority value will receive the touch events first. Now you just need to adjust the priorities accordingly.

创建一个阻塞层类,并在注册 CCTouchDispatcher 时将其优先级设置为最低,并覆盖 ccTouchBegan 并在其中返回 YES.

Create a blocking layer class and set its priority to minimum when registering with CCTouchDispatcher and override ccTouchBegan and just return YES in it.

如果您查看 CCMenu 类,您会注意到默认优先级是 kCCMenuTouchPriority = -128,这就是菜单项具有更高触摸优先级的原因.

If you take a look at the CCMenu class you will notice default priority is kCCMenuTouchPriority = -128, that's the reason menu items have higher touch priority.

这篇关于cocos2d中如何停止一个模态层下的所有CCTouch?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆