SPRITEKIT遊戲開發適配IPAD/IPHONE6/7/8/PLUS及IPHONEX的尺寸及安全區域

未適配前:Ball球超過屏幕的上下方
未適配前:Ball球超過屏幕的上下方安全

適配後:Ball球就在屏幕的可視範圍內運動了
適配後:Ball球就在屏幕的可視範圍內運動了ide

1、那麼如何適配不一樣的iPhone、iPhoneX及iPad的屏幕尺寸呢?

咱們開發一個App的時候, 一般但願它在 iPhone, iPad, Mac上同時能運行, 尤爲是遊戲。oop

這樣就須要咱們考慮不一樣設備不一樣的分辨率,但處理起來比較麻煩,好比說,按照官方的作法,咱們須要提供諸如 ifiero@1x,ifiero@2x,ifiero@3x, 這樣不一樣尺寸的圖片,那如何簡便的適配設備不一樣的分辨率呢,咱們的作法是, 固定一個大小, 向下兼容不一樣的設備。spa

即場景中的全部圖片, 都按照屏幕大小爲 2048 1536 來繪製。 也就是說, 咱們的背景圖的大小是 2048 1536, 其餘圖片也是依照這個比例來繪製。設計

爲何這樣作呢?code

咱們知道 2048 1536 是iPad Retina 的分辨率。也是咱們須要適配的設備裏面分辨率最高的。 因此咱們在遊戲中都選擇了這個大小,讓它來兼容分辨率低的設備。 2048 1536 在iPad Retina上是完美顯示的。 那在其餘設備上呢? 這裏就要依靠 AspectFill來進行縮放了,代碼以下:blog

if let scene = GameScene(fileNamed: "GameScene") {
                scene.size = CGSize(width: 2048, height: 1536)
                scene.scaleMode = .aspectFill /// 縮放
                view.presentScene(scene)
 }

不一樣尺寸的iPhone的屏幕尺寸比例
不一樣尺寸的iPhone的屏幕尺寸比例教程

橙色總體區域表示咱們場景的真實大小, 黑色線框內的區域表示場景展現在設備上的真實大小。
iPad Retina:橙色區域和黑色線框內的區域是完美吻合的,也就是說在設備上能完整顯示。
iPhone6/7/8/Plus:黑色線框內的區域是2048 * 1152,這邊要注意的是,超出黑色框的內容看不見,設計遊戲時,儘可能不要把精靈的Position位置放在位於不可見的區域。遊戲

不一樣尺寸的iPhone的屏幕尺寸比例
| 設備 | 屏幕比例 | 屏幕比值 |
| - | :-: | -: |
| iPad Retina | 4 / 3 | 1.33 |
| iPhone 6/7/8 | 16 / 9 | 1.77 |
| iPhone 6/7/8 Plus | 16 / 9 | 1.77 |
| iPhone X | -- | 2.16 |
iPhoneX的Safe Area爲觸發交互行爲的區域
iPhoneX的Safe Area爲觸發交互行爲的區域圖片

瞭解了原理後,咱們就開始來編寫代碼吧

1.extension拓展UIDevice,判斷設備是iPhone或者iPhoneX或iPad

import UIKit
import SpriteKit

// iPhone X  375*812(H) @1x
// 豎屏
public let AREA_INSET_HEIGHT_TOP   :CGFloat = (UIScreen.main.bounds.height == 812) ? 44.0 : 0
public let AREA_INSET_HEIGHT_BOTTOM:CGFloat = (UIScreen.main.bounds.height == 812) ? 34.0 : 0
// 橫屏(安全區域)
public let AREA_INSET_WIDTH_TOP    :CGFloat = (UIScreen.main.bounds.width == 812) ? 44.0 : 0
public let AREA_INSET_WIDTH_BOTTOM :CGFloat = (UIScreen.main.bounds.width == 812) ? 34.0 : 0

public let iPhoneX_REAL_HEIGHT:CGFloat = 812.0   /// 豎屏

extension UIDevice {
    
    /// 是否是iPhoneX ,若是是豎屏則 UIScreen.main.bounds.height == 812
    public func isPhoneX() -> Bool {
        if UIScreen.main.bounds.width == 812 {  /// 橫屏
            return true
        }
        return false
    }
    /// 是否是iPad
    public func isPad() -> Bool {
        
        if UIScreen.main.bounds.height > 812 {
            return true
        }
        return false
    }
}

2.GameScene定義可視範圍的起點及高度 (由於是橫屏,因此定義高度)

private var playableRect:CGRect!   /// 可視範圍
    private var playableHeight:CGFloat  = 0.0   /// 可視範圍的高度
    private var playableMargin:CGFloat = 0.0   /// 可視範圍的起點
    
    override func didMove(to view: SKView) {
        self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
        self.physicsWorld.contactDelegate = self
        
        initCheckDevice()
        setupBall()
        
    }

3.檢測是哪一種設備

