TardisX
TardisX

Reputation: 697

How to move a sprite along a CGPath with variable velocity

I am programming a game and want to move a sprite along a fixed path (straights and curves - think railroad engine) but I want to be able to drive the animation in terms of the sprites velocity - and change that velocity in response to game events.

followPath:duration: in SKAction is close, but there seems no way to adjust the speed "on the fly" - I definitely care about sprite speed - not 'duration to follow path'.

CGPath seems like the right construct for defining the path for the sprite, but there doesn't seem to be enough functionality there to grab points along the path and do my own math.

Can anyone suggest a suitable approach?

Upvotes: 4

Views: 687

Answers (2)

0x141E
0x141E

Reputation: 12753

You can adjust the execution speed of any SKAction with its speed property. For example, if you set action.speed = 2, the action will run twice as fast.

SKAction *moveAlongPath = [SKAction followPath:path asOffset:NO orientToPath:YES duration:60];
[_character runAction:moveAlongPath withKey:@"moveAlongPath"];

You can then adjust the character's speed by

[self changeActionSpeedTo:2 onNode:_character];

Method to change the speed of an SKAction...

- (void) changeActionSpeedTo:(CGFloat)speed onNode:(SKSpriteNode *)node
{
    SKAction *action = [node actionForKey:@"moveAlongPath"];
    if (action) {
      action.speed = speed;
    }
}

Upvotes: 5

Revinder
Revinder

Reputation: 291

Try some think like this :

CGMutablePathRef cgpath = CGPathCreateMutable();

//random values
float xStart = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ];
float xEnd = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ];

//ControlPoint1
float cp1X = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ];
float cp1Y = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.height ];

//ControlPoint2
float cp2X = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ];
float cp2Y = [self getRandomNumberBetween:0 to:cp1Y];

CGPoint s = CGPointMake(xStart, 1024.0);
CGPoint e = CGPointMake(xEnd, -100.0);
CGPoint cp1 = CGPointMake(cp1X, cp1Y);
CGPoint cp2 = CGPointMake(cp2X, cp2Y);
CGPathMoveToPoint(cgpath,NULL, s.x, s.y);
CGPathAddCurveToPoint(cgpath, NULL, cp1.x, cp1.y, cp2.x, cp2.y, e.x, e.y);

SKAction *planeDestroy = [SKAction followPath:cgpath asOffset:NO orientToPath:YES duration:5];
[self addChild:enemy];

SKAction *remove2 = [SKAction removeFromParent];
[enemy runAction:[SKAction sequence:@[planeDestroy,remove2]]];

CGPathRelease(cgpath);

Upvotes: 1

Related Questions