SpriteKit支持多种设备方向

时间:2014-02-25 20:54:48

标签: ios sprite-kit device-orientation

我有一个SpriteKit游戏,我想支持所有方向。现在当我改变方向时,节点不会保持其位置。我使用SKSceneScaleModeResizeFill进行缩放,因为它将保持正确的精灵大小。

当我开始游戏时,游戏玩家就像这样定位在中间屏幕:

enter image description here

然后当我旋转设备时,位置变为如下:

enter image description here

以下是我的视图控制器代码:

- (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];
    }
}

我的场景代码:

-(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 个答案:

答案 0 :(得分:10)

你的精灵在场景调整大小后保持其位置 - 你可以从截图中看到它与场景左下角保持相同的水平和垂直距离。问题是,在场景调整大小后,绝对偏移代表场景中不同的相对位置。

Sprite Kit可以自动调整场景大小,但是场景调整大小后节点的相对位置不是它可以为你做的事情。对于如何以不同的大小重新排列场景的内容没有“正确答案”,因为场景内容的排列是您的应用定义的内容。

SKScene子类中实现didChangeSize:,并在其中放置您想要的任何逻辑来移动节点。

例如,您可以使用以下节点将节点保持其位置作为场景大小的相对比例:

- (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元素,你可能希望它们与角落有一个固定的偏移,而不是场景大小的一部分。

答案 1 :(得分:1)

我添加了类似的问题并发现了这个问题。我使用viewWillTransitionToSize:withTransitionCoordinator:进行了不同的解决,正如@GOR here所述。

我在视图控制器中添加了以下代码(管理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));
}

它就像一个魅力!

答案 2 :(得分:1)

对于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
    }
}

因此,我们可以使用常量并将其初始化为一行。然后在node.position = newPosition我们可以设置新的位置 此外,我们还可以利用增强的for循环,从而实现更优雅的解决方案。