SKSpriteKit: расположение узлов при изменении размера при повороте устройства - PullRequest
0 голосов
/ 09 января 2020

Я использую SpriteKit, чтобы представить несколько ящиков (SKShapeNodes) с текстами внутри, например:

enter image description here

Затем я поворачиваю свое устройство, ожидая, что Ящики будут сохранять свое исходное положение независимо от ориентации, но получите это вместо:

enter image description here

Может ли кто-нибудь помочь мне найти преступника?

Это мой код:

import SpriteKit
import GameplayKit


struct TextMessage: Equatable
{
    var messageText : SKLabelNode?
    var messageBox : SKShapeNode?
}

class GameScene: SKScene {
    var background : SKSpriteNode!
    private var label : SKLabelNode?
    private var spinnyNode : SKShapeNode?
    var listOfTextMessages = [TextMessage]()
    var number = 1

    override func didMove(to view: SKView)
    {
        background = SKSpriteNode()
        background.color = .green
        addChild(background)
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        createTextMessageBox(text:"\(number)\(number)\(number)")
        number += 1
    }

    func createTextMessageBox(text:String)
    {
        var textboxWidth : CGFloat = 500

        if UIDevice.current.orientation.isLandscape { textboxWidth = 800 }
        else { textboxWidth = 500 }

        // Create the text message label
        let notificationText = SKLabelNode(fontNamed: "AppleSDGothicNeo-Regular")
        notificationText.name = "message_text"
        notificationText.text = text
        notificationText.fontSize = 45
        notificationText.fontColor = SKColor.white
        notificationText.alpha = 0
        notificationText.numberOfLines = 0
        notificationText.horizontalAlignmentMode = .left
        notificationText.verticalAlignmentMode = .center
        notificationText.preferredMaxLayoutWidth = textboxWidth-50

        // Height of the textbox depends on the size of the text
        let textboxHeight = notificationText.frame.height + 50

        // Notification textbox that contains the text
        let rightEdgeX = self.convert(CGPoint(x: self.frame.maxX, y: 0), to: background).x
        let bottomEdgeY = self.convert(CGPoint(x: 0, y: self.frame.minY), to: background).y
        let boxPositionX = rightEdgeX-50-textboxWidth
        let boxPositionY : CGFloat = bottomEdgeY+100

        // Create the Notification Textbox
        let notificationNode = SKShapeNode(rect: CGRect(x: boxPositionX, y: boxPositionY, width: textboxWidth, height: textboxHeight),cornerRadius: 20)
        notificationNode.name = "message_box"
        notificationNode.fillColor = UIColor(red: 120/255, green: 0/255, blue: 0/255, alpha: 0.8)
        notificationNode.strokeColor = UIColor(red: 128/255, green: 0/255, blue: 0/255, alpha: 1)
        notificationNode.lineWidth = 2
        notificationNode.alpha = 0
        notificationNode.zPosition = 1

        // Position text in the middle of the texbox
        notificationText.position = CGPoint(x: notificationNode.frame.minX+25, y: notificationNode.frame.maxY-textboxHeight/2)

        // Add nodes to the scene
        background.addChild(notificationNode)
        notificationNode.addChild(notificationText)

        // Add to the list of text messages
        let currentMessage = TextMessage(messageText: notificationText, messageBox: notificationNode)
        listOfTextMessages.insert(currentMessage, at: 0)

        // The first message is shown at the bottom, whereas the older messages are moved on top of it.
        for (index,textBox) in listOfTextMessages.enumerated()
        {
            // The latest message
            if index == 0
            {
                let actionBoxFadeIn = SKAction.fadeAlpha(to: 0.8, duration: 0.2) 
                let actionTextFadeIn = SKAction.run { textBox.messageText!.run(SKAction.fadeIn(withDuration: 0.2)) }
                let actionMoveGroup = SKAction.group([actionBoxFadeIn,actionTextFadeIn])
                textBox.messageBox!.run(actionMoveGroup)
            }
            else
            {
                textBox.messageBox!.position.y += listOfTextMessages[0].messageBox!.frame.height
            }
        }
    }


