1
votes

I am trying to move a SKSpriteNode in a circular path, pause that animation, and then reverse it from where it left off.

Here is what I have so far.

    CGPathRef circle = CGPathCreateWithEllipseInRect(CGRectMake(self.frame.size.width/2-75,self.frame.size.height/2-75,150,150), NULL);
    self.circlePathActionClockwise = [SKAction followPath:circle asOffset:NO orientToPath:YES duration:5.0];
    self.circlePathActionClockwise = [SKAction repeatActionForever:self.circlePathActionClockwise];

    [self.ball runAction:self.circlePathActionClockwise];
    self.ball.speed = 1.0;

This animated the ball in a circle. Then when I want to pause and reverse, I try:

    [self.ball runAction:[self.circlePathActionClockwise reversedAction]];
    self.ball.speed = 1.0;

This reverses the animation, but it does not start it from where it left off. Instead it treats it was a new animation and starts from the beginning.

Is there a way I can start an action from self.ball's current position?

Thanks a lot!

1
duplicate of - stackoverflow.com/questions/24234801/… - it doesn't have an answer upvoted, but the first comment is likely your best shot. Or... You could roll your own code for a circular path and just reverse direction/pause when needed. If you know how to plot a circle using cos/sin, that would get you there.prototypical

1 Answers

2
votes

The steps to reverse the direction of a sprite that is following a circular path are

  1. Compute the angle of the sprite at the stopping point (see point a and angle theta in the Figure 1)
  2. Create a new circular path that starts at angle theta
  3. Run an action in the opposite direction

enter image description here

Figure 1. A sprite following a counter-clockwise circular path

Here's an example of how to do that:

Step 1: compute the starting angle of the new path based on the current position of the sprite.

- (CGFloat) angleOnCircleWithPosition:(CGPoint)position andCenter:(CGPoint)center
{
    CGFloat dx = position.x - center.x;
    CGFloat dy = position.y - center.y;

    return atan2f(dy, dx);
}

Step 2: create a circular path given a center point and radius. Create the path starting from the specified angle (in radians).

- (CGPathRef) circlePathRefWithCenter:(CGPoint)center radius:(CGFloat)radius andStartingAngle:(CGFloat)startAngle
{
    CGMutablePathRef circlePath = CGPathCreateMutable();
    CGPathAddRelativeArc(circlePath, NULL, center.x, center.y, radius, startAngle, M_PI*2);
    CGPathCloseSubpath(circlePath);
    return circlePath;
}

You will need to declare the following instance variables:

BOOL clockwise;
SKSpriteNode *sprite;
CGFloat circleRadius;
CGPoint circleCenter;

Step 3: Reverse the direction of the sprite when the user taps the screen. It assumes that you've created a sprite and added it to the scene and set the radius and center of the circle path.

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [sprite removeActionForKey:@"circle"];
    CGFloat angle = [self angleOnCircleWithPosition:sprite.position andCenter:circleCenter];
    CGPathRef path = [self circlePathRefWithCenter:circleCenter radius:circleRadius andStartingAngle:angle];
    SKAction *followPath = [SKAction followPath:path asOffset:NO orientToPath:YES duration:4];
    if (clockwise) {
        [sprite runAction:[SKAction repeatActionForever:followPath] withKey:@"circle"];
    }
    else {
        [sprite runAction:[[SKAction repeatActionForever:followPath] reversedAction] withKey:@"circle"];
    }
    // Toggle the direction
    clockwise = !clockwise;
}