ddb ddb - 3 months ago 47
iOS Question

How to draw a line in SpriteKit efficiently

In my SpriteKit scene, user should be able to draw line with his/her finger. I have a working solution, if the line is long, FPS gets down to 4-6 and the line starts to get polygonal, as the image below:

enter image description here

To draw

myline
(
SKShapeNode*
), I collect points of touches movement in an
NSMutableArray* noteLinePoints
in this way

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint touchPoint = [[touches anyObject] locationInNode:self.scene];
SKNode *node = [self nodeAtPoint:touchPoint];

if(noteWritingActive)
{
[noteLinePoints removeAllObjects];
touchPoint = [[touches anyObject] locationInNode:_background];
[noteLinePoints addObject:[NSValue valueWithCGPoint:touchPoint]];
myline = (SKShapeNode*)node;
}
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if(myline)
{
CGPoint touchPoint = [[touches anyObject] locationInNode:_background];
[noteLinePoints addObject:[NSValue valueWithCGPoint:touchPoint]];
[self drawCurrentNoteLine];
}
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
if(myline)
{
myline.name = @"note";
myline = nil;
}
NSLog(@"touch ended");
}


and I draw the line in this way

- (CGPathRef)createPathOfCurrentNoteLine
{
CGMutablePathRef ref = CGPathCreateMutable();

for(int i = 0; i < [noteLinePoints count]; ++i)
{
CGPoint p = [noteLinePoints[i] CGPointValue];
if(i == 0)
{
CGPathMoveToPoint(ref, NULL, p.x, p.y);
}
else
{
CGPathAddLineToPoint(ref, NULL, p.x, p.y);
}
}

return ref;
}

- (void)drawCurrentNoteLine
{
if(myline)
{
SKNode* oldLine = [self childNodeWithName:@"line"];
if(oldLine)
[self removeChildrenInArray:[NSArray arrayWithObject:oldLine]];

myline = nil;

myline = [SKShapeNode node];
myline.name = @"line";
[myline setStrokeColor:[SKColor grayColor]];

CGPathRef path = [self createPathOfCurrentNoteLine];
myline.path = path;
CGPathRelease(path);

[_background addChild:myline];
}
}


How can I fix this problem? because all subsequent lines are all polygonal only, I think because the fps is very low and sampling rate of touches automatically get also very low...

Please note that for the test I used an iPad 3 (my app needs to be working from iPad 2 model with iOS7)

Answer

Do not constantly create new SKShapeNodes, there is a bug which is causing your slowdown. Instead, only use 1 SKShapeNode (Or create a bunch but reuse them), and append the path with new info (So there is no need to constantly add the myline to the background)

Alternative:

Use 1 community SKSkapeNode for rendering of the path, then convert the SKShapeNode to a texture with view.textureFromNode, then add an SKSpriteNode with this new texture instead of the shape node