简体   繁体   English

根据屏幕大小更改节点位置Swift / Sprite Kit

[英]Change Node Positioning Depending on Screen Size Swift/Sprite Kit

I want to change to positioning of my nodes depending on the size of the screen. 我想根据屏幕尺寸更改节点的位置。 For example, when I run my app on an iPhone 4s, not all of the nodes fit on the screen, since I developed the app with iPhone 6 dimensions in mind. 例如,当我在iPhone 4s上运行我的应用程序时,并非所有节点都适合屏幕,因为我在开发应用程序时就考虑了iPhone 6尺寸。 How can I make it so the nodes reposition themselves depending on which device it's running on? 如何使节点根据运行的设备重新定位? I know I can achieve this with constraints normally, but I don't know how to do that in Sprite Kit. 我知道我通常可以通过约束来实现,但是我不知道如何在Sprite Kit中做到这一点。 I have included a screen shot down below. 我包括下面的屏幕快照。

    lblRocketCount.position = CGPoint(x: 100, y: 150)
    lblRocketCount.text = "Bullets: 30"
    self.addChild(lblRocketCount)

    lblMissileCount.position = CGPoint(x: -100, y: 150)
    lblMissileCount.text = "Missiles: 5"
    self.addChild(lblMissileCount)


    leftBorder.position = CGPoint(x: -333, y: 0)
    self.addChild(leftBorder)

    rightBorder.position = CGPoint(x: 333, y: 0)
    self.addChild(rightBorder)

    topBorder.position = CGPoint(x: 0, y: 187)
    self.addChild(topBorder)

    bottomBorder.position = CGPoint(x: 0, y: -187)
    self.addChild(bottomBorder)

    buttonDirUp.position = CGPoint(x: -200, y: -50)
    buttonDirUp.setScale(2.0)
    self.addChild(buttonDirUp)

    ship.setScale(0.33)
    shootButton.setScale(0.7)
    missileButton.setScale(0.5)


    buttonDirLeft.position = CGPoint(x: -250, y: -100)
    buttonDirLeft.setScale(2.0)
    self.addChild(buttonDirLeft)

    buttonDirDown.position = CGPoint(x: -200, y: -150)
    buttonDirDown.setScale(2.0)
    self.addChild(buttonDirDown)

    buttonDirRight.position = CGPoint(x: -150, y: -100)
    buttonDirRight.setScale(2.0)
    self.addChild(buttonDirRight)

    self.view?.multipleTouchEnabled = true

    self.backgroundColor = SKColor.blackColor()

    self.anchorPoint = CGPointMake(0.5, 0.5)

    self.addChild(base)
    base.position = CGPointMake(200, -100)

    self.addChild(ball)
    ball.position = base.position

    self.addChild(ship)
    ship.position = CGPoint(x: self.frame.midX, y: self.frame.midY)

    self.addChild(shootButton)
    shootButton.position = CGPoint(x: self.frame.midX, y: -100)

    self.addChild(missileButton)
    missileButton.position = CGPoint(x: -200, y: 50)

Screen Shot 屏幕截图

This is a technique that I've found to be effective for dealing with multiple resolutions. 我发现这项技术可以有效应对多种分辨率。 You'll need to create two global variables in your GameViewController that reflect the size of the current view: 您需要在GameViewController中创建两个全局变量,以反映当前视图的大小:

import SpriteKit


// global variables
var SKViewSize: CGSize?
var SKViewSizeRect: CGRect?


class GameViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let skView = self.view as! SKView
        SKViewSize = skView.bounds.size
        let scene = GameScene(size: SKViewSize!)

        scene.scaleMode = .AspectFill
        skView.presentScene(scene)
        SKViewSizeRect = getViewSizeRect()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        SKViewSize = self.view.bounds.size
        SKViewSizeRect = getViewSizeRect()

        let skView = self.view as! SKView
        if let scene = skView.scene {
            if scene.size != self.view.bounds.size {
                scene.size = self.view.bounds.size
            }
        }
    }

    func getViewSizeRect() -> CGRect {
        return CGRect(x: ((SKViewSize!.width  * 0.5) * -1.0), y: ((SKViewSize!.height * 0.5) * -1.0), width: SKViewSize!.width, height: SKViewSize!.height)
    }
}

