How to stop SKCameraNode at the edge of the scene

I have a SpriteKit scene where I have a background (SKSpriteNode) whose size is 2x the size of the scene. I added a camera that moves when the user clicks his fingers and holds his fingers. I have a pinch to zoom and pan, however I need a camera so that it does not move past the edges of the node background.

I tried using the physical body and the contour of the ribs, but this did not work (unless I configured it incorrectly). Here is the code I have and some images to help convey the message. Should I move the background node instead of the camera?

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

Scene (gray - background image, red - camera) enter image description here

Fits this ...

enter image description here

But I need him to stop at the edge ... enter image description here

+4
1

.

"" 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 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 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 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

    ...

}

,

+4

Source: https://habr.com/ru/post/1671943/


All Articles