Ласточка касается, если не трогать ребенка моего текущего слоя - PullRequest
2 голосов
/ 28 марта 2012

Я пишу меню паузы с помощью CCLayer. Мне нужен слой, чтобы проглотить прикосновения, чтобы вы не могли нажать на слой ниже, однако мне также нужно иметь возможность использовать кнопки на самом слое паузы.

Я могу заставить слой глотать прикосновения, но меню тоже не будет работать.

Вот мой код:

pauseLayer.m

#import "PauseLayer.h"

@implementation PauseLayer

@synthesize delegate;

+ (id) layerWithColor:(ccColor4B)color delegate:(id)_delegate
{
    return [[[self alloc] initWithColor:color delegate:_delegate] autorelease];
}

- (id) initWithColor:(ccColor4B)c delegate:(id)_delegate {
    self = [super initWithColor:c];
    if (self != nil) {

        NSLog(@"Init");
        self.isTouchEnabled = YES;
        CGSize wins = [[CCDirector sharedDirector] winSize];

         delegate = _delegate;
         [self pauseDelegate];

        CCSprite * background = [CCSprite spriteWithFile:@"pause_background.png"];

        [self addChild:background];

        CCMenuItemImage *resume = [CCMenuItemImage itemFromNormalImage:@"back_normal.png"
                                                         selectedImage:@"back_clicked.png"
                                                                target:self
                                                              selector:@selector(doResume:)];
        resume.tag = 10;
        CCMenu * menu = [CCMenu menuWithItems:resume,nil];

        [menu setPosition:ccp(0,0)];

        [resume setPosition:ccp([background boundingBox].size.width/2,[background boundingBox].size.height/2)];

        [background addChild:menu];

        [background setPosition:ccp(wins.width/2,wins.height/2)];

    }
    return self;
}

-(void)pauseDelegate
{
    NSLog(@"pause delegate");
    if([delegate respondsToSelector:@selector(pauseLayerDidPause)])
        [delegate pauseLayerDidPause];
}

-(void)doResume: (id)sender
{
    if([delegate respondsToSelector:@selector(pauseLayerDidUnpause)])
        [delegate pauseLayerDidUnpause];
    [self.parent removeChild:self cleanup:YES];
}

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

- (void)onExit {
    [[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
    [super onExit];
}
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
    return YES;
}

-(void)dealloc
{
    [super dealloc];
}

@end

Ответы [ 3 ]

3 голосов
/ 28 марта 2012

Почему вы просто не отключаете прикосновения на игровом слое?как в методе onEnter, отключите прикосновения на игровом слое ... и onExit повторно включите их

что-то вроде

-onEnter{
gameLayer.isTouchEnabled=NO;
....
}
-onExit{
gameLater.isTouchEnabled=YES;
...
}

также вам не понадобится CCTouchDispatcher

1 голос
/ 25 июля 2013

Проблема в том, что иерархия слоя / узла не учитывается при распространении касаний.Касания передаются от обработчика касания с наименьшим значением priority к значению с самым высоким.

Касания больше не пересылаются, как только один из респондентов глотает касание.

Вы можете использовать подход, аналогичный CCMenu.CCMenu обрабатывает все касания и определяет, какой CCMenuItem был выбран, в зависимости от положения этих элементов.

Если вы реализуете это одинаково, вы позволяете PauseLayer обрабатывать и глотать все касания ииспользуйте отдельный механизм, чтобы определить, какой дочерний элемент в вашем PauseLayer был выбран.

Пример реализации: Подкласс CCMenu

Я реализовал решение в этом хранилище: https://github.com/Ben-G/MGWU-Widgets/tree/master/Projectfiles/Components/CCMenuBlocking

Этот компонент является CCMenu подклассом, который глотает все касания и не передает их.

Пример реализации: CCNode

Вот более общее решение для CCNode, которое глотаеттрогает и пересылает их только своим детям:

https://github.com/Ben-G/MGWU-Widgets/blob/master/Projectfiles/Components/Popup/PopUp.m

1 голос
/ 18 января 2013

В соответствии с вашим кодом проблема заключается в том, что модальный слой глотает события, даже если он предназначен для собственных детей.

Чтобы решить эту проблему, необходимо установить приоритет касания детей даже выше, чемсам модальный слой.Другими словами, установите значение приоритета касания меню ниже уровня модального слоя.

Есть два решения.

  1. Просто переопределите метод "CCMenu :: registerWithTouchDispatcher ()" и установите приоритет вышес начала.
  2. Изменить приоритет касания меню с помощью метода "setPriority" touchDispatcher или "setHandlerPriority" самого меню.

Чтобы найти второе решение, вы должны обратить внимание навремя«CCMenu :: registerWithTouchDispatcher ()» вызывается где-то ПОСЛЕ «onEnter» и «onEnterTransitionDidFinish».

Итак, используйте «scheduleOnce» или что-то в этом роде.

Примеры кодов.

- (id) initWithColor:(ccColor4B)c delegate:(id)_delegate {
   self = [super initWithColor:c];
   if (self != nil) {
         //your codes......   put CCMenu in instance

         [self scheduleOnce:@selector(setMenuPriority:) delay:0];
   }
   return self;
}

- (void) setMenuPriority (ccTime)dt {
   [[[CCDirector sharedDirector] touchDispatcher] setPriority:INT_MIN forDelegate:menu];
   //priority "INT_MIN" because you set the layer's priority to "INT_MIN+1".
}

PS: Мой английский не очень хорош, поэтому, если есть свободные предложения, исправление будет очень приятно:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...