spritekit swift sprite-kit

swift - spritekit - skview



Cómo detener un SKCameraNode al borde de una escena (1)

Tengo una escena de SpriteKit donde tengo un fondo (SKSpriteNode) que es 2 veces el tamaño del marco de la escena. Agregué una cámara que se mueve mientras el usuario sacude y pellizca con los dedos. Tengo un pellizco para ampliar y una panorámica implementada, sin embargo, necesito que la cámara no se mueva más allá de los bordes del nodo de fondo.

Intenté usar un cuerpo de física y un bucle de borde, pero no funcionó (a menos que lo haya configurado mal). Aquí está el código que tengo actualmente y algunas imágenes para ayudar a transmitir el mensaje. ¿Debo mover el nodo de fondo en lugar de la cámara?

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

Escena (gris es imagen de fondo, rojo es cámara)

Pase a esto ...

Pero necesito que se detenga en el borde ...


Hay algunas maneras en que puedes hacer esto.

En el juego de ejemplo de Manzanas DemoBots, usan restricciones para que la cámara siga al jugador. Sin embargo, si los jugadores se acercan al borde de la pantalla, la cámara deja de seguirlo.

/// 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] }

Si no usa restricciones, que es lo que parece que está haciendo, tendrá que agregar una verificación manualmente para evitar que la cámara se actualice. Algo en la línea de este pseudo código

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

Espero que esto ayude