检测SpriteKit中节点半径内的触摸

时间:2014-08-17 20:31:52

标签: objective-c xcode sprite-kit

我的SpriteKit游戏中有一个玩家对象,目前我正在使用以下代码移动它:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (touches.count == 1)
    {
        [self touchesMoved:touches withEvent:event];
    }
}


-(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    if (touches.count == 1)
    {
        [_player runAction:[SKAction moveTo:[[touches anyObject] locationInNode:self] duration:0.01]];
    }
}

但我只想在触摸位于该位置的特定范围内时移动播放器节点。

3 个答案:

答案 0 :(得分:3)

由于看起来您只关心触摸与_player对象的距离,我会将半径检测逻辑移动到您的_player对象并使用SKRegion来处理它

注意: 如果您需要知道触摸是否在多个节点的半径范围内,那么您可能希望使用this question中的方法。

要使用SKRegion确定您的触摸是否在_player的某个半径范围内,请在SKRegion对象中添加_player实例并使用半径初始化它你要。在[_player init]或其对您的项目最有意义的地方:

self.touchRegion = [[SKRegion alloc] initWithRadius:radius];

然后添加一个方法来确定某个点是否在该区域内:

- (BOOL)pointIsInTouchRegion:(CGPoint)point {
    return [self.touchRegion containsPoint: point];
}

接下来将您的touchesMoved方法更改为:

-(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    if (touches.count == 1)
    {
        UITouch *touch = [touches anyObject];
        CGPoint point = [self locationInNode:_player]; // NOTE: It's important to use _player here!
        if ([_player pointIsInTouchRegion: point]) {
            [_player runAction:[SKAction moveTo:[[touches anyObject] locationInNode:self] duration:0.01]];
        }
    }
}

注意: _player中使用[self locationInNode:_player];至关重要,因为您的SKRegion将在_player节点的坐标系中定义。

还有一点需要注意:你不必将所有逻辑放在_player中,这就是我的方式。您可以轻松地将SKRegion存储在场景的类中,并直接在其上调用[region containsPoint: point]


更新:iOS 7方法

在iOS 7中执行此操作的主要区别在于,您需要存储您感兴趣的实际半径而不是SKRegion(因为它仅在iOS 8中可用),然后自己进行计算在pointIsInTouchRegion:

因此,在_player中,设置您之前设置touchRegion的触摸半径:

self.touchRadius = radius

然后更改pointIsInTouchRegion:方法,使其进行实际距离计算。

- (BOOL)pointIsInTouchRegion:(CGPoint)point {
    CGPoint centerOfNode = CGPointMake(self.frame.size.width / 2.0, self.frame.size.height / 2.0); // NOTE: If this is in an SKSpriteNode, you might want to use self.anchorPoint instead
    CGFloat distanceToCenter = return hypotf(point.x - centerOfNode.x, point.y - centerOfNode.y);
    return (distanceToCenter <= self.radius);
}

touchesMoved中的代码不需要任何更改。

答案 1 :(得分:1)

以下演示如何1)选择距离触摸事件指定距离内的精灵,以及2)将所选精灵拖放到新位置。

@interface MyScene()

@property (weak) SKSpriteNode *selectedNode;

@end

@implementation MyScene

-(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];

        // Add three sprites to scene
        SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size:CGSizeMake(32, 32)];
        sprite.name = @"Blue";
        sprite.position = CGPointMake(CGRectGetMidX(self.frame),
                                      CGRectGetMidY(self.frame)-64);
        [self addChild:sprite];

        sprite = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(32, 32)];
        sprite.name = @"Red";
        sprite.position = CGPointMake(CGRectGetMidX(self.frame),
                                      CGRectGetMidY(self.frame) + 64);
        [self addChild:sprite];


        sprite = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(32, 32)];
        sprite.name = @"Green";
        sprite.position = CGPointMake(CGRectGetMidX(self.frame),
                                      CGRectGetMidY(self.frame));

        [self addChild:sprite];
    }
    return self;
}

#define kRadius     64

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    _selectedNode = nil;
    CGFloat minDistance = kRadius+1;
    for (UITouch *touch in touches) {
        CGPoint location = [touch locationInNode:self];
        for (SKSpriteNode *node in self.children) {
            CGFloat dx = location.x - node.position.x;
            CGFloat dy = location.y - node.position.y;
            // Compute distance from sprite to tap point
            CGFloat distance = sqrtf(dx*dx+dy*dy);
            if (distance <= kRadius) {
                if (distance < minDistance) {
                    // Select the closest node so far
                    _selectedNode = node;
                    minDistance = distance;
                }
            }
        }
    }
}

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self];
    if (_selectedNode) {
        // Move selected node to current touch position
        _selectedNode.position = location;
    }
}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    // Unselect node
    _selectedNode = nil;
}

- (void) update:(CFTimeInterval)currentTime {
    /* Called before each frame is rendered */
}

@end

答案 2 :(得分:0)

我认为你应该补充一下,如果我错误地理解你的问题,请原谅我:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   CGPoint point = [touch locationInView:self.view];

if (touches.count == 1) && (point.x == yourObjectsXPosition) && (point.y ==  yourObjectsYPosition) 

     {
    [self touchesMoved:touches withEvent:event];
     }
}