我正在使用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
答案 0 :(得分:3)
为什么不禁用游戏层上的触摸? 就像在onEnter方法中一样,禁用游戏层上的触摸......并且onExit重新启用它们
类似
-onEnter{
gameLayer.isTouchEnabled=NO;
....
}
-onExit{
gameLater.isTouchEnabled=YES;
...
}
你也不需要CCTouchDispatcher
答案 1 :(得分:1)
根据你的代码,问题是模态层即使是为自己的孩子吞咽事件也是如此。
要解决此问题,您必须将子项的触摸优先级设置为甚至高于模式层本身。 换句话说,将菜单的触摸优先级值设置为模态图层的下方。
有两种解决方案。
要实现第二种解决方案,您必须注意时间。 “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:我的英语不太好,所以如果句子松散,校正会非常高兴:)
答案 2 :(得分:1)
问题是,在传播触摸时,层/节点层次结构不。
触摸从最小priority
值的触摸处理程序传递到最高值。
一旦响应者吞下了触摸,触摸就不再转发了。
您可以使用类似于CCMenu
的方法。 CCMenu
处理所有触摸,并根据这些项目的位置检测已选择的CCMenuItem
。
如果您以相同的方式实现此功能,则让PauseLayer
处理并吞下所有触摸并使用单独的机制来确定您PauseLayer
中的哪个子元素已被选中。
我在此存储库中实现了一个解决方案: https://github.com/Ben-G/MGWU-Widgets/tree/master/Projectfiles/Components/CCMenuBlocking
该组件是CCMenu
子类,它吞下所有触摸并且不转发它们。
这是一个更为一般的CCNode
解决方案,它吞下了触摸并只将它们转发给自己的孩子:
https://github.com/Ben-G/MGWU-Widgets/blob/master/Projectfiles/Components/Popup/PopUp.m