Serrer la camera autour du fond d'une scène dans SpriteKit

J'ai donc une configuration de jeu de base qui peut être trouvée sur le lien bitbucket ci-dessous:

Lien du jeu

J'ai du mal à comprendre comment traduire le nœud de la camera par rapport à la disposition de la scène.

Le but est d'amener la camera à suivre le joueur jusqu'à atteindre une limite de coin définie par la taille de la scène. Dans cette configuration de scénario de test particulière, la scène a une taille de 1000×1000 avec une échelle de camera de 1.

Le code ci-dessous est utilisé pour modifier la position de la camera lorsqu'une nouvelle position est définie pour suivre le caractère:

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))) } } 

Il y a une valeur hardcore qui correspond actuellement à la taille de la scène requirejse, et je ne sais pas comment get ces résultats via l'échelle. L'échelle par défaut est:

 /* Set the scale mode to scale to fit the window */ scene.scaleMode = .AspectFill 

Sans la connaissance de savoir qu'il y a une traduction à l'échelle, par défaut, je m'attendrais à ce que les limites soient plus grandesSceneDimensionXValue – cameraSize.width / 2 largestSceneDimensionYValue – cameraSize.height / 2

Comme un exemple de haut niveau. Quelqu'un pourrait-il m'aider à get cette traduction?

Dans l'set, la scène devrait ressembler à ce qui suit dans tous les coins: objectif

VS ayant le fond noir débordant dans l'appareil photo en tant que tel:

anti-but

Je n'ai pas utilisé votre code. J'ai fait un exemple de projet et j'ai réussi à le faire fonctionner.

entrez la description de l'image ici

voici mon code

 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<UITouch>, withEvent event: UIEvent?) { for touch: AnyObject in touches { let location = touch.locationInNode(self) player.position = location } } override func touchesMoved(touches: Set<UITouch>, 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() } } 

c'est la même image que j'ai utilisée comme mon "monde" http://i.imgur.com/XhZbh8q.jpg

Des applications comme celle-ci sont exactement ce que SKConstraint est pour.

Vous pouvez voir une démo de cette fonctionnalité exacte – contraignant une camera pour qu'elle suive le joueur, mais ne montre pas trop d'espace vide autour du niveau – dans la session WWDC15. Deeper dans GameplayKit avec DemoBots . * (Le lien il devrait sauter à environ 7h27 dans le discours où la discussion de cette fonctionnalité commence.)

L'essentiel de ce qui est dans la video, avec quelques extraits de l'exemple de code DemoBots:

  1. Utilisez une contrainte de distance pour garder la camera cinput sur le lecteur (automatiquement, sans avoir à régler camera.position directement à chaque update() ).

     // 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) 
  2. Utilisez une contrainte de position pour maintenir la camera dans une certaine plage du bord du niveau. Calculer cette gamme en prenant le cadre du niveau et en insérant ce rect de la distance que la camera doit garder du bord du niveau.

     // 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 
  3. Appliquez les deux contraintes à votre SKCameraNode .

     camera.constraints = [playerBotLocationConstraint, levelEdgeConstraint] 

Pour un aperçu plus approfondi, téléchargez le projet de code exemple DemoBots d'Apple , qui contient beaucoup de commentaires et de code de prise en charge que j'ai découpé à partir des extraits ci-dessus pour éviter que ce message ne soit excessivement long. Tout pour la contrainte de camera est dans func setCameraConstraints() dans LevelScene.swift .

* Malgré le nom de la session, il s'agit de beaucoup plus que GameplayKit … il montre comment tirer parti de nombreuses technologies introduites dans iOS 8 / OS X 10.11 / Xcode 7 pour build quelque chose ressemblant à un jeu complet: App Thinning, nouveau Caractéristiques SpriteKit, ReplayKit, et bien plus encore.