Paolo Furlan
Paolo Furlan

Reputation: 92

Move a SKNode around a circle

i am moving my sknode around a circle created with this code:

    circleDiameter = 300;
    pathCenterPoint = CGPointMake(self.position.x - circleDiameter/2, self.position.y - circleDiameter/2);

    UIBezierPath *circlePath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(pathCenterPoint.x, pathCenterPoint.y, circleDiameter, circleDiameter) cornerRadius:circleDiameter/2];
    self.actionClockwise = [SKAction followPath:circlePath.CGPath asOffset:false orientToPath:true duration:2];
    self.circleActionForever = [SKAction repeatActionForever:self.actionClockwise];
    [self runAction:self.actionCounterClockwise withKey:@"circleActionForever"];

And everything is working. Now i want that when an user tap on the screen to revert the direction and move the node in counterClockwise. I did that by running the same action with .reversedAction command.

But the action always restart from the start point.

I want to know if there is some kind of method to make start the animation from the point where the old animation is when the user tap on the screen?

Upvotes: 1

Views: 120

Answers (1)

Alessandro Ornano
Alessandro Ornano

Reputation: 35382

A UIBezierPath is composed by path Elements where the first is moveToPoint that , as explained in the official document, starts a new subpath at a specified location in a mutable graphics path.

So, unfortunately is not enough doing:

UIBezierPath *circlePathReversed = [circlePath bezierPathByReversingPath];

because when you stop your circle from following the path, the actual position of the circle is not the same of the moveToPoint point (coordinates x and y).

However you could rebuild your path retrieving all elements and re-starting from the actual circle position.

void MyCGPathApplierFunc (void *info, const CGPathElement *element) {
    NSMutableArray *bezierPoints = (__bridge NSMutableArray *)info;

    CGPoint *points = element->points;
    CGPathElementType type = element->type;

    switch(type) {
        case kCGPathElementMoveToPoint: // contains 1 point
            [bezierPoints addObject:[NSValue valueWithCGPoint:points[0]]];
            break;

        case kCGPathElementAddLineToPoint: // contains 1 point
            [bezierPoints addObject:[NSValue valueWithCGPoint:points[0]]];
            break;

        case kCGPathElementAddQuadCurveToPoint: // contains 2 points
            [bezierPoints addObject:[NSValue valueWithCGPoint:points[0]]];
            [bezierPoints addObject:[NSValue valueWithCGPoint:points[1]]];
            break;

        case kCGPathElementAddCurveToPoint: // contains 3 points
            [bezierPoints addObject:[NSValue valueWithCGPoint:points[0]]];
            [bezierPoints addObject:[NSValue valueWithCGPoint:points[1]]];
            [bezierPoints addObject:[NSValue valueWithCGPoint:points[2]]];
            break;

        case kCGPathElementCloseSubpath: // contains no point
            break;
    }
}

Usage:

NSMutableArray *bezierPoints = [NSMutableArray array];
CGPathApply(circlePath.CGPath, bezierPoints, MyCGPathApplierFunc);

Upvotes: 1

Related Questions