在SpriteKit中围绕场景的背景夹紧相机
所以我有一个基础游戏设置,可以在下面的bitbucket链接找到:
游戏链接
我目前很难理解如何翻译相对于场景布局的相机节点。
目标是让摄像机跟随播放器,直到达到由场景大小定义的角落边界。 在此特定测试场景设置中,场景大小为1000×1000,相机比例为1。
下面的代码用于在新位置设置为跟随角色时修改摄像机的位置:
var cameraPosition: CGPoint { get { return CGPoint(x: camera!.position.x, y: camera!.position.y) } set { let cameraScale = CGFloat(1) let sceneScale = CGFloat(1)//CGFloat(1 - 0.44 + 0.05 /*possible rounding error adjustment*/) // let viewAspectRatio = CGRectGetWidth(view!.frame)/CGRectGetHeight(view!.frame) let newPositionValue = double2(x: Double(newValue.x * sceneScale), y: Double(newValue.y * sceneScale)) let scaledSceneSize = CGSize(width: size.width * sceneScale , height: size.height * sceneScale) //// scaledSceneSize.height = scaledSceneSize.height / viewAspectRatio let cameraSize = view!.bounds.size let scaledCameraSize = CGSize(width: cameraSize.width * cameraScale, height: cameraSize.height * cameraScale) let minX = 0//-scaledSceneSize.width * anchorPoint.x + scaledCameraSize.width / 2 let minY = -219//-scaledSceneSize.height * anchorPoint.y + scaledCameraSize.height / 2 let minValues = double2(x: Double(minX), y: Double(minY)) let maxX = 0//(scaledSceneSize.width * anchorPoint.x - scaledCameraSize.width / 2) //size.width - cameraSize.width / 2 let maxY = 219//(scaledSceneSize.height * anchorPoint.y - scaledCameraSize.height / 2) //- cameraSize.height / 2 let maxValues = double2(x: Double(maxX), y: Double(maxY)) let clampedPosition = clamp(newPositionValue, min: minValues, max: maxValues) camera!.position = CGPoint(x: (clampedPosition.x / Double(sceneScale)), y: (clampedPosition.y / Double(sceneScale))) } }
目前有适合所需场景大小的硬核值,我不确定如何通过比例获得这些结果。 默认情况下,比例为:
/* Set the scale mode to scale to fit the window */ scene.scaleMode = .AspectFill
如果不知道在规模上有翻译,默认情况下,我希望边界为maximumSceneDimensionXValue – cameraSize.width / 2 largestSceneDimensionYValue – cameraSize.height / 2
作为一个高级的例子。 有人能帮助我获得这个翻译吗?
整体而言,场景在所有角落应如下所示:
VS在相机中出现黑色背景溢出:
像这样的应用正是SKConstraint
的用途。
你可以看到这个确切function的演示 – 约束一个摄像头,使其跟随播放器,但不会在关卡边缘显示太多空白空间 – 在WWDC15会话中深入到使用DemoBots的GameplayKit 。*(链接)在谈论此function的讨论时,应该跳到大约7点27分。)
video中的内容,以及DemoBots示例代码中的一些片段:
-
使用距离约束使相机保持在播放器的中心位置(自动,无需在每次
update()
直接设置camera.position
)。// Constrain the camera to stay a constant distance of 0 points from the player node. let zeroRange = SKRange(constantValue: 0.0) let playerBotLocationConstraint = SKConstraint.distance(zeroRange, toNode: playerNode)
-
使用位置约束将摄像机保持在关卡边缘的特定范围内 。 通过获取关卡的框架并将该矩形插入摄像机应与关卡边缘保持的距离来计算该范围。
// get the scene size as scaled by `scaleMode = .AspectFill` let scaledSize = CGSize(width: size.width * camera.xScale, height: size.height * camera.yScale) // get the frame of the entire level contents let boardNode = childNodeWithName(WorldLayer.Board.nodePath)! let boardContentRect = boardNode.calculateAccumulatedFrame() // inset that frame from the edges of the level // inset by `scaledSize / 2 - 100` to show 100 pt of black around the level // (no need for `- 100` if you want zero padding) // use min() to make sure we don't inset too far if the level is small let xInset = min((scaledSize.width / 2) - 100.0, boardContentRect.width / 2) let yInset = min((scaledSize.height / 2) - 100.0, boardContentRect.height / 2) let insetContentRect = boardContentRect.insetBy(dx: xInset, dy: yInset) // use the corners of the inset as the X and Y range of a position constraint let xRange = SKRange(lowerLimit: insetContentRect.minX, upperLimit: insetContentRect.maxX) let yRange = SKRange(lowerLimit: insetContentRect.minY, upperLimit: insetContentRect.maxY) let levelEdgeConstraint = SKConstraint.positionX(xRange, y: yRange) levelEdgeConstraint.referenceNode = boardNode
-
将两个约束应用于
SKCameraNode
。camera.constraints = [playerBotLocationConstraint, levelEdgeConstraint]
要深入了解一下,请下载Apple的DemoBots示例代码项目 ,该项目有很多评论和支持代码,我从上面的代码片段中删除了这些代码,以防止这篇文章变得过长。 相机约束的所有内容都在LevelScene.swift
中的func setCameraConstraints()
中。
*尽管有会话名称,但它不仅仅是GameplayKit …它展示了如何利用iOS 8 / OS X 10.11 / Xcode 7中引入的许多技术来构建类似于全尺寸游戏的东西:App Thinning,new SpriteKitfunction,ReplayKit等等。
我没有使用你的代码。 我做了一个示例项目,并使其工作。
inheritance我的代码
import SpriteKit class GameScene: SKScene { let world = SKSpriteNode(imageNamed: "world.jpg") let player = SKSpriteNode(color: SKColor.greenColor(), size: CGSizeMake(10, 10)) var cam: SKCameraNode! override init(size: CGSize) { super.init(size: size) print(world.size) addChild(world) addChild(player) world.zPosition = 1 player.zPosition = 2 cam = SKCameraNode() self.camera = cam addChild(cam) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func touchesBegan(touches: Set, withEvent event: UIEvent?) { for touch: AnyObject in touches { let location = touch.locationInNode(self) player.position = location } } override func touchesMoved(touches: Set , withEvent event: UIEvent?) { for touch: AnyObject in touches { let location = touch.locationInNode(self) player.position = location } } func clampCamera(){ func clamp(inout input: CGFloat, num1: CGFloat, num2: CGFloat) { if input < num1 { input = num1 } else if input > num2 { input = num2 } } let lBoundary = -world.size.width/2 + size.width/2 let rBoundary = world.size.width/2 - size.width/2 let bBoundary = -world.size.height/2 + size.height/2 let tBoundary = world.size.height/2 - size.height/2 clamp(&camera!.position.x, num1: lBoundary, num2: rBoundary) clamp(&camera!.position.y, num1: bBoundary, num2: tBoundary) } override func update(currentTime: NSTimeInterval) { camera!.position = player.position clampCamera() } }
这是我用作“世界”的相同图像http://i.imgur.com/XhZbh8q.jpg