【问题标题】:Detect what instance of SKSpriteNode was touched?检测触摸了哪个 SKSpriteNode 实例?
【发布时间】:2014-03-09 15:58:26
【问题描述】:

我正在使用此代码来检测并查看用户点击是否在我的 SKSpriteNode 的框架内,如果是,则从屏幕上删除该节点。但我只想让被点击的节点消失。

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */

    for (UITouch *touch in touches) {
            CGPoint location = [touch locationInNode:self];

        if ((location.x > self.crate.frame.origin.x && location.x < self.crate.frame.origin.x + self.crate.frame.size.width) &&
            (location.y > self.crate.frame.origin.y && location.y < self.crate.frame.origin.y + self.crate.frame.size.height)) {

            [self.crate removeFromParent];
        }
    }
}

在我的更新方法中,我调用了一个方法 addCrate: 来每秒生成节点。

- (void)updateWithTimeSinceLastUpdate:(CFTimeInterval)timeSinceLast {

    self.lastSpawnTimeInterval += timeSinceLast;
    if (self.lastSpawnTimeInterval > 1) {
        self.lastSpawnTimeInterval = 0;
        [self addCrate];
    }
}

- (void)update:(NSTimeInterval)currentTime {
    // Handle time delta.
    // If we drop below 60fps, we still want everything to move 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)addCrate {

    // Create sprite
        self.crate = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:CGSizeMake(30, 30)];
        //self.crate.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.crate.frame.size];

    // Determine where to spawn the crate along the X axis
        int minX = self.crate.size.width / 2;
        int maxX = self.frame.size.width - self.crate.size.width / 2;
        int rangeX = maxX - minX;
        int actualX = (arc4random_uniform(rangeX)) + minX;

    // Create the crate slightly off-screen along the top,
    // and along a random position along the X axis as calculated above
        self.crate.position = CGPointMake(actualX, self.frame.size.height + self.crate.size.height/2);
        [self addChild:self.crate];
        self.crate.size = CGSizeMake(50, 50);


    // Determine speed of the crate
        int actualDuration = 3.5;

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

但是当我在我的 iPhone 上运行时,只有有时会注册点击并从屏幕上删除块,有时不会。同样,我希望被点击的节点消失,并且只有那个节点。

谢谢!

U1

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

        self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
        [self addCrate];
    }
        return self;
}

- (void)addCrate {

    // Create sprite
        self.crate = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:CGSizeMake(30, 30)];
    self.crate.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(30, 30)];
        self.crate.userInteractionEnabled = YES;
        //self.crate.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.crate.frame.size];

    // Determine where to spawn the crate along the X axis
        int minX = self.crate.size.width / 2;
        int maxX = self.frame.size.width - self.crate.size.width / 2;
        int rangeX = maxX - minX;
        int actualX = (arc4random_uniform(rangeX)) + minX;

    // Create the crate slightly off-screen along the top,
    // and along a random position along the X axis as calculated above
        self.crate.position = CGPointMake(actualX, self.frame.size.height + self.crate.size.height/2);
        [self addChild:self.crate];
        self.crate.size = CGSizeMake(50, 50);


    // Determine speed of the crate
        int actualDuration = 3.5;

    // Create the actions
        SKAction * actionMove = [SKAction moveTo:CGPointMake(actualX, -self.crate.size.height/2) duration:actualDuration];
        SKAction * actionMoveDone = [SKAction removeFromParent];
        [self.crate 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];

    NSLog(@"touchLocation x: %f and y: %f", touchLocation.x, touchLocation.y);

    if (touchedNode != self) {
        NSLog(@"Removed from parent.");
        [touchedNode removeFromParent];
    }
}


- (void)updateWithTimeSinceLastUpdate:(CFTimeInterval)timeSinceLast {

    self.lastSpawnTimeInterval += timeSinceLast;
    if (self.lastSpawnTimeInterval > 1) {
        self.lastSpawnTimeInterval = 0;
        [self addCrate];
    }
}

