【问题标题】:How to stop all CCTouch under a modal layer in cocos2d?cocos2d中如何停止一个模态层下的所有CCTouch?
【发布时间】:2012-09-17 10:59:43
【问题描述】:

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

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

我想:

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

我试过了:

  1. 使用 Touch 吞下所有使用 CCTargetedTouchDelegate 的触摸

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

  1. 我试过了

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

  1. 我已尝试调整 MenuStatus 方法,使其适用于 CCScrollLayers,但似乎不起作用。

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

// 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);
}

【问题讨论】:

    标签: event-handling cocos2d-iphone modal-dialog ccmenuitem


    【解决方案1】:

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

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

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

    【讨论】:

    • 我会试一试的。希望我能破解它
    • kCCMenuTouchPriority 已被 kCCMenuHandlerPriority 弃用。
    【解决方案2】:

    吞噬所有触摸事件的层需要以比任何底层控件更高的优先级注册。通常这些是菜单项,默认优先级为 kCCMenuHandlerPriority = -128(首先处理最低值)。

    吞咽层然后简单地处理它接收到的任何触摸,什么都不做。

    弹出窗口上的任何控件都需要优先于吞咽层,因此如果您使用菜单,则需要设置新的优先级。然后这些触摸将由项目首先处理(而不是吞咽层)。

    相关函数显示注册优先级-1024的吞咽层,处理(忽略)所有触摸,以及添加优先级高于吞咽层的菜单项:

    // Ensure dialog background, which swallows all touches, is prioritised before normal menus (-128)
    // Menus displayed on the dialog, then need to be prioritised before that.
    #define kDialogSwallowTouchPriority -1024
    #define kDialogMenuPriority -1032
    
    - (void) registerWithTouchDispatcher {
        [[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self
            priority:kDialogSwallowTouchPriority swallowsTouches:YES];
    }
    
    - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
    {
        // Swallow all touches
        return YES;
    }
    
    ...
    
    - (void)addCloseMenu
    {
        CCSprite *close = [CCSprite spriteWithSpriteFrameName:@"closebutton.png"];
        CCMenuItem *closeMenuItem = [CCMenuItemSprite itemWithNormalSprite:close  
            selectedSprite:nil target:self selector:@selector(closeTapped:)];
        closeMenuItem.anchorPoint = ccp( 1, 1 );
        closeMenuItem.position = ccp( self.dialog.contentSize.width - 10, 
            self.dialog.contentSize.height - 10 );
        self.closeMenu = [CCMenu menuWithItems:closeMenuItem, nil];
        self.closeMenu.anchorPoint = ccp( 1, 1 );
        self.closeMenu.position = CGPointZero;
        // Set the priority above the swallowing layer
        self.closeMenu.touchPriority = kDialogMenuPriority;
        [self.dialog addChild:self.closeMenu];
    }
    

    【讨论】:

      【解决方案3】:

      穷人的做法:添加一个 ccmenuitemsprite 和 ccmenu,并将 ccsprite 不透明度设置为 0,覆盖您不想点击的任何内容。当我不想弄乱触摸调度程序时,对我有用。

      【讨论】:

      • 您将无法接触到任何在阻止程序前有 z 顺序的项目。 IE。它阻止了一切,而不仅仅是“背后”的东西。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多