我想根据屏幕大小更改节点的位置。例如,当我在iPhone 4s上运行我的应用程序时,并非所有节点都适合屏幕,因为我开发了iPhone 6尺寸的应用程序。我怎样才能使节点重新定位,具体取决于它运行的设备?我知道我可以通过约束实现这一点,但我不知道如何在Sprite Kit中做到这一点。我在下面放了一个屏幕截图。
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)
答案 0 :(得分:1)
这是一种我发现有效处理多种分辨率的技术。您需要在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)
}
}
然后为所有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))
}
}
例如,要创建一个精灵节点并将其置于任何屏幕尺寸的中心,您可以在GameScene
中使用它:
let sprite = SKSpriteNode(color: SKColor.whiteColor(), size: CGSizeMake(32, 32))
addChild(sprite)
sprite.posByScreen(0.5, y: 0.5)
答案 1 :(得分:1)
对于您正在寻找的内容没有简单的答案,您首先需要根据不同的宽高比来决定您的游戏应该是什么样的,并计划一下。在很多情况下,你想要给16:9手机更多FOV(他们可以看到更多的游戏世界)。要做到这一点,请设计2层游戏:游戏图层和hud叠加层。
游戏层将利用.AspectFill让你的游戏在各种设备上保持相同的“大小”,iPhone 4s的人们无法看到它们上方和下方的某些屏幕(你可以调整它们失去一些屏幕通过移动游戏层节点位置)
HUD覆盖层将处理需要停留在屏幕上固定位置的东西,如按钮和生活栏。现在您可以像人们提到的那样使用基于%的坐标,或者您可以保留绝对坐标,如果您的游戏检测到3:2(或4:3,如果您想要的话),只需添加/减去叠加节点的像素差异iPad)比例
基本原则:(不要复制verbatum)
让我们说我们创造一个160x284点的游戏场景
这意味着在iphone 4s上我们的分辨率是320x480,宽高比填充将采用顶部/底部或左/右之间的最小距离并缩放。在我们的情况下160将扩展到320,284将扩展到568.哦,哦,iPhone只有480,所以你输掉了88像素,这意味着在游戏世界我们将失去44分。
//这意味着顶部和底部各丢失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);
}
}