当层重叠时,如何将触摸处理限制为一个层? [英] How do I limit touch handling to one layer when layers overlap?

查看:154
本文介绍了当层重叠时,如何将触摸处理限制为一个层?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个有趣的问题处理触摸事件在我写的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屋!

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