SpriteKit SceneをiPhone/iPadのホームバーに対応させる
3年間放置していたiOSアプリをホームバーに対応させた話
かれこれ3年くらい放置していた iPhone/iPad 両対応のアプリをホームバーに対応させようと思ったら結構大変だったのでその記録です。 ちなみに放置していたアプリはこちらです。
apps.apple.com対応前の設定はこんな感じ
4.7インチの iPhone(6, 6S, 7, 8, 第2世代SEなど1334 * 750ピクセル)をベースにiPadにも対応させるため、SKScene の幅を1334ピクセル高さを1000.5ピクセル(4:3)に設定し、アンカーポイントを(0, 0)に設定してました。 4:3の iPad を表示領域として、スプライトを16:9の iPhone の領域におさまるように配置するイメージです。この設定だと iPhone だとぴったりで iPad だと上下に余白ができます。 シーンのスケールモードの設定は aspectFill に設定してました。
class GameViewController: UIViewController { override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() if let view = self.view as! SKView? { // Load the SKScene from 'GameScene.sks' if let scene = GameScene(fileNamed: "GameScene") { // Set the scale mode to scale to fit the window scene.scaleMode = .aspectFill // Present the scene view.presentScene(scene) } } } }
ホームバーの無い iPhone 8 や iPad Pro 第2世代では問題なく表示できていました。しかし iPhone X 以降(またはiPad Pro 11, 12.9インチ)のホームバー付きの端末で表示させる以下のようになりました。 全体が拡大されてスプライトがはみ出ています。
ホームバーに対応する手順
iPhone X 以降(またはiPad Pro 11, 12.9インチ)のホームバーに対応する手順は以下のようになります。
- SKSceneのサイズを16:9に合わせて変更する
- アンカーポイントを(0, 0)から(0.5, 0.5)に変更する
- presentSceneを呼び出すタイミングでSceneのサイズを調整する
手順1と2でシーンエディタの修正をします。手順3でプログラムの修正をします。
SKSceneのサイズを16:9に合わせて変更する
SKScene のサイズを16:9に合うように変更します。私の場合は1334 * 1000.5だった設定を1334 * 750に変更しました。16:9であれば960 * 540だったり、2208 * 1242だったりでも問題ないようです。作成したスプライトの画像サイズに合うように適宜変更すれば良いようです。ポイントは縦横比が16:9になるように SKScene のサイズを設定することです。
Sceneのアンカーポイントを中央にする
16:9 の iPhone の画面にぴったり合うようにスプライトを配置すると iPhone 11 系では左右に余白ができ、iPad 系では上下に余白ができます。この余白に影響を受けないようにするにはアンカーポイントを中央(0.5, 0.5)に設定する必要があります。シーンのアンカーポイントを変更するとスプライトの位置が変わってしまうので適宜スプライトの位置も変更します(地味にこの作業が一番めんどくさい)。
ここまでの修正を反映するとこんな感じです
presentSceneを呼び出すタイミングでSceneのサイズを調整する
UIView の presentScene メソッドを呼ぶタイミングで、UIView のサイズ(機種によってサイズがかわる)と SKScene のサイズの比率を計算して SKScene のサイズを調整してあげます。スケールモードの設定は aspectFill から aspectFit に変更します。
class GameViewController: UIViewController { override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() if let view = self.view as! SKView? { // Load the SKScene from 'GameScene.sks' if let scene = GameScene(fileNamed: "GameScene") { var factor = view.frame.size.height / scene.size.height // iPad if view.frame.size.width / factor < scene.size.width { factor = view.frame.size.width / scene.size.width } scene.size = CGSize(width: view.frame.size.width / factor, height: view.frame.size.height / factor) // Set the scale mode to scale to fit the window scene.scaleMode = .aspectFit // Present the scene view.presentScene(scene) } } } }
手順を適用した結果はこちら
手順1から3を適用して修正した結果は以下のようになります。
iPhone 8
ホームバーなし(ホームボタンあり)の従来型の iPhone 画面です。
iPhone 11
ホームバーありの新型の iPhone 画面です。左右に余白ができています。
iPad Pro 11インチ
ホームバーありの新型の iPad 画面です。上下に余白ができています。