When to use didMoveToView or initWithSize with SpriteKit in xCode 6.4

后端 未结 3 1921
失恋的感觉
失恋的感觉 2021-01-03 03:39

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

-(void) didMoveToView:(SKVi         


        
相关标签:
3条回答
  • 2021-01-03 03:59

    Both options are correct. Said that, the init method is not actually the same than the didMoveToView: method, as this last one will be called once the SKScene is presented in a SKView.

    0 讨论(0)
  • 2021-01-03 04:01

    I think that, for all intents and purposes, there isn't much of a difference between the two methods when it comes to actually setting up your scene and using it. (initWithSize is called when the scene is initialized, while didMoveToView is always called right when the scene is presented by the view). I guess if you really prefer to see the initialization then you could just use the init method without any trouble at all.

    Regarding the .sks file:

    take a look at your view controller implementation file. Right above the v.controller's methods you'll see:

    @implementation SKScene (Unarchive)
    
    + (instancetype)unarchiveFromFile:(NSString *)file {
        /* Retrieve scene file path from the application bundle */
        NSString *nodePath = [[NSBundle mainBundle] pathForResource:fileofType:@"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
    

    This is the part that handles the sks. Using the file is totally optional, you aren't forced to do it and it really has no impact on you setting up your scene. However, if you do want to work with it, then you'll find that you'll need to work with this code snippet.

    0 讨论(0)
  • 2021-01-03 04:03

    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)
            }
    
    
        }
    }
    
    0 讨论(0)
提交回复
热议问题