当层重叠时,如何将触摸处理限制为一个层? [英] How do I limit touch handling to one layer when layers overlap?
问题描述
我有一个有趣的问题处理触摸事件在我写的cocos2D程序。我在CCScene中有3个CCLayer子类化图层:
I have an interesting problem handling touch events in a cocos2D program I’m writing. I have 3 CCLayer sublassed layers in a CCScene:
backgroundLayer - z:0 - 用于显示背景图片的简单静态图层。
backgroundLayer – z:0 – simple static layer used to display a background image.
planetLayer - z:3 - 显示层 - 数据变更的可视化显示在此处。
planetLayer - z:3 – display layer – visualization of data changes are displayed here.
gameControlsLayer - z:5 - 例如滑块和按钮。
gameControlsLayer – z:5 – layer used to display data controllers such as sliders and buttons.
我分隔了行星和控制图层,因为我想平移和缩放地球图层,而不必担心受到影响的控制。
I separated the planet and control layers because I want to pan and zoom the planet layer without worrying about the controls being affected.
以下是设置这些图层的场景init代码:
Here is the scene init code that sets up these layers:
- (id) init
{
self = [super init];
if (self != nil)
{
// background layer
BackgroundLayer *backgroundLayer = [BackgroundLayer node];
[self addChild:backgroundLayer z:0];
// planet layer
PlanetLayer *planetLayer = [PlanetLayer node];
[self addChild:planetLayer z:3];
// gameplay layer
GameControlsLayer *gameControlsLayer = [GameControlsLayer node];
[self addChild:gameControlsLayer z:5];
}
return self;
}
我需要在行星和控制层上进行触摸处理。在控制层上,触摸处理是作为层孩子的控制对象。我写了所有这些代码,它工作正常。
I need touch handling on both the planet and control layers. On the control layer, the touch handling is inside control objects that are layer children. I wrote all this code first and it works fine.
之后,我为地球层写了层级触摸处理,所以我可以做触摸滚动和缩放。我有滚动的(虽然不是缩放),它的工作正常。我的问题是这样的:当我触摸和操纵控制层上的控件,它们工作正常,但是当我移动一个滑块向上和向下,例如,控制层后面的行星层平移,好像触摸是为
After that, I wrote layer-wide touch handling for the planet layer so I could do touch scrolling and zooming. I’ve got the scrolling in (though not the zoom yet), and it works fine. My problem is this: When I touch and manipulate the controls on the control layer, they work fine, but as I move a slider thumb up and down, for example, the planet layer behind the control layer pans as if the touches were meant for it.
它可能是多余的包括代码,但这里是相关的片段:
It may be redundant to include the code, but here are the relevant snippets:
滑块控件,控制层的孩子:
For the slider control, a child of the control layer:
- (void) onEnterTransitionDidFinish
{
[[CCTouchDispatcher sharedDispatcher]
addTargetedDelegate:self priority:1 swallowsTouches:YES];
}
- (void) onExit
{
[[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
}
#pragma mark Touch Delegate
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint location = [[CCDirector sharedDirector]
convertToGL:[touch locationInView:[touch view]]];
float distance = [self distanceBetweenPointOne:thumbPosition
andPointTwo:location];
if (distance > thumbRadius*2)
{
return NO;
}
// touch is on the thumb. store the location so we
// can calculate changes on ccTouchMoved events
touched = YES;
return YES;
}
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
if (!touched)
{
return;
}
CGPoint location = [[CCDirector sharedDirector]
convertToGL:[touch locationInView:[touch view]]];
location = [self convertToNodeSpace:location];
// if we're too far off the thumb, abandon it
float distance = [self distanceBetweenPointOne:thumbPosition
andPointTwo:location];
if (distance > thumbRadius*3)
{
//touched = NO;
return;
}
// this call adjusts some ivars – not relevant
[self updateValueAndPosition:location];
}
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
if (touched)
{
touched = NO;
}
}
- (void)ccTouchCancelled:(UITouch *)touch
withEvent:(UIEvent *)event
{
[self ccTouchEnded:touch withEvent:event];
}
这是来自Planet层的相关代码:
Here is the relevant code from the planet layer:
// Yes, we want touch notifications please
//
- (void) onEnterTransitionDidFinish
{
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self
priority:0 swallowsTouches:NO];
}
#pragma mark Touch Delegate
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLocation = [touch locationInView:[touch view]];
touchLocation = [[CCDirector sharedDirector]
convertToGL:touchLocation];
// ****NOTE – the following is a kludge I used it to break
// ********** the behavior; the controls are all grouped
// ********** at the bottom of the screen. But this is not
// ********** an acceptable fix. I shouldn’t need to mask
// ********** off certain areas of the screen. This strategy
// ********** will not hold once I add other controls to the
// ********** control layer.
//
if (touchLocation.y > 250.0f)
{
self.touched = YES;
touchHash = [touch hash];
return YES;
}
return YES;
}
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
if (!touched)
{
return;
}
if ([touch hash] == touchHash)
{
CGSize screenSize = [[CCDirector sharedDirector] winSize];
CGPoint touchLocation =
[touch locationInView:[touch view]];
CGPoint prevLocation =
[touch previousLocationInView:[touch view]];
touchLocation = [[CCDirector sharedDirector]
convertToGL:touchLocation];
prevLocation = [[CCDirector sharedDirector]
convertToGL:prevLocation];
CGPoint diff = ccpSub(touchLocation, prevLocation);
CGPoint currentPosition = [self position];
CGPoint newPosition = ccpAdd(currentPosition, diff);
if (newPosition.x < lowestX)
newPosition.x = lowestX;
else if (newPosition.x > highestX-screenSize.width)
newPosition.x = highestX-screenSize.width;
if (newPosition.y < lowestY)
newPosition.y = lowestY;
else if (newPosition.y > highestY-screenSize.height)
newPosition.y = highestY-screenSize.height;
[self setPosition:newPosition];
}
}
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
if ([touch hash] == touchHash)
{
if (touched)
{
touched = NO;
}
}
}
- (void)ccTouchCancelled:(UITouch *)touch
withEvent:(UIEvent *)event
{
[self ccTouchEnded:touch withEvent:event];
}
我想添加双指缩放功能,但我需要清除问题之前是可取的。有人有答案吗?我觉得我缺少明显的东西...
I want to add the pinch zoom capabilities, but I need to clear up this issue before that will be advisable. Does anybody have the answer here? I feel like I’m missing something obvious…
谢谢!
推荐答案
p>在 planetLayer
的 ccTouchBegan:
中,您应该找到一种方法来判断触摸是否在一个
In your planetLayer
's ccTouchBegan:
, you should find a way to tell whether the touch was inside of one of the controls and in such case return NO instead of YES.
有一种可能性是检查 [touch view]
(我有一个控制层,由UIKit对象构成,它的工作原理),否则你应该得到触摸的坐标,并检查他们是否 CGRectContainsPoint([控制rect],位置))
。
One possibility you have is checking [touch view]
(I have a control layer made of UIKit object and it works like that), otherwise you should get the coordinate of the touch and check whether they CGRectContainsPoint([control rect], location))
.
这篇关于当层重叠时,如何将触摸处理限制为一个层?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!