Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use didMoveToView or initWithSize with SpriteKit in xCode 6.4

Since xCode was updated to version 6.0, the default method for SpriteKit in "GameScene" (the default scene created) changes to:

-(void) didMoveToView:(SKView *) view {
/* Scene set up in here */
}

as opposed to the older method:

-(id) initWithSize:(CGSize) size {
    if (self = [super initWithSize:size]{
    /* Scene set up in here */
    }
}

I understand that the new method (as with the changes in the view controller) is used to help manage the import from the .sks file that is new in xCode 6. However, I was curious if I didn't want to use the new "storyboard"-type format that is the .sks file, should I still use the new method? Or should I change the method back to the initWithSize method and just delete the .sks file?

like image 456
Su_toL Avatar asked Jul 31 '15 12:07

Su_toL


1 Answers

Init methods should be used for initializing but keep in mind that inside init, view is always nil. So any code that needs the view has to be moved to didMoveToView method (it's called immediately after a scene is presented by a view).

About initWithSize in Xcode 6... By default, scene is loaded from .sks file. Because of this, initWithSize is never called actually. initWithCoder is called instead:

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{

    if (self = [super initWithCoder:aDecoder]) {
        // do stuff 
    }
    return self;
}

So initializing anything inside initWithSize won't have any effect. If you decide to delete .sks file and create a scene in "old" way, you can do something like this in view controller:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Configure the view.
    SKView * skView = (SKView *)self.view;
    skView.showsFPS = YES;
    skView.showsNodeCount = YES;
    /* Sprite Kit applies additional optimizations to improve rendering performance */
    skView.ignoresSiblingOrder = YES;

    // Create and configure the scene.
    GameScene *scene = [GameScene sceneWithSize:self.view.bounds.size];
    scene.scaleMode = SKSceneScaleModeAspectFill;


    // Present the scene.
    [skView presentScene:scene];
}

After that, you can use initWithSize for initialization.

Note that in viewDidLoad the final size of a view may not be known yet, and using viewWillLayoutSubviews instead could be a right choice. Read more here.

And proper implementation of viewWillLayoutSubviews for scene initialization purpose would be:

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];

    // Configure the view.
    SKView * skView = (SKView *)self.view;
    skView.showsFPS = YES;
    skView.showsNodeCount = YES;
    /* Sprite Kit applies additional optimizations to improve rendering performance */
    skView.ignoresSiblingOrder = YES;

    //viewWillLayoutSubviews can be called multiple times (read about this in docs ) so we have to check if the scene is already created
    if(!skView.scene){
        // Create and configure the scene.
        GameScene *scene = [GameScene sceneWithSize:self.view.bounds.size];
        scene.scaleMode = SKSceneScaleModeAspectFill;

        // Present the scene.
        [skView presentScene:scene];
    }
}

Swift code:

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
        // Configure the view.
        let skView = self.view as SKView
        skView.showsFPS = true
        skView.showsNodeCount = true
        skView.showsPhysics = true
        skView.showsDrawCount = true

        /* Sprite Kit applies additional optimizations to improve rendering performance */
        skView.ignoresSiblingOrder = true

        /* Set the scale mode to scale to fit the window */

        if(skView.scene == nil){

            scene.scaleMode = .AspectFill
            scene.size  = skView.bounds.size
            skView.presentScene(scene)
        }


    }
}
like image 103
Whirlwind Avatar answered Oct 04 '22 15:10

Whirlwind