// MARK: - 檢測是哪一種設備
    func initCheckDevice(){
        if UIDevice.current.isPhoneX() {
            maxAspectRatio = 2.16         /// iPhoneX 2.16 ratio
        }else {
            maxAspectRatio  = UIDevice.current.isPad() ? (4.0 / 3.0) : (16.0 / 9.0)  /// iPhone 16:9,iPad 4:3
        }
        /// 畫出可視區域
        drawPayableArea(size: self.size,ratio: maxAspectRatio)
    }

4.畫出可視區域並賦於可視區域的邊屆物理特性

// MARK: - 畫出可視區域
    func drawPayableArea(size:CGSize,ratio:CGFloat){
        /*
         /// 安全區域即用戶交互的區域,非可視區域 (iPhoneX的安全區域 < 可視區域)
         let safeInsetTop    =  self.size.height * AREA_INSET_TOP    / iPhoneX_REAL_HEIGHT
         let safeInsetBottom =  self.size.height * AREA_INSET_BOTTOM / iPhoneX_REAL_HEIGHT
         let safeHeight = self.size.height - safeInsetTop - safeInsetBottom
         */
        
        playableHeight  = size.width / ratio
        playableMargin = (size.height - playableHeight ) / 2.0   /// P70
        playableRect = CGRect(x: 0, y: playableMargin, width: size.width, height:  playableHeight)  /// 注意 scene的anchorPoint(0,0)原點的位置;
        
        let shapeFrame = SKShapeNode(rect: playableRect)
        shapeFrame.zPosition = 1
        shapeFrame.strokeColor = SKColor.red
        shapeFrame.lineWidth = 5.0
        addChild(shapeFrame)
        
        /// 可視區域的物理狀態
        let playableBody = SKPhysicsBody(edgeLoopFrom: playableRect)
        playableBody.friction = 0
        self.physicsBody = playableBody
        playableBody.categoryBitMask    = PhysicsCategory.Frame
        playableBody.contactTestBitMask = PhysicsCategory.Ball
        playableBody.collisionBitMask   = PhysicsCategory.Ball
        
    }

這樣子Ball球就只在可視區域內運動了

2、iPhoneX的尺寸及安全區域

iPhoneX的屏幕尺寸 375(W)x812(H)

iPhoneX的Safe Area爲觸發交互行爲的區域

交互行爲(按鈕)須在安全區域內

安全區域

頂部狀態欄 44points

底部間隔 34points

iPhoneX的屏幕尺寸及安全區域

iPhoneX的屏幕尺寸及安全區域:
| 設備 | 屏幕尺寸 | 圖片存放的位置 | 安全區域 |
| - | :-: | -: | -: |
| iPhoneX | 375x812 | @1x | 375x(812 - 34 - 44),交互的起點Position(x:0,y:34) |
| iPhoneX | 750x1624 | @2x | 交互的起點Position(x:0,y:2 x 34) |
| iPhoneX | 1125x2436 | @3x | 交互的起點Position(x:0,y:3 x 34) |
| iPhoneX | 1536x2048 | @1x | y:2048 x 44 / 812 (已知812對應44,求2048對應y的值)|

圖片存放的位置

安全區域

// iPhone X  375*812(H) @1x
// 豎屏
public let AREA_INSET_HEIGHT_TOP   :CGFloat = (UIScreen.main.bounds.height == 812) ? 44.0 : 0
public let AREA_INSET_HEIGHT_BOTTOM:CGFloat = (UIScreen.main.bounds.height == 812) ? 34.0 : 0
// 橫屏(安全區域)
public let AREA_INSET_WIDTH_TOP    :CGFloat = (UIScreen.main.bounds.width == 812) ? 44.0 : 0
public let AREA_INSET_WIDTH_BOTTOM :CGFloat = (UIScreen.main.bounds.width == 812) ? 34.0 : 0

public let iPhoneX_REAL_HEIGHT:CGFloat = 812.0   /// 豎屏


 /// 安全區域即用戶交互的區域,非可視區域 (iPhoneX的安全區域 < 可視區域)
let safeInsetTop    =  self.size.height * AREA_INSET_WIDTH_TOP  / iPhoneX_REAL_HEIGHT
let safeInsetBottom =  self.size.height * AREA_INSET_WIDTH_BOTTOM    / iPhoneX_REAL_HEIGHT
let safeHeight = self.size.height - safeInsetTop - safeInsetBottom   // 安全區域的高度

可視區域

playableHeight  = size.width / ratio  /// ratio爲2.16
 playableMargin = (size.height - playableHeight ) / 2.0 
 playableRect = CGRect(x: 0, y: playableMargin, width: size.width, height:  playableHeight)  /// 注意 scene的anchorPoint(0,0)原點的位置;

重要的一點就是要了解屏幕尺寸和安全區域的不一樣,通俗點講就是,屏幕尺寸能夠聽任何元素,但不可放交互行爲,全部的用戶交互行爲都要放在安全區域內。

源碼傳送門:http://www.iFIERO.com/uploads...
更多遊戲教程: http://www.iFIERO.com

相關文章
相關標籤/搜索