02fentym
02fentym

Reputation: 1772

SpriteKit .sks files and subclassing

Apple demoed this code in their WWDC 2014 Session 608 video on best practices for SpriteKit.

AppDelegate.m

+ (instancetype)unarchiveFromFile:(NSString *)file {
    /* Retrieve scene file path from the application bundle */
    NSString *nodePath = [[NSBundle mainBundle] pathForResource:file ofType:@"sks"];
    /* Unarchive the file to an SKScene object */
    NSData *data = [NSData dataWithContentsOfFile:nodePath
                                      options:NSDataReadingMappedIfSafe
                                        error:nil];
    NSKeyedUnarchiver *arch = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    [arch setClass:self forClassName:@"SKScene"];
    SKScene *scene = [arch decodeObjectForKey:NSKeyedArchiveRootObjectKey];
    [arch finishDecoding];

    return scene;
}

I understand the gist of what it's doing, but what I'm confused about is how to utilize this code in for any other .sks file. I tried calling the unarchiveFromFile method from my GameScene.m class, but to no avail. I read the post here on this topic, but it did not clarify things.

EDIT As per what was suggested by Okapi, I tried the following in a new OS X SceneKit project in the GameScene.m class:

#import "GameScene.h"

@implementation GameScene

-(void)didMoveToView:(SKView *)view {
    SKNode *nodeInScene2 = [self childNodeWithName:@"object1"];
    for (SKNode *blah in [SKScene unarchiveFromFile:@"Scene2"].children) {
        [nodeInScene2 addChild:blah];
    }
}

-(void)update:(CFTimeInterval)currentTime {
    /* Called before each frame is rendered */
}

@end

I have 2 .sks files. The first is called GameScene.sks and that has a sprite in there called "object1". I would like to add children stored in "Scene2.sks". The loop in the didMoveToView method gives me an error. What am I doing wrong? This is what Apple did in their WWDC 608 video, but perhaps I'm missing something since I can't find their project online.

Upvotes: 2

Views: 793

Answers (2)

Jul3ia
Jul3ia

Reputation: 1

This one hung me up for a while too. I ended up declaring unarchiveFromFile in every subclass that needed it, then calling it when I wanted to transition scenes. Something like this...

if (contactQuery == (playerCategory | proceedCategory)) {
    SKScene *levelTwo = [LevelTwo unarchiveFromFile:@"LevelTwo"];
    [self.view presentScene:levelTwo transition:[SKTransition doorsCloseHorizontalWithDuration:0.5]];
}

Full sample code can be downloaded here.

Upvotes: 0

Jonny
Jonny

Reputation: 16298

+unarchiveFromFile: is defined as a category on SKScene in GameViewController.m. You would need to copy that code if you want to use it somewhere else.

@implementation SKScene (Unarchive)

+ (instancetype)unarchiveFromFile:(NSString *)file {
    /* Retrieve scene file path from the application bundle */
    NSString *nodePath = [[NSBundle mainBundle] pathForResource:file ofType:@"sks"];
    /* Unarchive the file to an SKScene object */
    NSData *data = [NSData dataWithContentsOfFile:nodePath
                                          options:NSDataReadingMappedIfSafe
                                            error:nil];
    NSKeyedUnarchiver *arch = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    [arch setClass:self forClassName:@"SKScene"];
    SKScene *scene = [arch decodeObjectForKey:NSKeyedArchiveRootObjectKey];
    [arch finishDecoding];

    return scene;
}

@end

Upvotes: 1

Related Questions