Then create an extension for all SKNode types that allows you to position them using a percentage of the current screen size: 然后为所有SKNode类型创建一个扩展名,该扩展名允许您使用当前屏幕尺寸的百分比来定位它们:

public extension SKNode {

    public func posByScreen(x: CGFloat, y: CGFloat) {
        self.position = CGPoint(x: CGFloat((SKViewSizeRect!.width * x) + SKViewSizeRect!.origin.x), y: CGFloat((SKViewSizeRect!.height * y) + SKViewSizeRect!.origin.y))
    }
}

For example, to create a sprite node and center it on any screen size, you'd use this in your GameScene : 例如,要创建一个精灵节点并将其居中放置在任何屏幕尺寸上,可以在GameScene使用它:

let sprite = SKSpriteNode(color: SKColor.whiteColor(), size: CGSizeMake(32, 32))
addChild(sprite)
sprite.posByScreen(0.5, y: 0.5)

There is no easy answer to what you are looking for, you first need to decide what your game should be like at the different aspect ratios, and plan around that. 对于要寻找的内容没有简单的答案,您首先需要确定游戏在不同宽高比下的外观,然后进行规划。 In a lot of cases, you want to just give the 16:9 phones more FOV (They can see more of the game world). 在很多情况下,您只想给16:9手机更多的FOV(他们可以看到更多游戏世界)。 To do this, design your game with 2 layers: a game layer, and a hud overlay. 为此,将游戏设计为2个层:一个游戏层和一个hud叠加层。

The game layer will utilize .AspectFill to keep your game the same "size" across devices, with the iPhone 4s folk losing the ability to see some of the screen above and below them (You can adjust where they lose some of the screen by moving the game layer nodes position) 游戏层将利用.AspectFill来使您的游戏在各种设备上保持相同的“大小”,而iPhone 4s的人们将失去在其上和下查看某些屏幕的能力(您可以通过移动来调整他们丢失某些屏幕的位置游戏层节点位置)

The HUD overlayer will handle the things that need to stay at a fixed position on screen, like buttons and life bars. HUD覆盖层将处理需要保持在屏幕上固定位置的事物,例如按钮和救生圈。 Now you can use the % based coordinates like some people have mentioned, or you can keep the absolute coordinates, and just add/subtract the pixel difference from your overlay nodes if your game detects a 3:2 (or 4:3 if you want iPad) ratio 现在,您可以像某些人提到的那样使用基于%的坐标,或者您可以保留绝对坐标,并且如果您的游戏检测到3:2(或者如果您愿意,则为4:3),只需从叠加节点中减去像素差即可。 iPad)比例

Basic principle: (Do not copy verbatum) 基本原理:(请勿复制verbatum)

Lets say we create a game scene that is 160x284 points 假设我们创建了一个160x284点的游戏场景

This means on an iphone 4s our resolution is 320x480, aspect fill is going to take the smallest of the distance between top/bottom or left/right and scale to that. 这意味着在iPhone 4s上,我们的分辨率为320x480,纵横比填充将采用顶部/底部或左侧/右侧之间最小的距离进行缩放。 In our case 160 is going to scale to 320, 284 is going to scale to 568. Uh oh, iphone only has 480, so you are losing out on 88 pixels, which means in the game world we are losing 44 points. 在我们的案例中,160将缩放到320,284将缩放到568。呃,iphone只有480,所以您损失了88像素,这意味着在游戏世界中我们损失了44点。

//This means that the top and bottom will lose out on 22 points each, so lets make that our iphone4s padding //这意味着顶部和底部将分别输掉22点,所以让我们的iphone4s填充

class GameScene
{
  let gameNode = SKNode();
  let overlayNode = SKNode();
  let iPhone4sPadding = 22;
  func init()
  {
     //add all of the games nodes that you would add to the scene to gameNode instead
      self.addChild(gameNode);

     //add all of your overlay nodes (buttons, lifebars, etc) to the overlayNode

     //do a check on uiscreen to see if the height is 480, if it is
     //  all nodes on the bottom add iphone4spadding to the y
     //  all nodes on the top subtract iphone4spadding from the y
     self.addChild(overlayNode);

  }
}

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

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