简体   繁体   English

交换的宽度和高度值

[英]Swapped width and height values

Explanation 说明

For some reason, width and height values are being swapped in my game (as you can see below) that is set to be in landscape orientation. 由于某些原因,宽度和高度值在我的游戏中被交换(如下所示),该值设置为横向。 This way, the sprite that should be centered in the screen, is totally off the right position. 这样,应该在屏幕中央居中的精灵完全偏离了正确的位置。

在此处输入图片说明


Code

You can download it here . 您可以在这里下载。

GameScene 游戏场景

import SpriteKit

class GameScene: SKScene {

    override func didMoveToView(view: SKView) {

        print("width:", self.frame.width)
        print("height:", self.frame.height)

        //Sprite
        let sprite = SKSpriteNode (imageNamed: "sprite")
        sprite.anchorPoint = CGPointZero
        sprite.position = CGPoint(x: self.frame.width / 2 - sprite.frame.width / 2, y: self.frame.height / 2 - sprite.frame.height / 2)
        addChild(sprite)
    }
}

GameViewController GameViewController

import UIKit
import SpriteKit

class GameViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set view size.
        let scene = GameScene(size: view.bounds.size)

        // Configure the view.
        let skView = view as! SKView
        skView.showsFPS = true
        skView.showsNodeCount = true

        /* Sprite Kit applies additional optimizations to improve rendering performance */
        skView.ignoresSiblingOrder = true

        /* Set the scale mode to scale to fit the window */
        scene.scaleMode = .ResizeFill

        skView.presentScene(scene)
    }

    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
            return .Landscape
        } else {
            return .Landscape
        }
    }
}


Thanks in advance, 提前致谢,
Luiz. 路易斯

If you go to targets-General in your xCode project (where you set version number, bundle ID etc) did you untick portrait? 如果您在xCode项目中转到targets-General(在其中设置版本号,捆绑软件ID等),您是否取消了肖像画? You also might have to check your info.plist to see if all portrait entries are removed for both devices. 您可能还必须检查一下info.plist,以查看是否同时删除了两个设备的所有肖像条目。

You approach unfortunately is bad practice a lot of tutorials teach you and I would not continue like this. 不幸的是,您的做法是错误的做法,许多教程都教您,我不会这样继续。

If you use "scaleMode ResizeFill" or set the scene size to "view.bounds" your game will never look consistent on all devices. 如果您使用“ scaleMode ResizeFill”或将场景大小设置为“ view.bounds”,则游戏在所有设备上的外观将永远不会保持一致。 Furthermore all your values (sprite sizes, font sizes, physics values etc) will also not be the same on devices different to the one you are testing on. 此外,在与要测试的设备不同的设备上,所有值(子图形大小,字体大小,物理值等)也将不同。

Basically you will have to adjust for all of this on like 5-6 devices and its madness, especially using xCode simulator. 基本上,您将不得不针对5-6台设备及其疯狂程度进行调整,尤其是使用xCode模拟器时。 Trust me I have been there before with 2 games and it nearly killed me. 相信我,我之前参加过2场比赛,差点杀死我。 Its a game of game of "yeah this looks about right". 它是“是的,看起来不错”的游戏。

Dont go through this, so what you should do is 不要经历这个,所以你应该做的是

1) Change your scene size to the default scene size used by xCode 1)将场景大小更改为xCode使用的默认场景大小

  GameScene(size: CGSize(width: 1024, height: 768)) // swap if portrait

Note: Check update at bottom 注意:检查底部的更新

  If you dont do this, and leave it at view.bounds.size, point 2 will not work.

2) Change your scene scale mode to .AspectFill (also default xCode settings). 2)将场景缩放模式更改为.AspectFill(也是默认的xCode设置)。

This way all your stuff will look great on all iPhones. 这样,您所有的东西在所有iPhone上都会看起来很棒。 Your values will scale correctly and you save yourself a lot of work. 您的值将正确缩放,您可以节省很多工作。 On iPads you will have some extra space at the top and bottom (landscape) or left and right (portrait) which you usually just cover with some more background and have as a non playable area 在iPad上,顶部和底部(风景)或左侧和右侧(人像)会有一些额外的空间,通常只覆盖了一些背景并且作为不可玩的区域

Your scene basically looks like this now. 您的场景现在基本上像这样。

在此处输入图片说明

The red area is your whole scene size (iPad) but if you run on iPhones you will only see the green bit. 红色区域是整个场景的大小(iPad),但如果在iPhone上运行,则只会看到绿色的部分。 In Portrait mode that red area would be on the left and right side. 在“人像”模式下,红色区域将位于左侧和右侧。

