SKSpriteNode遵循bezier路径旋转



我想做的是:使SKSpriteNode遵循一个UIBezierPath,其中端点是用户触摸的位置。

问题:当用户触摸时,我将位置发送给处理移动它的播放器节点。然而,这只适用于玩家节点向上"指向"时,例如在第一次触碰时。其他触碰会让玩家移动到错误的点。

描述问题的图片:https://i.stack.imgur.com/nleXj.png
我在photoshop中添加了一些解释,下面是一个解释:
- Thick>是我正在移动的SKSpriteNode。
-紫色方块是触摸的确切位置,按顺序编号(实际上是为了调试目的添加的SKSpriteNodes)
-细箭头是球员在触球时的位置。

我认为问题出在玩家节点坐标系统和场景坐标系统之间的转换上。
例如:第一次触碰(当玩家的旋转方向没有改变时)会将玩家移动到正确的位置。然而,第二次触摸在玩家节点坐标系中是向左的,但随后它在场景坐标系中基本上是向左的,就好像触摸是随着节点旋转的,如果它被旋转到指向上方。

代码:
GameScene。m:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */
    for (UITouch *touch in touches) {
        [self playRiddle];
        CGPoint touchPoint = [touch locationInNode:_player];
        [_player moveTo:touchPoint];
        SKSpriteNode *n = [SKSpriteNode spriteNodeWithColor:[UIColor purpleColor] size:CGSizeMake(10, 10)];
        n.position = [self convertPoint:touchPoint fromNode:_player];
        [_worldNode addChild:n];
    }
}

Player.m:

- (void)moveTo:(CGPoint)point {
    _moving = YES;
    [self removeActionForKey:@"move"];
    CGVector vector = [self convertAngleToVector:[self shipOrientation]];
    CGPoint controlPoint = CGPointMake(vector.dx, vector.dy);
    UIBezierPath *path = [self createPathWindEndPoint:point controlPoint:controlPoint];
    SKAction *move = [SKAction followPath:[path CGPath] asOffset:YES orientToPath:YES speed:15];
    SKAction *done = [SKAction runBlock:^{
        _moving = NO;
    }];
    [self runAction:[SKAction sequence:@[move, done]] withKey:@"move"];
}
- (UIBezierPath *)createPathWindEndPoint:(CGPoint)endpoint controlPoint:(CGPoint)cp {    
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointZero];
    [path addQuadCurveToPoint:endpoint controlPoint:cp];
    //Draw path
    SKShapeNode *line = [SKShapeNode node];
    line.path = [path CGPath];
    [line setStrokeColor:[UIColor darkGrayColor]];
    line.position = self.position;
    [self.parent addChild:line];
    return path;
}
- (CGVector)convertAngleToVector:(CGFloat)radians {
    CGVector vector;
    vector.dx = cos(radians) * 25;
    vector.dy = sin(radians) * 25;
    return vector;
}
- (CGFloat)shipOrientation {
    return self.zRotation + M_PI_2;
}

_player节点的父节点是一个添加到GameScene中的SKNode。我用[node convertPoint: ..]尝试了很多东西。但没有成功。希望你能给我指点一下方向。

谢谢!

我建议你使用绝对场景坐标而不是相对节点坐标来创建路径。下面是一个示例:

GameScene

1)在touchesBegan中,进行以下更改,将触摸位置转换为场景坐标

CGPoint touchPoint = [touch locationInNode:self];

Player.m

2)修改以下内容,以场景坐标创建路径(见注释)

- (void)moveTo:(CGPoint)point {
    _moving = YES;
    [self removeActionForKey:@"move"];
    CGVector vector = [self convertAngleToVector:[self shipOrientation]];
    // Offset the control point by the node's position
    CGPoint controlPoint = CGPointMake(vector.dx+self.position.x, vector.dy+self.position.y);
    UIBezierPath *path = [self createPathWindEndPoint:point controlPoint:controlPoint];
    // Use absolute path
    SKAction *move = [SKAction followPath:[path CGPath] asOffset:NO orientToPath:YES speed:15];
    SKAction *done = [SKAction runBlock:^{
        _moving = NO;
    }];
    [self runAction:[SKAction sequence:@[move, done]] withKey:@"move"];
}
- (UIBezierPath *)createPathWindEndPoint:(CGPoint)endpoint controlPoint:(CGPoint)cp {
    UIBezierPath *path = [UIBezierPath bezierPath];
    // Use scene coordinates
    [path moveToPoint:self.position];
    [path addQuadCurveToPoint:endpoint controlPoint:cp];
    //Draw path
    SKShapeNode *line = [SKShapeNode node];
    line.path = [path CGPath];
    [line setStrokeColor:[UIColor darkGrayColor]];
    // Line relative to the origin
    line.position = CGPointZero;
    [self.parent addChild:line];
    return path;
}

如果您想在一个节点和它的父节点之间转换点,那么试试下面的代码:

CGPoint myPoint = [self convertPoint:myNode.position fromNode:myNode.parent];

你还应该看看在视图和场景坐标之间转换

最新更新