SpriteKit supports multiple device orientations

I have a SpriteKit game in which I want to support all orientations. Right now, when I change orientation, node is not retaining its position. I use SKSceneScaleModeResizeFillto scale because it will keep the correct size of the sprite.

When I launch the game, the game player is positioned in the middle of the screen as follows:

enter image description here

Then, when I rotate the device, the position will look like this:

enter image description here

Here is my view controller code:

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    // Configure the view.
    SKView * skView = (SKView *)self.view;
    if (!skView.scene) {

        // Create and configure the scene.
        SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];
        scene.scaleMode = SKSceneScaleModeResizeFill;

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

And my scene code:

-(id)initWithSize:(CGSize)size {    
    if (self = [super initWithSize:size]) {

        self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];

        //Add spaceship in the center of the view
        SKSpriteNode *spaceship = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship.png"];
        spaceship.position = CGPointMake(size.width/2, size.height/2);
        [spaceship setScale:.3];
        [self addChild:spaceship];

    }
    return self;
}
+3
source share
3 answers

- , . , .

Sprite Kit , , . " " , , - , .

didChangeSize: SKScene .

, , , - :

- (void)didChangeSize:(CGSize)oldSize {
    for (SKNode *node in self.children) {
        CGPoint newPosition;
        newPosition.x = node.position.x / oldSize.width * self.frame.size.width;
        newPosition.y = node.position.y / oldSize.height * self.frame.size.height;
        node.position = newPosition;
    }
}

, , , , . , HUD , , .

+8

. -, viewWillTransitionToSize:withTransitionCoordinator:, @GOR .

( SKView SKScene)

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    //skView is my SKView object, with scaleMode SKSceneScaleModeResizeFill
    skView.frame = CGRectMake(0, 0, size.width, size.height);

    //currentScene is my SKScene object
    currentScene.size = skView.frame.size;

    //Then, as all the objects in my scene are children of a unique SKNode* background, I only relocate it 
    currentScene.background.position = CGPointMake(CGRectGetMidX(currentScene.frame), CGRectGetMidY(currentScene.frame));
}

!

+1

For Swift 3,

override func didChangeSize(_ oldSize: CGSize) {
    for node in self.children{
        let newPosition = CGPoint(x:node.position.x / oldSize.width * self.frame.size.width,y:node.position.y / oldSize.height * self.frame.size.height)
        node.position = newPosition
    }
}

Thus, we can use a constant and initialize it in one line. Then in node.position = newPositionwe can establish a new position.
We can also use the extended for loop, which leads to a much more elegant solution.

+1
source

All Articles