Search code examples
iossprite-kitskshapenodecgpathref

Drawing line with Touch iOS Sprite Kit


Im using the following code to draw lines in my sprite kit scene but nothing shows up. But the node counts goes up. Can anyone see what could be the problem. Ive been fighting with this code forever

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch* touch = [touches anyObject];
    CGPoint positionInScene = [touch locationInNode:self];

    pathToDraw = CGPathCreateMutable();
    CGPathMoveToPoint(pathToDraw, NULL, positionInScene.x, positionInScene.y);

    lineNode = [SKShapeNode node];
    lineNode.path = pathToDraw;
    lineNode.strokeColor = [SKColor redColor];
    //lineNode.lineWidth = 2;
    [self addChild:lineNode];
}

- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    UITouch* touch = [touches anyObject];
    CGPoint positionInScene = [touch locationInNode:self];
    CGPathAddLineToPoint(pathToDraw, NULL, positionInScene.x, positionInScene.y);
    lineNode.path = pathToDraw;

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{

  //  lineNode.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:pathToDraw];
  //  lineNode.physicsBody.dynamic = NO;
  //  lineNode.physicsBody.categoryBitMask = lines;
  //  lineNode.physicsBody.contactTestBitMask = 0;
  //  lineNode.physicsBody.collisionBitMask = blueParticles | redParticles| yellowParticles;

    CGPathRelease(pathToDraw);
}

Edit------ Code works when background node removed..How can I set up my background node so that I can daw overtop? Thanks

SKSpriteNode *background;

        if(screenHeight == 480){
            background = [SKSpriteNode spriteNodeWithImageNamed:@"iPhone4BG.png"];
        }
        if(screenHeight == 568){
            background = [SKSpriteNode spriteNodeWithImageNamed:@"iPhone5BG.png"];
        }
        if(screenHeight == 667){
            background = [SKSpriteNode spriteNodeWithImageNamed:@"iPhone6BG.png"];
        }
        if(screenHeight == 736){
            background = [SKSpriteNode spriteNodeWithImageNamed:@"iPhone6PlusBG.png"];
        }

        background.position = CGPointMake(screenWidth/2, screenHeight/2);
        background.size = CGSizeMake(screenWidth, screenHeight);

       // [self addChild:background];

Solution

  • NOTE Core issue was Simulator not rendering a path that isn't closed. On the device the issue doesn't exist. Also a background element was involved that the original poster didn't mention and wasn't represented in code. This answer will solve the issue on the simulator.

    To fix your problem, modify your code as follows :

    - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
    {
        UITouch* touch = [touches anyObject];
        CGPoint positionInScene = [touch locationInNode:self];
        CGPathAddLineToPoint(pathToDraw, NULL, positionInScene.x, positionInScene.y);
        // add this line to fix your issue
        CGPathMoveToPoint(pathToDraw, NULL, positionInScene.x, positionInScene.y);
        lineNode.path = pathToDraw;
    
    }
    

    The core issue is that when it goes to render the path, it doesn't have a complete path. Your current approach is to be constantly modifying the path on each touchMove.

    The way you close a sub path is :

    CGPathCloseSubpath(pathToDraw);
    

    However I chose to just use CGPathMoveToPoint each time you added a segment to the path.

    From CGPath reference for CGPathMoveToPoint :

    This function ends the subpath already in progress (if any) and starts a new subpath, initializing the starting point and the current point to the specified location (x,y) after an optional transformation.

    I am closing the current subpath before it gets rendered, and also setting the start location for the next segment.

    However, you are going to run into major issues with performance as defined in the link in the the comments if you are going to be drawing a long line or many lines. Draw a really long line, and you will see what I mean. With minimal line drawing, you might get away with the current approach.

    Sadly, drawing of this nature with SKShapeNode is not as optimized as it should be.