Reputation: 313
SpriteKit SKAction animateWithTextures doesn't render properly first time round using Texture Atlasing.
I have a scene that initialises a sprite and runs an action on it that worked fine when I wasn't using texture atlasing. The problem is now that when the scene loads the first time it draws the sprites frame size the same as it's texture size so the sprite is drawn stretched. I have a back button so when I exit and re-enter the scene it loads up normally. It doesn't affect any of the other sprite textures from Texture Atlases, only the animated textures and it's strange that it only happens when it is first rendered.
Note: I am using a singleton which has an array storing all the animations which is generated in the ViewController.m file.
** ADDED **
Okay I've done a lot of experimenting and I've come to the conclusion that there must be something wrong with the way the automatic atlas generator is interpreting my file names, I think it's something to do with the "@2x" tags in particular.
I've tried renaming the atlas folders by removing the ".atlas" part of the name and the images are rendering perfectly, of course this is not the ideal solution as it means many more draw calls.
The way I have been naming my images is as follows...
THEME-NAME-NUMBER-RESOLUTION-DEVICE-PNG
So for example, an image would be called "SPOOKY_tree_0@2x~iphone.png"
I then load it into the cache singleton using a helper method as so...
- (SKAction *)animationWithFile:(NSString *)name theme:(NSString *)theme frameCount: (int)frameCount delay:(float)delay {
// Load the animation frames as textures and create the sprite frames
NSMutableArray *frames = [NSMutableArray arrayWithCapacity:frameCount];
for (int i = 0; i < frameCount; i++) {
NSString *retina;
if ([GLOBAL _hd]) {
retina = @"@2x";
} else { retina = @""; }
NSString *deviceType;
if ([GLOBAL _ipad]) {
deviceType = @"~ipad";
} else { deviceType = @"~iphone"; }
// Create the file name
NSString *file = [NSString stringWithFormat:@"%@%@_%d%@%@", theme, name, i, retina, deviceType];
// Create the texture/frame
SKTexture *frame = [SKTexture textureWithImageNamed:file];
[frames addObject:frame];
}
// Return the animation object from all the sprite animation frames
return [SKAction animateWithTextures:frames timePerFrame:delay];
}
// Return the animation object from all the sprite animation frames
return [SKAction animateWithTextures:frames timePerFrame:delay];
and then stores it in an NSMutableDictionary under a key using the "name" variable like so...
- (void)loadPegAnimations {
NSString *newName;
SKAction *newAnimation;
int newFrameCount;
CGFloat fps = 1.0/20.0;
newName = kP1_DEPLOYING_PEG;
newFrameCount = 9;
newAnimation = [self animationWithFile:newName theme:pegTheme frameCount:newFrameCount delay:fps];
[self addAnimation:newAnimation byName:newName];
newName = kP1_LOSING_PEG;
newFrameCount = 22;
newAnimation = [self animationWithFile:newName theme:pegTheme frameCount:newFrameCount delay:fps];
[self addAnimation:newAnimation byName:newName];
newName = kP2_DEPLOYING_PEG;
newFrameCount = 9;
newAnimation = [self animationWithFile:newName theme:pegTheme frameCount:newFrameCount delay:fps];
[self addAnimation:newAnimation byName:newName];
newName = kP2_LOSING_PEG;
newFrameCount = 22;
newAnimation = [self animationWithFile:newName theme:pegTheme frameCount:newFrameCount delay:fps];
[self addAnimation:newAnimation byName:newName];
}
When I want to use that animation i use a call to the singleton cache using the line "[[PEGOGraphicLoader sharedGraphicLoader] frameByName:kP1_DEPLOYING_PEG]];" which returns an SKAction *.
I think somehow, when it's calling back the images for the animations it's then re-applying the @2x to the images and trying to squash them into the sprite frame but I'm not sure. Also this still doesn't explain the fact that the animations are rendering normally after the first time.
I already tried leaving the resolution element and the device element out of the -textureWithImageNamed: method but the images aren't getting found by the texture atlas at all that way and are just showing up as huge X's. I think I'm gonna work without the texture atlas enabled until I know it's definitely not a bug with the texture atlas generator.
In the meantime I am considering using a hack type naming convention so I can programmatically decide which textures to load depending on the device type etc and just have different atlas folders for each device type.
If anyone has been having similar issues or would like to enlighten me as to what I'm doing wrong then I'd like to know. I have yet to test the game on an actual device so it may be an issue with the simulator.
Upvotes: 1
Views: 3698
Reputation: 193
I found myself having the same problem with my sprites using a TextureAtlas. I played with different settings for a bit and found that setting the Resize: YES and Restore: YES Boolean options corrected my incorrectly-sized sprite animations. Hope this helps
Upvotes: 2
Reputation: 51
I thought SpriteKit handled Retina automatically. Try removing the line of code where you change the string @2x, also try removing the device type and see if that isn't also handled for you.
I have also noted that if you use animateWithTextures it helps if you set resize:NO and restore:NO
Upvotes: 1