Drawing dashed line in Sprite Kit using SKShapeNod

2019-04-09 05:42发布

问题:

I want to draw a dashed line in my sprite kit game, I can use SKShapeNode node to draw a normal line like the following:

 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;

I tried to set a dashed pattern to UIBezierPath like this:

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

but the dashed pattern is not applied.

I also tried to create a dashed copy of CGPath directly from UIBezierpath.CGPath property as:

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

but also the same.

I really appreciate if someone could explain what is the problem and how can I draw a dashed line between two points by applying dashed cgpath to skshapenode.

Edit: I know for this simple example I could divide the distance between these two points to small fixed distances and moving and drawing dashed line by bezeirpath but consider a free hand path with points came from touches, it is a very complex and inefficient to redraw the path with fixed length points then draw dashes. I wonder if there is a way to apply the dashed pattern to the path and making skshapenode to use it that is my question.

回答1:

If anyone is still interested in a simple answer to this question:

Use CGPathCreateCopyByDashingPath to create a dashed copy of - [UIBezierCurve CGPath]

CGPathRef CGPathCreateCopyByDashingPath(
   CGPathRef path,
   const CGAffineTransform *transform,
   CGFloat phase,
   const CGFloat *lengths,
   size_t count
);

and add it to the SKShapeNode's path property.

Example:

    // 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);

EDIT: For performance, you can add an SKShapeNode to an SKEffectNode and set the shouldRasterize property to YES.



回答2:

Change the code at location 1 to something like this:

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