• 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域


    此篇文章是对上一篇文章(http://www.ifiero.com/index.php/archives/611)的进一步补充,主要说明如何适配Apple的最新三款手机iPhoneXs、iPhoneXs Max及iPhoneXr !!!

    未适配前:Ball球超过屏幕的上下方

    未适配前:Ball球超过屏幕的上下方

    适配后:Ball球就在屏幕的可视范围内运动了

    适配后:Ball球就在屏幕的可视范围内运动了

    回顾:为何要把场景中的所有图片, 都按照屏幕大小为 2048 * 1536 来绘制。 也就是说, 我们的背景图的大小是 2048 * 1536, 其他图片也是依照这个比例来绘制。

    为什么这样做呢?

    我们知道 2048 * 1536 是iPad Retina 的分辨率。也是我们需要适配的设备里面分辨率最高的。 所以我们在游戏中都选择了这个大小,让它来兼容分辨率低的设备。 2048 * 1536 在iPad Retina上是完美显示的。 那在其他设备上呢? 先用 AspectFill来进行缩放,并应用相应的屏幕辨率高宽比值Ratio, 来适配各个不同的iPhone尺寸。AspectFill缩放的代码如下:

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

    了解了用 AspectFill来进行缩放,那么我们现在就来看看iPhoneX的屏幕尺寸分辨率

    以iPhoneX的分辨率为例,SafeArea为安全区域

    以iPhoneX的分辨率为例,SafeArea为安全区域

    iPhoneX的屏幕尺寸分辨率(上图中 高度812 = 2436缩小1/3):

    设备屏幕尺寸分辨率图片存放对应的位置
    iPhoneX (1倍 @1x) 375×812 @1x
    iPhoneX (2倍 @2x) 750×1624 @2x
    iPhoneX (3倍 @3x) 1125×2436 @3x

    iPhoneX/iPhoneXs/iPhoneXs Max/iPhoneXr的屏幕尺寸分辨率

    iPhoneX系列的分辨率

    iPhoneX系列的分辨率

    iPhoneX系列的屏幕分辨率:

    设备屏幕分辨率图片存放的位置
    iPhoneX (3倍 @3x) 1125×2436 @3x
    iPhoneXs (3倍 @3x) 1125×2436 @3x
    iPhoneXs Max (3倍 @3x) 1242×2688 @3x
    iPhoneXr (2倍 @2x) 828×1792 @2x

    根据以上iPhoneX系列的屏幕分辨率,得出高宽比Ratio都为2.16

    各款iPhone的屏幕分辨比率

    各款iPhone的屏幕分辨比率

    橙色整体区域表示我们场景的真实大小, 用 AspectFill来进行缩放后,scene.scaleMode = .aspectFill,黑色线框内的区域表示场景展示在设备上的真实大小(即屏幕可视范围)。

    iPad Retina:橙色区域和黑色线框内的区域是完美吻合的,也就是说在设备上能完整显示。

    iPhone6/7/8/Plus:黑色线框内的区域是2048 * 1152,这边要注意的是,超出黑色框的内容看不见,设计游戏时,尽量不要把精灵的Position位置放在位于不可见的区域。

    iPhoneX:黑色线框内的区域是2048 * 948(兰色为安全区域),其中948高度=2048 / 2.16(高宽比)。

    不同尺寸的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/Xs/Xr/Xs Max 2.16

    再者我们主要是适配SpriteKit游戏开发,因为不需要计算Navigation导航栏的高度,也不需要TabBar状态栏的高度,只需要计算可视区域(屏幕可视范围),还有,注意要把需要交互的元素放在安全区域SafeArea,而不要放在危险区域 Danger Area就行了。

    可视区域(屏幕可视范围)= 安全区域 Safe Area + 危险区域 Danger 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 || UIScreen.main.bounds.height == 896) ? 44.0 : 0
    public let AREA_INSET_HEIGHT_BOTTOM:CGFloat = (UIScreen.main.bounds.height == 812 || UIScreen.main.bounds.height == 896) ? 34.0 : 0
    // 横屏(安全区域)
    public let AREA_INSET_WIDTH_LEFT  :CGFloat = (UIScreen.main.bounds.width == 812 || UIScreen.main.bounds.width == 896) ? 44.0 : 0
    public let AREA_INSET_WIDTH_RIGHT :CGFloat = (UIScreen.main.bounds.width == 812 || UIScreen.main.bounds.width == 896) ? 34.0 : 0
    
    extension UIDevice {
        /// 是不是iPhoneX ,如果是竖屏则 UIScreen.main.bounds.height == 812
        public func isPhoneX() -> Bool {
            if UIScreen.main.bounds.width == 812 || UIScreen.main.bounds.width == 896 {  /// 横屏
                return true
            }
            return false
        }
        /// 是不是iPad
        public func isPad() -> Bool {
            return (UIDevice.current.userInterfaceIdiom == .pad) ? true : false;
        }
        
    }
    

    2.检测是哪种设备

      // MARK: - 检测是哪种设备
        func initCheckDevice(){
            if UIDevice.current.isPhoneX() {
                maxAspectRatio = 2.16         /// iPhoneX || iPhoneXs || iPhoneXs Max || iPhoneXr 2.16 高/宽比 ratio
            }else {
                maxAspectRatio  = UIDevice.current.isPad() ? (4.0 / 3.0) : (16.0 / 9.0)  /// iPhone 16:9,iPad 4:3
            }
            /// 画出可视区域
            drawPlayableArea(size: self.size,ratio: maxAspectRatio)
            /// 画出安全区域
            drawSafeArea(size: self.size,ratio: maxAspectRatio)
        }
    

    3.画出安全区域

     // MARK: - 安全区域即用户交互的区域,非可视区域 (iPhoneX的安全区域 < 可视区域)
        func drawSafeArea(size:CGSize,ratio:CGFloat){
            
            playableHeight  = size.width / ratio
            playableMargin = (size.height - playableHeight ) / 2.0   /// P70
            
            let safeInsetLeft   =  AREA_INSET_WIDTH_LEFT * ratio
            let safeInsetRight  =  size.width - safeInsetLeft - AREA_INSET_WIDTH_RIGHT * ratio
            
            playableRect = CGRect(x: safeInsetLeft, y: playableMargin, safeInsetRight, height:  playableHeight)  /// 注意 scene的anchorPoint(0,0)原点的位置;
            let shapeFrame = SKShapeNode(rect: playableRect)
            shapeFrame.zPosition = 2
            shapeFrame.strokeColor = SKColor.green
            shapeFrame.lineWidth = 6.0
            addChild(shapeFrame)
            
        }
    

    4.画出可视区域并赋于可视区域的边届物理特性

     // MARK: - 画出可视区域
        func drawPlayableArea(size:CGSize,ratio:CGFloat){
            
            playableHeight  = size.width / ratio
            playableMargin = (size.height - playableHeight ) / 2.0   /// P70
            playableRect = CGRect(x: 0, y: playableMargin,  size.width, height:  playableHeight)  /// 注意 scene的anchorPoint(0,0)原点的位置;
            print("playable Margin",playableMargin)
            
            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
            
            /// 地板
            setupFloor()
        }
    

    这样子Ball球就只在可视区域内(屏幕可视范围)运动了。

    适配iPhoneXs Max

    适配iPhoneXs Max

    重要的一点就是要了解屏幕尺寸和安全区域的不同,通俗点讲就是,屏幕可视范围可以放任何元素,但所有的用户交互行为都要放在安全区域内(兰色框内)。

    即可视区域(屏幕可视范围)= 安全区域 Safe Area + 危险区域 Danger Area

     

    源码传送门: https://github.com/apiapia/BreakOutGameVansVTutorial

    更多游戏教学:http://www.iFIERO.com

  • 相关阅读:
    Maven工程运行环境修改
    Maven中出现org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException错误
    IDEA创建maven_web工程后,右键包没有Servlet、Filter、Listener选项
    Spring中的依赖注入
    什么是JavaBean
    mybatis配置SqlMapConfig.xm时没有提示
    JDK1.8之后匿名内部类访问方法中的局部变量不用加final修饰
    架构、框架和设计模式
    CitrixSQL Server 2016高可用之SQL镜像 SQL Server mirror 带见证服务器
    CitrixPVS BDM启动模式创建虚机 BDM模式部署桌面(精华)
  • 原文地址:https://www.cnblogs.com/apiapia/p/9710703.html
Copyright © 2020-2023  润新知