2017-03-09 136 views
4

我有一個SpriteKit場景,我有一個背景(SKSpriteNode),它是場景幀大小的兩倍。我添加了一個攝像頭,隨着用戶用手指捏住並捏住攝像頭。我有捏縮放和平移實現,但是,我需要相機不移過背景節點的邊緣。如何停止場景邊緣的SKCameraNode

我試過使用物理體和邊緣循環,但沒有奏效(除非我設置錯誤)。這裏是我現在的代碼和一些圖像來幫助傳達信息。我應該移動背景節點而不是相機嗎?

self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame) 
self.physicsBody!.categoryBitMask = SCENE_EDGE_CAT 
self.physicsWorld.contactDelegate = self 

mCamera = self.childNode(withName: "camera") as! SKCameraNode 
mCamera.physicsBody = SKPhysicsBody(edgeLoopFrom: mCamera.frame) 
mCamera.physicsBody?.collisionBitMask = self.SCENE_EDGE_CAT 
mCamera.physicsBody!.contactTestBitMask = mCamera.physicsBody!.collisionBitMask 

func panForTranslation(_ translation: CGPoint) { 
    let position = mCamera.position 
    let aNewPosition = CGPoint(x: position.x - translation.x, y: position.y - translation.y) 
    mCamera?.position = aNewPosition 
} 
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { 
    let touch = touches.first 
    let positionInScene = touch?.location(in:self) 
    let previousPosition = touch?.previousLocation(in:self) 
    let translation = CGPoint(x: (positionInScene?.x)! - (previousPosition?.x)!, y: (positionInScene?.y)! - (previousPosition?.y)!) 

    panForTranslation(translation) 
    print(mCamera.position) 
} 

場景(灰色爲背景圖片,紅色相機) enter image description here

鍋到這...

enter image description here

但我需要它停止在邊緣。 .. enter image description here

回答

2

有幾種方法可以做到這一點。

在蘋果示例遊戲DemoBots中,他們使用相機的約束來跟隨玩家。但是,如果玩家靠近屏幕邊緣,相機會停止跟隨他。

/// Constrains the camera to follow the PlayerBot without approaching the scene edges. 
private func setCameraConstraints() { 
    // Don't try to set up camera constraints if we don't yet have a camera. 
    guard let camera = camera else { return } 

    // Constrain the camera to stay a constant distance of 0 points from the player node. 
    let zeroRange = SKRange(constantValue: 0.0) 
    let playerNode = playerBot.renderComponent.node 
    let playerBotLocationConstraint = SKConstraint.distance(zeroRange, to: playerNode) 

    /* 
     Also constrain the camera to avoid it moving to the very edges of the scene. 
     First, work out the scaled size of the scene. Its scaled height will always be 
     the original height of the scene, but its scaled width will vary based on 
     the window's current aspect ratio. 
    */ 
    let scaledSize = CGSize(width: size.width * camera.xScale, height: size.height * camera.yScale) 

    /* 
     Find the root "board" node in the scene (the container node for 
     the level's background tiles). 
    */ 
    let boardNode = childNode(withName: WorldLayer.board.nodePath)! 

    /* 
     Calculate the accumulated frame of this node. 
     The accumulated frame of a node is the outer bounds of all of the node's 
     child nodes, i.e. the total size of the entire contents of the node. 
     This gives us the bounding rectangle for the level's environment. 
    */ 
    let boardContentRect = boardNode.calculateAccumulatedFrame() 

    /* 
     Work out how far within this rectangle to constrain the camera. 
     We want to stop the camera when we get within 100pts of the edge of the screen, 
     unless the level is so small that this inset would be outside of the level. 
    */ 
    let xInset = min((scaledSize.width/2) - 100.0, boardContentRect.width/2) 
    let yInset = min((scaledSize.height/2) - 100.0, boardContentRect.height/2) 

    // Use these insets to create a smaller inset rectangle within which the camera must stay. 
    let insetContentRect = boardContentRect.insetBy(dx: xInset, dy: yInset) 

    // Define an `SKRange` for each of the x and y axes to stay within the inset rectangle. 
    let xRange = SKRange(lowerLimit: insetContentRect.minX, upperLimit: insetContentRect.maxX) 
    let yRange = SKRange(lowerLimit: insetContentRect.minY, upperLimit: insetContentRect.maxY) 

    // Constrain the camera within the inset rectangle. 
    let levelEdgeConstraint = SKConstraint.positionX(xRange, y: yRange) 
    levelEdgeConstraint.referenceNode = boardNode 

    /* 
     Add both constraints to the camera. The scene edge constraint is added 
     second, so that it takes precedence over following the `PlayerBot`. 
     The result is that the camera will follow the player, unless this would mean 
     moving too close to the edge of the level. 
    */ 
    camera.constraints = [playerBotLocationConstraint, levelEdgeConstraint] 
} 

如果你不使用的限制,這是你彷彿在做,你必須手動添加一個檢查從更新停止攝像。沿着這個僞代碼的東西線

func panForTranslation(_ translation: CGPoint) { 
    guard mCamera.position < ... else { return } // Check your corner position and exit early if camera moved to far 

    ... 

} 

希望這有助於

+0

我會做第二個選項,但我已經開始嘗試,並遇到了一個問題。相機節點沒有「大小」屬性。所以我可以得到這個位置,但我無法知道左右邊緣在哪裏,而不知道節點的寬度。有沒有解決辦法? – TheValyreanGroup

+0

相機將與場景尺寸相同。因此,只需獲取場景大小,例如讓cameraSize = self.size – crashoverride777

+0

即使我改變相機的比例?這是一個地圖視圖,所以用戶捏合放大,並做到這一點,我改變相機的規模。 – TheValyreanGroup