Thats why y positioning is usually done from the centre because if you use frame.minY or frame.maxY you would be in the red zone and won't see the sprite on iPhones. 这就是为什么y定位通常是从中心开始的原因,因为如果使用frame.minY或frame.maxY,您将处在红色区域中,而不会在iPhone上看到精灵。 That red zone you just cover with some more background (your background full screen images should be iPad size). 您仅用更多背景覆盖的红色区域(您的全屏背景图像应为iPad尺寸)。

This also make your game more balanced, because if your would just stretch up your game than it will be easier on iPads because you have more space. 这也使您的游戏更加平衡,因为如果您只是扩大游戏范围,则比iPad上的游戏更容易,因为您有更多的空间。

So design your game within the green zone. 因此,请在绿色区域内设计游戏。 Than on iPads the only thing you might have to do is move up some UI, like pause button or score label, when you want to show them at the top edge. 与iPad相比,当您要在顶部显示某些用户界面时,唯一需要做的就是向上移动一些UI,例如暂停按钮或得分标签。 I do it this way. 我是这样的。

 // Some button
 ...
 someButton.position = CGPoint(x: frame.midX, y: frame.midY + 200)
 addChild(someButton)

 if UIDevice.current.userInterfaceIdiom == .pad {
     // set for iPad
 }

 // Some label
 someLabel.positon = CGPoint(x: frame.midX - 100, someButton.position.y) // because its y position is the same as someButton I only have to adjust someButton.position.y on iPads.
 addChild(someLabel)

I would not continue with your approach, even if it means redoing a lot of work. 我不会继续使用您的方法,即使这意味着要重做很多工作。

UPDATE: 更新:

It seems with xCode 8 apple changed the default scene size from 1024x768 (768x1024) to 1334x750 (750x1334). 似乎使用xCode 8苹果将默认场景大小从1024x768(768x1024)更改为1334x750(750x1334)。 I have only played around with those settings for a bit and they seem confusing for a universal game. 我只玩过这些设置,对于通用游戏它们似乎有些混乱。

So you scene would now look like this and stuff on the xAxis on iPads is offscreen. 因此,您的场景现在看起来像这样,并且iPad上xAxis上的内容不在屏幕上。

在此处输入图片说明

That makes no sense as the iPad is clearly not more widescreen than an iPhone. 因为iPad显然不比iPhone宽屏,所以这没有任何意义。 I actually opened a bug report to see what apple says about this so for now I would probably keep it at 1024x768. 我实际上打开了一个错误报告,看看苹果对此有何评论,所以现在我可能将其保持在1024x768。

Hope this helps 希望这可以帮助

Override viewWillLayoutSubviews in your GameViewController to ensure you get the proper width/height of the view. GameViewController重写viewWillLayoutSubviews ,以确保获得正确的视图宽度/高度。 The implication with this also is that any objects you may instantiate would need to wait until this method has been called. 这也意味着您可以实例化的任何对象都需要等待,直到调用此方法为止。

So you would want to do something like 所以你想做类似的事情

class GameViewController: UIViewController {

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    // NOTE: Add code to do this only once!
    // Set view size.
    let scene = GameScene(size: view.bounds.size)

    // Configure the view.
    let skView = view as! SKView
    skView.showsFPS = true
    skView.showsNodeCount = true

    /* Sprite Kit applies additional optimizations to improve rendering performance */
    skView.ignoresSiblingOrder = true

    /* Set the scale mode to scale to fit the window */
    scene.scaleMode = .ResizeFill

    skView.presentScene(scene)
}

Note I didn't try and compile this and it is missing a trailing } . 请注意,我没有尝试对此进行编译,并且缺少尾随的} Additionally, you would want to do this only once, I haven't added the code to do that. 另外,您只想执行一次,我还没有添加代码来执行此操作。 In my game, my scene is a property so I just check to see if it is nil and if it is, then I create the scene and present. 在我的游戏中,我的场景是一个属性,因此我只需要检查它是否为nil,如果为零,就可以创建场景并呈现。

Following your code and according to how do you want to construct your sprite and position in GameScene you simply must change the scene.scaleMode to AspectFill or AspectFit (depend by what do you want to achieve): 按照您的代码,并根据您要如何在GameScene构造精灵和位置,您只需将scene.scaleMode更改为AspectFillAspectFit (取决于您要实现的目标):

sources : 资料来源

@available(iOS 7.0, *)
public enum SKSceneScaleMode : Int {

    case Fill /* Scale the SKScene to fill the entire SKView. */
    case AspectFill /* Scale the SKScene to fill the SKView while preserving the scene's aspect ratio. Some cropping may occur if the view has a different aspect ratio. */
    case AspectFit /* Scale the SKScene to fit within the SKView while preserving the scene's aspect ratio. Some letterboxing may occur if the view has a different aspect ratio. */
    case ResizeFill /* Modify the SKScene's actual size to exactly match the SKView. */
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM