I have a sprite that moves from point A to B. Moving could cause the sprite to go around an object, which means the sprite will go from facing west to north to east.
I store the current facing direction in _facing
. I use the A* pathfinding algorithm to build an NSArray
of CGPoints
. Then I walk the sprite through the points, while changing the texture from a static (standing still) texture to an animated texture. Ultimately this will be more complex, as the sprite "turns" from direction-to-direction, but while I'm learning Objective-C / SpriteKit I'm trying to keep it simple.
Anyways, the problem is that I need to change the animation from walking west/north/east as those points are hit, but when I queue up SKAction
objects they of course run in sequence, which means when the "west" animation is playing the sprite isn't moving at all. How can I have some SKAction
's run in parallel with another sequence of SKAction
's? Are using blocks a potential solution?
Here's the code where I check if a "turn" is happening at the given point and respond accordingly:
// Set direction facing.
if (curCGPoint.x > prevCGPoint.x && [_facing isEqualToString:@"left"]) {
[self setDirectionFacing:@"right"];
// Add action to change direction.
SKAction *changeDir = [SKAction repeatActionForever:[SKAction animateWithTextures:walkRightFrames timePerFrame:0.1f resize:NO restore:YES]];
[walkActions addObject:changeDir];
} else if (curCGPoint.x < prevCGPoint.x && [_facing isEqualToString:@"right"]) {
[self setDirectionFacing:@"left"];
// Add action to change direction.
SKAction *changeDir = [SKAction repeatActionForever:[SKAction animateWithTextures:walkLeftFrames timePerFrame:0.1f resize:NO restore:YES]];
[walkActions addObject:changeDir];
}
// Build SKAction to walk hero to the current point.
SKAction *walkAction = [SKAction moveTo:curCGPoint duration:0.1];
// Add to our array of walk SKAction's.
[walkActions addObject:walkAction];
The previous code is in a for()
where I run through all points – subsequently I do something like this to actually run the actions:
SKAction *sequence = [SKAction sequence:walkActions];
[_sprite runAction:sequence withKey:@"Move_Hero"];
Update: For those that run into this trying to do the same thing, you can use a combination of SKAction sequences, SKAction groups, and blocks (via SKAction:runBlock
) to get your parallel and successive actions going. Using SKAction:runBlock
you can fire off actions from specific "group" entries that should only run at that particular moment but should not block successive actions. This is a very flexible route to take.