    override func didChangeSize(_ oldSize: CGSize)
    {
        super.didChangeSize(oldSize)

        if background != nil
        {
            background.size = CGSize(width: self.frame.width, height: self.frame.height)
            background.position = CGPoint(x: self.frame.width/2, y: self.frame.height/2)
        }

        if self.view != nil && !listOfTextMessages.isEmpty
        {
            if UIDevice.current.orientation.isLandscape
            {
                let textboxWidth : CGFloat = 800
                let textlabelWidth = textboxWidth-50

                for (index,textBox) in listOfTextMessages.enumerated()
                {
                    if index == 0
                    {
                        textBox.messageText!.fontSize = 45
                        textBox.messageText!.fontColor = SKColor.white
                        textBox.messageText!.numberOfLines = 0
                        textBox.messageText!.horizontalAlignmentMode = .left
                        textBox.messageText!.verticalAlignmentMode = .center
                        textBox.messageText!.preferredMaxLayoutWidth = textlabelWidth

                        let textboxHeight = textBox.messageText!.frame.height + 50

                        let rightEdgeX = self.convert(CGPoint(x: self.frame.maxX, y: 0), to: background).x
                        let bottomEdgeY = self.convert(CGPoint(x: 0, y: self.frame.minY), to: background).y
                        let boxPositionX = rightEdgeX-50-textboxWidth
                        let boxPositionY : CGFloat = bottomEdgeY+100

                        textBox.messageBox!.path = UIBezierPath(roundedRect: CGRect(x: boxPositionX, y: boxPositionY, width: textboxWidth, height: textboxHeight), cornerRadius: 20).cgPath

                        textBox.messageText!.position = CGPoint(x: textBox.messageBox!.frame.minX+25, y: textBox.messageBox!.frame.maxY-textboxHeight/2)
                    }
                    else
                    {
                        textBox.messageText!.fontSize = 45
                        textBox.messageText!.fontColor = SKColor.white
                        textBox.messageText!.numberOfLines = 0
                        textBox.messageText!.horizontalAlignmentMode = .left
                        textBox.messageText!.verticalAlignmentMode = .center
                        textBox.messageText!.preferredMaxLayoutWidth = textlabelWidth

                        let textboxHeight = textBox.messageText!.frame.height + 50

                        let rightEdgeX = self.convert(CGPoint(x: self.frame.maxX, y: 0), to: background).x
                        let boxPositionX = rightEdgeX-50-textboxWidth
                        let boxPositionY = listOfTextMessages[index-1].messageBox!.frame.minY //+ textboxHeight


                        textBox.messageBox!.path = UIBezierPath(roundedRect: CGRect(x: boxPositionX, y: boxPositionY, width: textboxWidth, height: textboxHeight), cornerRadius: 20).cgPath

                        textBox.messageText!.position = CGPoint(x: textBox.messageBox!.frame.minX+25, y: textBox.messageBox!.frame.minY-textboxHeight/2)
                    }
                }
            }
            else
            {
                let textboxWidth : CGFloat = 500
                let textlabelWidth = textboxWidth-50

                for (index,textBox) in listOfTextMessages.enumerated()
                {
                    if index == 0
                    {
                        textBox.messageText!.fontSize = 45
                        textBox.messageText!.fontColor = SKColor.white
                        textBox.messageText!.numberOfLines = 0
                        textBox.messageText!.horizontalAlignmentMode = .left
                        textBox.messageText!.verticalAlignmentMode = .center
                        textBox.messageText!.preferredMaxLayoutWidth = textlabelWidth

                        let textboxHeight = textBox.messageText!.frame.height + 50

                        let rightEdgeX = self.convert(CGPoint(x: self.frame.maxX, y: 0), to: background).x
                        let bottomEdgeY = self.convert(CGPoint(x: 0, y: self.frame.minY), to: background).y
                        let boxPositionX = rightEdgeX-50-textboxWidth
                        let boxPositionY : CGFloat = bottomEdgeY+100


                        textBox.messageBox!.path = UIBezierPath(roundedRect: CGRect(x: boxPositionX, y: boxPositionY, width: textboxWidth, height: textboxHeight), cornerRadius: 20).cgPath

                        textBox.messageText!.position = CGPoint(x: textBox.messageBox!.frame.minX+25, y: textBox.messageBox!.frame.maxY-textboxHeight/2)
                    }
                    else
                    {
                        textBox.messageText!.fontSize = 45
                        textBox.messageText!.fontColor = SKColor.white
                        textBox.messageText!.numberOfLines = 0
                        textBox.messageText!.horizontalAlignmentMode = .left
                        textBox.messageText!.verticalAlignmentMode = .center
                        textBox.messageText!.preferredMaxLayoutWidth = textlabelWidth

                        let textboxHeight = textBox.messageText!.frame.height + 50

                        let rightEdgeX = self.convert(CGPoint(x: self.frame.maxX, y: 0), to: background).x
                        let boxPositionX = rightEdgeX-50-textboxWidth
                        let boxPositionY = listOfTextMessages[index-1].messageBox!.frame.maxY - textboxHeight


                        textBox.messageBox!.path = UIBezierPath(roundedRect: CGRect(x: boxPositionX, y: boxPositionY, width: textboxWidth, height: textboxHeight), cornerRadius: 20).cgPath

                        textBox.messageText!.position = CGPoint(x: textBox.messageBox!.frame.minX+25, y: textBox.messageBox!.frame.minY-textboxHeight/2)
                    }
                }
            }
        }
    }
}

