2

I am trying to adjust SKScene position based on the device the game is running. For example due to 'top notch' area of iPhone XS Max, I need to subtract that height from SKScene height and position the scene accordingly.

So here is how I calculate the height aka safeAreaHeight in the AppDelegate and subtract from scene height aka sceneHeight:

    safeAreaHeight = UIApplication.shared.statusBarFrame.size.height
    sceneHeight -= safeAreaHeight

In GameViewController I try to re-position the SKScene like below:

    if let view = self.view as! SKView? {
        // Load the SKScene from 'MainMenuScene.sks'
        if let scene = SKScene(fileNamed: "MainMenuScene") {
            // Set the scale mode to scale to fit the window
            scene.scaleMode = .aspectFit
            scene.size.height = sceneHeight
            scene.size.width = sceneWidth
            scene.position.y -= safeAreaHeight
            // Present the scene
            view.presentScene(scene)
        }

        view.ignoresSiblingOrder = true
        view.showsFPS = true
        view.showsNodeCount = true
    }

However, I am getting below error:

SKScene: Setting the position of a SKScene has no effect.

Additionally, I tried to use SKAction to move position of the SKScene as well, then I received below error:

SKScene: Animating the position of a SKScene has no effect.

Thank you for the help.

Vetuka
  • 1,523
  • 1
  • 24
  • 40
  • 1
    I size the scene to the view controller's view and position nodes to avoid notches (or potentially other non-safe areas) as necessary. Is there a reason this wouldn't work for your situation? If you adjust the scene for the safe area, what are you expecting to display next to the notch? I kinda like that the sky, or other background, fills that space. – JKaz Feb 05 '19 at 23:24
  • @JKaz I didn't try to size to view controller's view. Is the view controller's view equals to 'safe area'? I just want that area to be plain black color. I am not going to utilize that area. – Vetuka Feb 05 '19 at 23:35
  • 1
    The vc's view is the screen, not just the safe area. The safe area insets are a property of the view. Where I've seen or worked with skScene, the scene fills the screen and individual controls/nodes/etc are positioned within the safe area, avoiding a non-safe area that looks different from the safe area. I think it's recommended to not separately color the non-safe areas, though in a quick look, I didn't find a source. – JKaz Feb 06 '19 at 17:56

1 Answers1

2

Well I figured how to achieve this, I am sharing in case it would help someone else.

Inside AppDelegate you get the correct safe area values and store it in a singleton (in my case: safeAreaHeight) for access throughout the app. Subtract the amount from scene height (sceneHeight).

    let kWindow = UIApplication.shared.windows[0]
    safeAreaHeight = kWindow.safeAreaInsets.top + kWindow.safeAreaInsets.bottom
    screenHeight = screenRect.size.height - safeAreaHeight

Don't forget the adjust the sceneHeight in GameViewController before presenting it:

    if let view = self.view as! SKView? {
        // Load the SKScene from 'MainMenuScene.sks'
        if let scene = SKScene(fileNamed: "MainMenuScene") {
            // Set the scale mode to scale to fit the window
            scene.scaleMode = .aspectFit
            scene.size.height = sceneHeight
            scene.size.width = sceneWidth
            // Present the scene
            view.presentScene(scene)
        }

        view.ignoresSiblingOrder = true
        view.showsFPS = true
        view.showsNodeCount = true
    }

Inside loaded scene, in this case it is MainMenuScene, you simply find subview of SKScene and adjust its Y position by subtracting the safeAreaHeight at its center

    guard let subView = self.view else { return }
    subView.center.y -= safeAreaHeight

PS.: Do not adjust all the views in different scenes (ie.: GameScene, GameOverScene etc.) Once you adjust, it remains throughout the app.

Vetuka
  • 1,523
  • 1
  • 24
  • 40