1

Since Sprite Kit / iOS7 only supports iPhone 4 and newer, I don't need non-retina textures on iPhone. So if I have an universal app and want to keep the overall bundle size small, I could use the same textures for retina iPhone and non-retina iPad. (Like in this question)

To do so, I don't use the standard naming conventions like "@2x", "~ipad", etc. Instead, I load all of my textures depending on the device type. Is that a good idea?

Simplified example:

SKTexture *myTexture;

if (isIPad && retinaDisplay){        
    myTexture = [SKTexture textureWithImageNamed:@"myTexture_iPad_HD"];
} else {
    // non-retina iPad and retina iPhone
    myTexture = [SKTexture textureWithImageNamed:@"myTexture_iPad_SD"];        
}

SKSpriteNode *mySprite = [SKSpriteNode spriteNodeWithTexture:myTexture size:CGSizeMake(...,...)]

(The CGSize of the SKSpriteNode depends on the device. The "playable area" on iPad is 960x640. On iPhone it's 480x320. So on iPhone the CGSize is half, of course.)

Thanks in advance for your help!

Community
  • 1
  • 1
  • the more important question is: does it work? If so, there's no question here that needs answering. – CodeSmile Feb 08 '14 at 08:43
  • It seemed to worked but I wasn't sure whether this solution could cause problems later on. So I thought that someone solved this problem in a different (better) way. But now I found a solution that works just by using standard naming conventions. –  Feb 08 '14 at 10:50

2 Answers2

2

It turns out I can solve this problem with the standard naming conventions. As long as I use …

myTexture = [SKTexture textureWithImageNamed:@"myTexture"];
[SKSpriteNode spriteNodeWithTexture:myTexture size:CGSizeMake(...,...)];

… and name my texture like this: "myTexture.png" and "myTexture@2x~ipad.png".

On iPad everything works as expected. On iPhone, I don't want to load the @2x texture, hence the device-modifier "~ipad". Now there is no @2x texture on iPhone, so the "myTexture.png" is loaded instead. Since I defined the size: parameter of my SKSpriteNode and the CGSize is half the size as on iPad, the texture is scaled down and now "retina".

0

For myself, I have solved this problem as follows:

Create Objective-C Category SKScene + iPad

#import "SKScene+iPad.h"
#import <objc/runtime.h>

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];

        SEL originalSelector = @selector(initWithSize:);
        SEL swizzledSelector = @selector(lns_initWithSize:);

        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

        BOOL didAddMethod =
        class_addMethod(class,
                        originalSelector,
                        method_getImplementation(swizzledMethod),
                        method_getTypeEncoding(swizzledMethod));

        if (didAddMethod) {
            class_replaceMethod(class,
                                swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

- (instancetype)lns_initWithSize:(CGSize)size {
    [self lns_initWithSize:size];
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
        self.size = (CGSize) {
            self.size.width / 2.f,
            self.size.height / 2.f
        };

    }
    return self;
}
NSLeader
  • 345
  • 2
  • 10