13
votes

I have a sprite sheet with the animation images for my sprite. How would I make put these images in to a SKTextureAtlas (so I can animate in an SKAction) without splitting up the individual files? I have seen and done this before, but not using SpriteKit and/or SKTextures.

Is this even possible without splitting up the files? Worst case scenario: I would need to make the sheet separate images.

In the past I have just make a method with sprite size and number of total sprites which were separated the images in code then animated through.


Thanks in advance for any help!

P.S. I'm new to SpriteKit but not to game programming or iOS

2
Thanks for asking this question and posting your result code. This is exactly what I needed.Sungwon Jeong

2 Answers

13
votes

Thanks to @LearnCocos2D guy for pointing me toward using textureWithRect:inTexture: I made a custom init method within my custom Entity : SKSpriteNode class which will allow the use of a sprite sheet with all images on it. I tried to include some comments to explain the code. I have this version scan the x as my animation is horizontal. Y can be changed only with the method called. Not in the method with this version.

Make sure to put it in the interface!

Example when alloc-initing:

Entity *cookie = [[Entity alloc] initWithSpriteSheetNamed:@"cookie_sheet" withinNode:map sourceRect:CGRectMake(0, 0, 32, 32) andNumberOfSprites:6];

The method in the Entity : SKSpriteNode

- (id) initWithSpriteSheetNamed: (NSString *) spriteSheet withinNode: (SKSpriteNode *) scene sourceRect: (CGRect) source andNumberOfSprites: (int) numberOfSprites {

    // @param numberOfSprites - the number of sprite images to the left
    // @param scene - I add my sprite to a map node. Change it to a SKScene
    // if [self addChild:] is used.

    NSMutableArray *mAnimatingFrames = [NSMutableArray array];

    SKTexture  *ssTexture = [SKTexture textureWithImageNamed:spriteSheet];
    // Makes the sprite (ssTexture) stay pixelated:
    ssTexture.filteringMode = SKTextureFilteringNearest;

    float sx = source.origin.x;
    float sy = source.origin.y;
    float sWidth = source.size.width;
    float sHeight = source.size.height;

    // IMPORTANT: textureWithRect: uses 1 as 100% of the sprite.
    // This is why division from the original sprite is necessary.
    // Also why sx is incremented by a fraction.

    for (int i = 0; i < numberOfSprites; i++) {
        CGRect cutter = CGRectMake(sx, sy/ssTexture.size.width, sWidth/ssTexture.size.width, sHeight/ssTexture.size.height);
        SKTexture *temp = [SKTexture textureWithRect:cutter inTexture:ssTexture];
        [mAnimatingFrames addObject:temp];
        sx+=sWidth/ssTexture.size.width;
    }

    self = [Entity spriteNodeWithTexture:mAnimatingFrames[0]];

    animatingFrames = mAnimatingFrames;

    [scene addChild:self];

    return self;
}
5
votes

You need to have each animation frame as a separate image. Then you can use SKAction to animate the images, optionally using SKTextureAtlas.

So yes, you have to split your existing sheet unless you write a custom animation handler that changes the texture rect of the animated sprite manually. You can create a smaller texture from the spritesheet texture by using textureWithRect:inTexture:.