检测 SKNode 上的双击

Posted

技术标签:

【中文标题】检测 SKNode 上的双击【英文标题】:Detect double tap on SKNode 【发布时间】:2014-03-12 02:48:19 【问题描述】:

好的,所以我的代码会在 1 到 2 之间选择一个随机数,并根据该随机数生成一个 metalCrate: 或只是一个 crate:。我想,金属板条箱应该需要点击 2 次才能消失。不幸的是,使用我的代码,这是行不通的。

@interface MyScene () <SKPhysicsContactDelegate>

@property (nonatomic) NSTimeInterval lastSpawnTimeInterval;
@property (nonatomic) NSTimeInterval lastUpdateTimeInterval;
@property (nonatomic) SKSpriteNode *crate;
@property (nonatomic) SKSpriteNode *metalCrate;
@property (nonatomic) SKLabelNode *scoreLabel;
@property (nonatomic) int score;

@end

@implementation MyScene

-(id)initWithSize:(CGSize)size 

    if (self = [super initWithSize:size]) 

        self.backgroundColor = [SKColor whiteColor];
        _score = 0;

        _scoreLabel = [SKLabelNode labelNodeWithFontNamed:@"Helvetica Neue"];
        _scoreLabel.text = [NSString stringWithFormat:@"%d", self.score];
        _scoreLabel.fontSize = 25;
        _scoreLabel.fontColor = [SKColor blackColor];
        _scoreLabel.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
        _scoreLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;
        _scoreLabel.position = CGPointMake(20, 27);
        [self addChild:_scoreLabel];
    

    return self;


- (void)addCrate:(SKColor*)color withDuration:(int)duration withSize:(CGSize)size withMinX:(int)minX withMaxX:(int)maxX 
    self.crate = [SKSpriteNode spriteNodeWithColor:color size:size];
    self.crate.color = color;

    int rangeX = maxX - minX;
    int actualX = (arc4random_uniform(rangeX)) + minX;

    self.crate.position = CGPointMake(actualX, self.frame.size.height + self.crate.size.height/2);
    [self addChild:self.crate];
    self.crate.size = size;

    SKAction * actionMove = [SKAction moveTo:CGPointMake(actualX, -self.crate.size.height/2) duration:duration];
    SKAction * actionMoveDone = [SKAction removeFromParent];
    [self.crate runAction:[SKAction sequence:@[actionMove, actionMoveDone]]];


- (void)addMetalCrate:(SKColor*)color withDuration:(int)duration withSize:(CGSize)size withMinX:(int)minX withMaxX:(int)maxX 
    self.metalCrate = [SKSpriteNode spriteNodeWithColor:color size:size];
    self.metalCrate.color = color;

    int rangeX = maxX - minX;
    int actualX = (arc4random_uniform(rangeX)) + minX;

    self.metalCrate.position = CGPointMake(actualX, self.frame.size.height + self.metalCrate.size.height/2);
    [self addChild:self.metalCrate];
    self.metalCrate.size = size;

    SKAction * actionMove = [SKAction moveTo:CGPointMake(actualX, -self.metalCrate.size.height/2) duration:duration];
    SKAction * actionMoveDone = [SKAction removeFromParent];
    [self.metalCrate runAction:[SKAction sequence:@[actionMove, actionMoveDone]]];


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 

    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInNode:self];
    SKNode *touchedNode = [self nodeAtPoint:touchLocation];

    if (touchedNode != self && touchedNode != self.scoreLabel && [self nodeAtPoint:touchLocation] == self.crate) 
        NSLog(@"Node has been touched. Single tap.");
        [touchedNode removeFromParent];
        [self updateScore:1];
     else if (touchedNode != self && touchedNode != self.scoreLabel && [self nodeAtPoint:touchLocation] == self.metalCrate && [touch tapCount] == 2) 
        NSLog(@"Node has been touched.  Double tap.");
        [touchedNode removeFromParent];
        [self updateScore:2];
    


- (void)updateScore:(int)amount 

    _score += amount;
    _scoreLabel.text = [NSString stringWithFormat:@"%d", self.score];


