Zooming and scrolling in SpriteKit

前端 未结 5 485
一整个雨季
一整个雨季 2020-12-02 17:43

I am new to SpriteKit. I need to display an image via UIImageView OR SpriteNode (it is a background image for a game). However, I need the user to be able to zoom in to the

5条回答
  •  悲&欢浪女
    2020-12-02 18:16

    If you are using an SKCameraNode you can calculate the difference between two touches to define zooming and panning at once.

    • Define an SKCameraNode for your SKView
    • Check if there are two touches
    • If so, calculate the difference between the previous touches and current touches
    • Tell the camera to scale by that much
    • Pan by the camera by either the average of the two points, or the first one (if there's only one)

    Result should be something like this. Note that I used the event?.allTouches instead of the received set, if one finger doesn't move between touches, it's not in the touches set, which would cause a pan where a user would expect a zoom.

    let cameraNode = SKCameraNode()
    
    override func didMove(to view: SKView) {
    
        cameraNode.position = CGPoint(x: size.width / 2, y: size.height / 2)
        addChild(cameraNode)
        camera = cameraNode
    }
    
    override func touchesMoved(_ touch: Set, with event: UIEvent?) {
    
        guard let touches = event?.allTouches else {
            return
        }
    
        let arr = Array(touches)
        guard let touch = arr.first else {
            return
        }
    
        var positionInScene = touch.location(in: self)
        var previousPosition = touch.previousLocation(in: self)
    
        if touches.count > 1 {
    
            let touch2 = arr[1]
    
            let positionInScene2 = touch2.location(in: self)
            let previousPosition2 = touch2.previousLocation(in: self)
    
            let oldDistance = distance(previousPosition, previousPosition2)
            let newDistance = distance(positionInScene, positionInScene2)
    
            let diff = (oldDistance / newDistance)
    
            if diff.isNormal && diff != 1 {
    
                let scaleAction = SKAction.scale(by: diff, duration: 0)
                cameraNode.run(scaleAction)
            }
    
            previousPosition = average(previousPosition, previousPosition2)
            positionInScene = average(positionInScene, positionInScene2)
        }
    
        let translation = CGPoint(x: positionInScene.x - previousPosition.x, y: positionInScene.y - previousPosition.y)
    
        let panAction = SKAction.moveBy(x: -translation.x, y: -translation.y, duration: 0)
        cameraNode.run(panAction)
    }
    
    func average(_ a: CGPoint, _ b: CGPoint) -> CGPoint {
    
        return CGPoint(x: (a.x + b.x) / 2, y: (a.y + b.y) / 2)
    }
    
    func distance(_ a: CGPoint, _ b: CGPoint) -> CGFloat {
    
        let xDist = a.x - b.x
        let yDist = a.y - b.y
        return CGFloat(sqrt((xDist * xDist) + (yDist * yDist)))
    }
    

提交回复
热议问题