SpriteKit设备方向改变导致SKLabelNode失真Swift

时间:2017-02-28 00:29:01

标签: ios swift sprite-kit orientation sklabelnode

我正在使用SpriteKit在Swift中为iOS编写游戏。我仍然是SpriteKit的新手。

我想支持iPhone和iPad的两种方向,并且发现了这一点: multiple orientations in SpriteKit

这在模拟器和设备中按预期工作,但是在设备上我注意到一些SKSpriteNodes在设备旋转动画之前稍微扭曲到它们的新大小。

这一点非常明显,特别是对于SKLabelNodes,文本会根据方向的变化而略微压扁或拉伸。

我知道为什么会发生失真,但确认和修复会很棒。

这种情况发生在使用链接中描述的代码的设备上,但我已经更新了swift 3

class GameViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let scene = GameScene(size:self.view.bounds.size)
        scene.scaleMode = .resizeFill
        (self.view as! SKView).presentScene(scene)
    }

    override var shouldAutorotate: Bool {
        return true
    }

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        if UIDevice.current.userInterfaceIdiom == .phone {
            return .allButUpsideDown
        } else {
            return .all
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Release any cached data, images, etc that aren't in use.
    }

    override var prefersStatusBarHidden: Bool {
        return true
    }
}

class GameScene: SKScene {
    var currentNode: CustomNode!

    override func didMove(to view: SKView) {
        self.backgroundColor = SKColor.white
        transitionToScene(sceneType: .Menu)
    }
    override func didChangeSize(_ oldSize: CGSize) {
        currentNode?.layout()
    }
    func transitionToScene(sceneType: SceneTransition) {
        switch sceneType {
        case .Menu:
            currentNode?.dismissWithAnimation(animation: .Right)
            currentNode = MenuNode(gameScene: self)
            currentNode.presentWithAnimation(animation: .Right)

        case .Scores:
            currentNode?.dismissWithAnimation(animation: .Left)
            currentNode = ScoresNode(gameScene: self)
            currentNode.presentWithAnimation(animation: .Left)

        default: fatalError("Unknown scene transition.")
        }
    }
}

class CustomNode: SKNode {
    weak var gameScene: GameScene!

    init(gameScene: GameScene) {
        self.gameScene = gameScene
        super.init()
    }
    func layout() {}
    func presentWithAnimation(animation:Animation) {
        layout()
        let invert: CGFloat = animation == .Left ? 1 : -1
        self.position = CGPoint(x: invert*gameScene.size.width, y: 0)
        gameScene.addChild(self)
        let action = SKAction.move(to: CGPoint(x: 0, y: 0), duration: 0.3)
        action.timingMode = SKActionTimingMode.easeInEaseOut
        self.run(action)
    }
    func dismissWithAnimation(animation:Animation) {
        let invert: CGFloat = animation == .Left ? 1 : -1
        self.position = CGPoint(x: 0, y: 0)
        let action = SKAction.move(to: CGPoint(x: invert*(-gameScene.size.width), y: 0), duration: 0.3)
        action.timingMode = SKActionTimingMode.easeInEaseOut
        self.run(action, completion: {self.removeFromParent()})
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}


class MenuNode: CustomNode {
    var label: SKLabelNode
    var container: SKSpriteNode

    override func layout() {
        container.position = CGPoint(x: gameScene.size.width/2.0, y: gameScene.size.height/2.0)
    }
    override init(gameScene: GameScene) {
        label = SKLabelNode(text: "Menu Scene")
        label.horizontalAlignmentMode = .center
        label.verticalAlignmentMode = .center
        container = SKSpriteNode(color: UIColor.black, size: CGSize(width: 200, height: 200))
        container.addChild(label)
        super.init(gameScene: gameScene)
        self.addChild(container)
        self.isUserInteractionEnabled = true
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.gameScene.transitionToScene(sceneType: .Scores)
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class ScoresNode: CustomNode {
    var label: SKLabelNode
    var container: SKSpriteNode

    override func layout() {
        container.position = CGPoint(x: gameScene.size.width/2.0, y: gameScene.size.height/2.0)
    }
    override init(gameScene: GameScene) {
        label = SKLabelNode(text: "Scores Scene")
        label.horizontalAlignmentMode = .center
        label.verticalAlignmentMode = .center
        container = SKSpriteNode(color: UIColor.black, size: CGSize(width: 200, height: 200))
        container.addChild(label)
        super.init(gameScene: gameScene)
        self.addChild(container)
        self.isUserInteractionEnabled = true
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.gameScene.transitionToScene(sceneType: .Menu)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

enum SceneTransition{
    case Menu, Scores
}
enum Animation {
    case Left, Right, None
}

信用:Epic Byte

我也尝试过使用

viewWillTransitionToSize...

因为这会处理设备方向的变化,我看到在设备轮换中多次调用didChangeSize ...因此我更喜欢viewWillTransitionToSize ......

提前致谢。

莱昂

2 个答案:

答案 0 :(得分:2)

进入Storyboard文件,选择ViewController的视图,在右侧栏中查找滑块图片,它应该是左边的第4个。这称为属性检查器。将内容模式更改为中心。这会给你黑条但会停止压扁。

答案 1 :(得分:1)

这是根据@ Knight0fDragon的建议创建的代码,生成的SKLabelNodes在使用scaleMode .resizeFill旋转时不会挤压或拉伸。请注意,此视图的大小适用于1024x768分辨率的iPad,创建大小为1024x1024的方形视图。当应用程序加载时,根据方向,宽度或高度的最大值很容易复制。

class GameViewController: UIViewController {

var scene : GameScene!
var newView: SKView!

override func viewDidLoad() {
    super.viewDidLoad()

    self.newView = SKView(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 1024, height: 1024)))
    (self.view as? SKView)?.contentMode = .center
    self.newView.contentMode = .center
    self.newView.autoresizesSubviews = false
    self.newView.autoresizingMask = [.flexibleBottomMargin, .flexibleTopMargin, .flexibleLeftMargin, .flexibleRightMargin]
    (self.view as? SKView)?.addSubview(newView)
    self.newView.center = view.center
    self.scene = GameScene(size: CGSize(width: 1024, height: 1024))
    self.scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    self.scene.scaleMode = .resizeFill
    self.newView.presentScene(scene)
}

override var shouldAutorotate: Bool {
    return true
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    if UIDevice.current.userInterfaceIdiom == .phone {
        return .allButUpsideDown
    } else {
        return .all
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Release any cached data, images, etc that aren't in use.
}

override var prefersStatusBarHidden: Bool {
    return true
}
}

class GameScene: SKScene {

var labelNode: SKLabelNode!
var container: SKSpriteNode!

override func didMove(to view: SKView) {
    self.backgroundColor = SKColor.darkGray

    container = SKSpriteNode(color: .black, size: CGSize(width: 300, height: 300))
    self.addChild(container)

    labelNode = SKLabelNode(text: "hello")
    labelNode.fontColor = .white
    container.addChild(labelNode)
}
}