- (void)update:(NSTimeInterval)currentTime 
    // Handle time delta.
    // If we drop below 60fps, we still want everything to movbe the same distance.
    CFTimeInterval timeSinceLast = currentTime - self.lastUpdateTimeInterval;
    self.lastUpdateTimeInterval = currentTime;
    if (timeSinceLast > 1)  // more than a second since last update
        timeSinceLast = 1.0 / 60.0;
        self.lastUpdateTimeInterval = currentTime;
    

    [self updateWithTimeSinceLastUpdate:timeSinceLast];


- (void)updateWithTimeSinceLastUpdate:(CFTimeInterval)timeSinceLast 

    self.lastSpawnTimeInterval += timeSinceLast;
    if (self.lastSpawnTimeInterval > 0.5) 

        self.lastSpawnTimeInterval = 0;

        //Modify instance properties here

        int random = (arc4random() % 2) + 1;
        //NSLog(@"%d", random);

        if (random == 1) 

            [self addCrate:[SKColor grayColor] withDuration:3.75 withSize:CGSizeMake(45, 45)
                  withMinX:self.crate.size.width / 2 withMaxX:self.frame.size.width - self.crate.size.width / 2];

         else 

            [self addMetalCrate:[SKColor redColor] withDuration:3 withSize:CGSizeMake(50, 50)
                  withMinX:self.crate.size.width / 2 withMaxX:self.frame.size.width - self.crate.size.width / 2];
        

        //Modify instance properties here
    


@end

解释一下,我认为问题在于检测触摸是在 metalCrate 上还是只是在 crate 上,我正在将 git 与触摸的位置进行比较。

提前谢谢你!

【问题讨论】:

【参考方案1】:

您可以为您的 crate 和 metal crate 节点命名,然后简单地使用该名称进行比较。

[self.crate setName:@"crate"];
[self.metalCrate setName:@"metalCrate"];

编辑你的 -touchesBegan: 方法如下:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 

    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInNode:self];
    SKNode *touchedNode = [self nodeAtPoint:touchLocation];

    if ([touchedNode.name isEqualToString:@"crate"] && [touch tapCount] == 1) 
        NSLog(@"Crate node has been touched. Single tap.");
        [touchedNode removeFromParent];
        [self updateScore:1];
     else if ([touchedNode.name isEqualToString:@"metalCrate"] && [touch tapCount] == 2) 
        NSLog(@"Metal crate node has been touched.  Double tap.");
        [touchedNode removeFromParent];
        [self updateScore:2];
    

【讨论】:

谢谢,但似乎没有节点检测到触摸? 我想我知道为什么。我扔进了一个 NSLog,touchedNode.name 返回了 null。 好的,所以我尝试设置 touchNode.name = [self nodeAtPoint:touchLocation].name;但这也返回 null。【参考方案2】:

想通了。

我所做的只是使用比较字符串的想法。在这种情况下,我比较了节点的大小以确定它是什么。

感谢您的帮助!

【讨论】:

这很好,但是比较节点的大小仍然不是很干净或绝对。 还有什么其他方法可以做到吗?名称返回 null。另外,我正在使用 [touch tapCount];检测双击,但它不是恒定的,有时它似乎被检测到有时没有。有什么方法可以添加 UITapGestureRecognizer? UITapGestureRecognizer 也适用于节点。你可以使用它。 你能告诉我如何将它与节点一起使用吗?也许一些示例代码? 对不起,我错了。您必须将 UITapGestureRecognizer 添加到 SKView 而不是 SKScene 并在选择器方法中处理点击。看看这里如何:***.com/questions/11355671/…

以上是关于检测 SKNode 上的双击的主要内容,如果未能解决你的问题,请参考以下文章

如何检测视图上的双击? [复制]

Objective-c:如何检测视图上的双击?

如何在 UICollectionView 中检测“仅单指”单元格上的双击?

如何检测 MudBlazor 中表格行的双击?

如何检测 QTableView 中的双击

检测Java Swing中的双击