2016-02-01 8 views
5

so dass ich ein Basis-Spiel-Setup haben, die unten in der bitbucket Link zu finden ist:Spann Kamera um den Hintergrund einer Szene in SpriteKit

Game link

Ich bin derzeit eine harte Zeit zu verstehen, wie zu übersetze den Kameraknoten in Relation zum Layout der Szene.

Ziel ist es, dass die Kamera dem Player bis zum Erreichen einer durch die Größe der Szene definierten Eckgrenze folgt. In diesem speziellen Testszenario Setup ist die Szene 1000x1000 in der Größe mit einer Kamera Skala von 1

Der folgenden Code verwendet wird, um die Position der Kamera zu ändern, wenn eine neue Position gesetzt, um den Charakter zu folgen:

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

    } 

Es gibt Hardcore-Werte, die derzeit der erforderlichen Szenengröße entsprechen, und ich bin mir nicht sicher, wie ich diese Ergebnisse über die Skala erhalten kann. Die Skala ist standardmäßig:

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

Ohne das Wissen, zu wissen, gibt es eine Übersetzung in der Skala, standardmäßig würde ich die Grenzen erwartet largestSceneDimensionXValue sein - cameraSize.width/2 largestSceneDimensionYValue - cameraSize.height/2

Als High-Level-Beispiel. Kann mir jemand helfen, diese Übersetzung zu bekommen?

Insgesamt ist die Szene wie die folgende in allen Ecken aussehen sollte:

anti goal

Antwort

1

Ich habe nicht den Code verwenden: goal

VS den schwarzen Hintergrund Überlauf in der Kamera als solche mit . Ich habe ein Beispielprojekt gemacht und das funktioniert.

enter image description here

heren mein 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() 
    } 
} 

dies das gleiche Bild ist ich als meine "Welt" verwenden http://i.imgur.com/XhZbh8q.jpg

+0

Dies ist sehr ähnlich zu meinem ersten Ansatz, der nicht funktioniert, wenn die Kamera zurück und andere Bedingungen skaliert. Der Hauptgrund, warum ich den Code oben angehängt habe, ist das Referenzszenario. Wenn Sie das oben genannte in den Code, der im Repo gepostet wird, arbeiten können, dann sollte es perfekt sein, aber ich bin 100% positiv, wird es nicht. Die Kamera-Skalierung sollte 0,44 sein, aber ich habe alles normalisiert, um herauszufinden, woher die Werte kommen. – TheCodingArt

+0

Beachten Sie, dass die Breite der Szene nicht mit der Breite der Kamera übereinstimmt. – TheCodingArt

+0

ich spielte herum mit Ihrem Code und es fing an, mein eigenes Projekt zu werden lol .. theres wirklich eine Menge gehen dort .. wenn ich Sie war, könnte ich ein neues Beispielprojekt beginnen, das jedes Element der Kompliziertheit addiert (cameraScale .. usw.) nacheinander, bis Sie einen einfacheren Weg finden, das Problem zu lösen. – hamobi

2

Anwendungen wie diese sind genau das, was SKConstraint für ist.

Sie können eine Demo dieser genauen Funktion sehen - eine Kamera so beschränken, dass sie dem Player folgt, aber nicht zu viel freien Platz um den Rand des Levels zeigt - in der WWDC15-Sitzung Deeper into GameplayKit with DemoBots. * (Der Link sollte es in der Rede auf etwa 7.27 springen, wo die Diskussion über diese Funktion beginnt)

der Kern von dem, was in dem Video, mit einigen Schnipseln aus dem DemoBots Beispielcode:.

  1. Verwenden Sie ein Abstand Einschränkung, um die Kamera auf dem Player zentriert zu halten (automatisch , ohne camera.position direkt auf jede update() setzen zu müssen).

    // 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. Verwenden einer Position constraint die Kamera innerhalb eines bestimmten Bereichs des Niveaus der Kante zu halten. Berechne diesen Bereich, indem du den Rahmen der Ebene nimmst und den Abstand zwischen der Kamera und der Kante der Ebene einnimmst.

    // 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. beide Einschränkungen auf Ihre SKCameraNode Nehmen.

    camera.constraints = [playerBotLocationConstraint, levelEdgeConstraint] 
    

Für einen tieferen Blick, download Apple's DemoBots sample code project, die eine Menge von Kommentaren und Code-Unterstützung, die ich von dem oben genannten Schnipsel getrimmt diesen Beitrag um zu verhindern, übermäßig lange zu bekommen. Alles für die Kameraeinschränkung ist in func setCameraConstraints() in LevelScene.swift.

* Trotz des Sessionnamens ist es viel mehr als nur GameplayKit ... es zeigt, wie man viele der in iOS 8/OS X 10.11/Xcode 7 eingeführten Technologien nutzt, um etwas zu erschaffen, das einem kompletten Spiel ähnelt : App-Ausdünnung, neue SpriteKit-Funktionen, ReplayKit und vieles mehr.

+0

Sie vermissen den Punkt der Frage, ja das ist eine Hauptanwendung für eine Einschränkung, aber der allgemeine Offset muss noch berechnet und bekannt werden, worauf die obige Frage eine Antwort zu erhalten versucht. – TheCodingArt

+0

* Wenn Ihr Level groß genug ist und die Kamera niemals skaliert oder rotiert, kann Ihr Inset einfach die Hälfte der Breite/Höhe des Bildschirms betragen. * Wenn Ihr Level immer kleiner als der Gerätebildschirm ist, wird ein konstanter halber Bildschirmgröße eingefügt Vom Level-Rahmen ist alles was Sie brauchen. – rickster

+0

Diese Bedingungen gelten nicht für die obige Beispielanwendung und ich benötige etwas, das mit der Kamera skaliert werden kann. – TheCodingArt

Verwandte Themen