Спасибо!

РЕДАКТИРОВАТЬ:

Код для ViewController:

import UIKit
import SpriteKit
import GameplayKit

class GameViewController: UIViewController {

    override func viewDidLoad()
       {
           super.viewDidLoad()

           let scene = GameScene()
           let skView = self.view as! SKView

           if skView.bounds.size.height>skView.bounds.size.width
           {
               scene.size = CGSize(width: 1080, height: 1920)
           }
           else
           {
               scene.size = CGSize(width: 1920, height: 1080)
           }


           skView.showsFPS = true
           skView.showsNodeCount = true
           skView.ignoresSiblingOrder = false
           scene.scaleMode = .aspectFit
           skView.presentScene(scene)

       }

       override func viewWillLayoutSubviews()
       {
           super.viewDidLayoutSubviews()

           let skView = self.view as! SKView

           if let scene = skView.scene
           {
               if skView.bounds.size.height>skView.bounds.size.width
               {
                   scene.size = CGSize(width: 1080, height: 1920)
               }
               else
               {
                   scene.size = CGSize(width: 1920, height: 1080)
               }


               var size = scene.size

               // Bound size of the SKView in Points
               let boundWidth = skView.bounds.width
               let boundHeight = skView.bounds.height

               // New Height and Width ratio based on points
               let newHeight = boundHeight*size.width/boundWidth
               let newWidth = boundWidth*size.height/boundHeight

               // Adjust the new height in the scene
               if newHeight > size.height
               {
                   //scene.anchorPoint = CGPoint(x: 0, y: (newHeight - scene.size.height) / 2.0 / newHeight)
                   size.height = newHeight
                   scene.size = size
               }

               // Adjust the new width in the scene
               if newWidth > size.width
               {
                   //scene.anchorPoint = CGPoint(x: 0, y: (newWidth - scene.size.width) / 2.0 / newWidth)
                   size.width = newWidth
                   scene.size = size
               }
           }
       }
}

1 Ответ

1 голос
/ 09 января 2020

Вот очистка вашего кода изменения размера. Единственное различие, которое я обнаружил, было при настройке boxPositionY

    override func didChangeSize(_ oldSize: CGSize)
    {
        super.didChangeSize(oldSize)

        if background != nil
        {
            background.size = CGSize(width: self.frame.width, height: self.frame.height)
            background.position = CGPoint(x: self.frame.width/2, y: self.frame.height/2)
        }

        if self.view != nil && !listOfTextMessages.isEmpty
        {
            let textboxWidth : CGFloat = UIDevice.current.orientation.isLandscape ? 800 : 500
            let textlabelWidth = textboxWidth-50
            for (index,textBox) in listOfTextMessages.enumerated()
            {
                textBox.messageText!.fontSize = 45
                textBox.messageText!.fontColor = SKColor.white
                textBox.messageText!.numberOfLines = 0
                textBox.messageText!.horizontalAlignmentMode = .left
                textBox.messageText!.verticalAlignmentMode = .center
                textBox.messageText!.preferredMaxLayoutWidth = textlabelWidth
                let textboxHeight = textBox.messageText!.frame.height + 50    
                let rightEdgeX = self.convert(CGPoint(x: self.frame.maxX, y: 0), to: background).x
                let boxPositionX = rightEdgeX-50-textboxWidth

                ////////////////////////////////////////
                let boxPositionY : CGFloat = {
                    if UIDevice.current.orientation.isLandscape
                    {
                        return (index == 0) ? self.convert(CGPoint(x: 0, y: self.frame.minY), to: background).y+100 : listOfTextMessages[index-1].messageBox!.frame.minY //+ textboxHeight
                    }
                    else
                    {
                        return (index == 0) ? self.convert(CGPoint(x: 0, y: self.frame.minY), to: background).y+100 : listOfTextMessages[index-1].messageBox!.frame.maxY - textboxHeight
                    }
                }()
                /////////////////////////////////////////

                textBox.messageBox!.path = UIBezierPath(roundedRect: CGRect(x: boxPositionX, y: boxPositionY, width: textboxWidth, height: textboxHeight), cornerRadius: 20).cgPath
                textBox.messageText!.position = CGPoint(x: textBox.messageBox!.frame.minX+25, y: textBox.messageBox!.frame.minY-textboxHeight/2)
            }


        }
    }
...