使用SKShapeNode和CGPath在Sprite Kit中绘制虚线

6

我想在我的Sprite Kit游戏中画一条虚线,我可以使用SKShapeNode节点来绘制普通的线条,如下所示:

 UIBezierPath *_path=[UIBezierPath bezierPath];
 //1
 CGPoint point1 = CGPointMake(100,100);
 CGPoint point2 = CGPointMake(150,150);
 [_path moveToPoint:point1];
 [_path addLineToPoint:point2];
 //2
 SKShapeNode *line = [SKShapeNode node];
 line.path = _path.CGPath;

我尝试为UIBezierPath设置虚线模式,像这样:

// adding this code at location 1 or 2 above but no effect
CGFloat dashes[] = {6, 2};
[_path setLineDash:dashes count:2 phase:0];

但虚线模式未被应用。

我还尝试直接从UIBezierpath.CGPath属性创建虚线副本,如下所示:

 CGFloat dashes[] = {6, 2};
 CGPathRef aCGPath= CGPathCreateCopyByDashingPath(_path.CGPath,NULL,0,dashes,2);
line.path = aCGPath;

但同时也是一样的。

如果有人能够解释一下问题,并告诉我如何通过将虚线cgpath应用于skshapenode来在两个点之间绘制虚线,我会非常感激。

编辑:我知道对于这个简单的例子,我可以将这两个点之间的距离分成小的固定距离,然后通过bezeirpath移动和绘制虚线,但考虑到手指滑动生成的自由路径,重新绘制具有固定长度点的路径并绘制虚线非常复杂且低效。我想知道是否有一种方法可以将虚线图案应用于路径,并使skshapenode使用它,这就是我的问题。

2个回答

10
如果有人仍然对这个问题感兴趣: 使用CGPathCreateCopyByDashingPath创建一个虚线副本 - [UIBezierCurve CGPath]
CGPathRef CGPathCreateCopyByDashingPath(
   CGPathRef path,
   const CGAffineTransform *transform,
   CGFloat phase,
   const CGFloat *lengths,
   size_t count
);

并将其添加到SKShapeNodepath属性中。

示例:

    // creates a dashed pattern
    CGFloat pattern[2];
    pattern[0] = 10.0;
    pattern[1] = 10.0;
    CGPathRef dashed =
    CGPathCreateCopyByDashingPath([bezierPath CGPath],
                                  NULL,
                                  0,
                                  pattern,
                                  2);

    self.myShapeNode.path = dashed;

    CGPathRelease(dashed);

编辑:为了提高性能,您可以将SKShapeNode添加到SKEffectNode中,并将shouldRasterize属性设置为YES


你的解决方案非常好!但我不理解你的性能评论。你是说将shapenode添加到effectnode中,然后将effectnode添加到场景中?就像在effect node上设置rasterize一样吗?你能否澄清一下?谢谢! - Thunk
1
如果您直接使用SKShapeNode,它将在每一帧绘制路径。如果您按照上述描述使用SKEffectNode,它将缓存路径的位图版本,因此渲染速度更快(仅适用于不经常更改的路径)。 - Binary Pulsar
1
嘿,谢谢你的回答,虽然有点晚了,但我最终还是解决了那个问题。由于性能和奇怪的内存泄漏问题,我最终没有使用SKShapeNode,而是使用SKSpriteNode来绘制虚线(每个短划线都是一个SKSpriteNode)。为了保持性能,我使用了单个“虚线图像”的SKTexture,结果非常完美。 我会将你的答案标记为已接受,这样任何想要使用SKShapeNode解决问题的人都可以在这里找到解决方案。 - Androyal

0

将位置1处的代码更改为以下内容:

UIBezierPath *_path=[UIBezierPath bezierPath];
CGPoint point1 = CGPointMake(100,100);
CGPoint point2 = CGPointMake(150,150);
CGFloat deltaX = 1;
CGFloat deltaY = 1;
CGPoint tmpPoint = point1;
[_path moveToPoint:point1];
while(tmpPoint.x<point2.x && tmpPoint.y<point2.y){
    tmpPoint.x+=deltaX;
    tmpPoint.y+=deltaY;
    if((tmpPoint.y-point1.y)%2==1){
       [_path addLineToPoint:tmpPoint];
    }else{
      [_path moveToPoint:tmpPoint];
    }
}
// If the line is not a 45 degree straight line
// Please modify the while loop accordingly
[_path addLineToPoint:point2];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接