【问题标题】:How to make tap through parent nodes?如何通过父节点进行点击?
【发布时间】:2015-06-09 01:40:18
【问题描述】:

我通过 SO 搜索并尝试了几个示例,但我仍然无法理解这种行为。在模拟器 7.1 上分接工作,但在 8.1 上不起作用。我之前也问过类似的问题,但与此不同,我使用 nodesAtPoint 方法解决了它,然后循环遍历所有节点并检查节点名称/类.. . 但这有所不同,因为现在我使用实现 touchesBegan 的自定义 Button 类,我希望它能够检测并在可能的情况下“吞下”触摸。

所以我有一个简单的 Button 类,它是 SKSpriteNode 的子类,它有自己的 touchesBegan 和 userInteractionEnabled = YES。在我看来,控制器属性ignoreSiblingsOrder 设置为YES

这是一个可以产生描述行为的(简化的)示例:

#import "GameScene.h"

@interface Button : SKSpriteNode
-(instancetype)initWithColor:(UIColor *)color size:(CGSize)size;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
@end


@implementation Button
-(instancetype)initWithColor:(UIColor *)color size:(CGSize)size {
    self = [super initWithColor:color size:size];
    self.userInteractionEnabled = YES;
    return self;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"%@ hit", self.name);
}
@end

@implementation GameScene

-(id)initWithSize:(CGSize)size {
    if (self = [super initWithSize:size]) {

        self.userInteractionEnabled = NO;

        SKNode* root = [SKNode new];
        root.name = @"root";
        SKNode* layer1 = [SKNode new];
        SKNode* layer2 = [SKNode new];

        layer1.zPosition = -1;//layer1 and layer2 are just containers
        layer2.zPosition = -2;


        Button* button = [Button spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(100, 100)];
        button.name = @"yellow button";
        button.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));

        [layer1 addChild:button];

        [root addChild:layer1];
        [root addChild:layer2];

        [self addChild:root];

    }
    return self;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    NSLog(@"Touch detected");
}

@end

我只是不明白为什么这在 8.1 上不起作用...我知道命中测试的顺序与渲染节点的顺序相反,但是实现点击行为的正确方法是什么?所以目前发生的事情是,当我在 7.1 上测试时,我收到消息“黄色按钮”,但在 8.1 上,我收到消息“检测到触摸”(当我打印节点名称时,它显示为 root)。我也因此而成为pointed to file a radar,但正如我所说,我用nodeAtPoint而不是nodeAtPoint解决了所有问题,所以我没有。因为我认为这不是错误,而是我的错误,因为在 7.1 上一切都很好。那么这是一个错误,还是别的什么?

【问题讨论】:

    标签: ios objective-c sprite-kit simulator zposition


    【解决方案1】:

    具有讽刺意味的是,根据我的数学,这似乎是 7.1 而不是 8.1 的错误。不过我还没有用 7.1 测试过。

    首先,我无法让您的任何代码与 self.userInteractionEnabled = NO; 一起使用,因为什么都不会收到。

    zPosition 在设置ignoreSiblingsOrder 时使用,但它基于其父级。因此,如果父级为 -1,而您添加一个子级为 0,则其渲染 zPosition 仍为 -1。触摸也是如此,但顺序相反。使用 userInteraction 渲染的最后一个获取触摸事件。

    希望这是有道理的。查看添加的 cmets 和调试。

    #import "GameScene.h"
    
    @interface Button : SKSpriteNode
    -(instancetype)initWithColor:(UIColor *)color size:(CGSize)size;
    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
    @end
    
    
    @implementation Button
    -(instancetype)initWithColor:(UIColor *)color size:(CGSize)size {
        self = [super initWithColor:color size:size];
        self.userInteractionEnabled = YES;
        return self;
    }
    
    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        NSLog(@"%@ hit", self.name);
    }
    @end
    
    @implementation GameScene
    
    -(id)initWithSize:(CGSize)size {
        if (self = [super initWithSize:size]) {
    
            SKNode* root = [SKNode new];
            root.name = @"root";
    
            SKNode* layer1 = [SKNode new];
            layer1.name = @"layer1";
    
            SKNode* layer2 = [SKNode new];
            layer2.name = @"layer2";
    
            layer1.zPosition = -1;//layer1 and layer2 are just containers
            layer2.zPosition = -2;
    
    
            Button* button = [Button spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(100, 100)];
            button.name = @"yellow button";
            button.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
    
            //layer1 is at -1 and button does not have a z so it will be -1 in the scene like its parent (-1+0)
            [layer1 addChild:button];
    
            //root is 0 layer1 is -1 (along with button) root is above layer1 and will recieve any touches
            [root addChild:layer1];
    
            //root is 0 layer2 is -2 layer1 (and button) are above layer2 and root is above layer1 root gets touch
            [root addChild:layer2];
    
            //nothing changes except root is added
            [self addChild:root];
    
            //button needs to be on same zPosition or higher to get touch
            //it is -1 because of parent node + 1 = 0
            //best if you do +2 to ensure it is above
    
    //        button.zPosition = 2;
    
        }
        return self;
    }
    
    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    
        for (UITouch *touch in touches)
        {
            CGPoint point = [touch locationInNode:self];
            SKNode *node = [self nodeAtPoint:point];
            NSLog(@"Touch detected: %@", node.name);
        }
    
    }
    

    另外我建议不要对 zPosition 使用负数。它确实使事情变得更加混乱。

    【讨论】:

    • 是的,谢谢...我很困惑,因为不同的模拟器提供不同的结果,我不知道哪个是正确的。我认为 7.1 工作正常。将按钮的 zPosition 设置为高于父母的 zPosition 解决了问题..
    猜你喜欢
    • 2012-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多