- (void)update:(NSTimeInterval)currentTime {
    // Handle time delta.
    // If we drop below 60fps, we still want everything to move 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];

}

【问题讨论】:

    标签: sprite-kit touchesbegan skspritenode


    【解决方案1】:

    我认为您应该在创建 crate 并在 touchBegan: 方法中检查它们时使用设置 node.name 属性的组合。

    类似这样的:

    SKSpriteNode *crate = [SKSpriteNode spriteNodeWithTexture:tex];
    crate.name = @"crate";
    

    还有touchBegan:方法:

    .....
    if ([touchedNode.name isEquelToString:@"crate"]){
       // do something with that node
    }
    .....
    

    更新1:

    而不是写这些东西:

    if ((location.x > self.crate.frame.origin.x && location.x < self.crate.frame.origin.x + self.crate.frame.size.width) &&
            (location.y > self.crate.frame.origin.y && location.y < self.crate.frame.origin.y + self.crate.frame.size.height)) {
    
            [self.crate removeFromParent];
        }
    

    使用:

    if(CGRectContainsPoint(self.frame, touchPoint)){
       // do something
    }
    

    更新2:

    在您的代码中看不到您在 crate 节点上设置 userInteractionEnabled = YES。

    更新3:

    这是一个例子:

    //
    //  BGMyScene.m
    //  Test1
    //
    //  Created by AndrewShmig on 3/10/14.
    //  Copyright (c) 2014 Bleeding Games. All rights reserved.
    //
    
    #import "BGMyScene.h"
    
    @implementation BGMyScene
    
    - (id)initWithSize:(CGSize)size
    {
        if (self = [super initWithSize:size]) {
            /* Setup your scene here */
    
            self.backgroundColor = [SKColor colorWithRed:0.15
                                                   green:0.15
                                                    blue:0.3
                                                   alpha:1.0];
    
    //      first label
            SKLabelNode *myLabel = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
    //        myLabel.userInteractionEnabled = YES;
            myLabel.text = @"Hello, World!";
            myLabel.fontSize = 30;
            myLabel.position = CGPointMake(CGRectGetMidX(self.frame),
                                           CGRectGetMidY(self.frame));
            [self addChild:myLabel];
    
    //      second label
            SKLabelNode *myLabel2 = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
    //        myLabel2.userInteractionEnabled = YES;
            myLabel2.text = @"Hello, World!";
            myLabel2.fontSize = 30;
            myLabel2.position = CGPointMake(100, 100);
            [self addChild:myLabel2];
        }
        return self;
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        UITouch *touch = [touches anyObject];
        CGPoint touchLocation = [touch locationInNode:self];
        SKNode *touchedNode = [self nodeAtPoint:touchLocation];
    
        NSLog(@"touchLocation x: %f and y: %f", touchLocation.x, touchLocation.y);
    
        if (touchedNode != self) {
            NSLog(@"Removed from parent.");
            [touchedNode removeFromParent];
        }
    }
    
    - (void)update:(CFTimeInterval)currentTime
    {
        /* Called before each frame is rendered */
    }
    
    @end
    

    您将看到以下屏幕:

    点击“Hello, World!”后标签它们将从父节点中删除。

    【讨论】:

    • 是的,我已将 userInteractionEnabled 设置为是。但我做了更正,它仍然不起作用。
    • 在touchBegan:方法中,如何判断是哪个节点被触摸了?
    • 那么我从哪里得到“touchedNode”?
    • @IsaRanjha,确定你应该触摸哪个节点(实际上你可以离开 name = nil 并使用节点的 userData 属性)在创建节点后设置节点的 name 属性。之后,签入 touchBegan: 方法节点名称并执行所需的操作。请参阅(nodeAtPoint: 和 nodesAtPoint: 方法)developer.apple.com/Library/ios/documentation/SpriteKit/…:
    • 知道了。但是,如果我将所有东西都命名为相同的东西(@“crate”),它们不会全部消失吗?我怎么知道哪个被窃听了?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-06
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多