Search code examples
swiftsprite-kitgesture

How to use pinch gesture in game scene


I need your help guys. I have game scene and func which allow to move camera using panGesture. Also i need pinchGesture to zoom in and out my SKScene. I found some code here, but it lags. Can plz someone help me to improve this code? `

@objc private func didPinch(_ sender: UIPinchGestureRecognizer) {
            guard let camera = self.camera else {return}
            if sender.state == .changed {
                previousCameraScale = camera.xScale
            }
            camera.setScale(previousCameraScale * 1 / sender.scale)
            sender.scale = 1.0
        }

`


Solution

  • try this pinch code.

    //pinch -- simple version
    @objc func pinch(_ recognizer:UIPinchGestureRecognizer) {
        guard let camera = self.camera else { return } // The camera has a weak reference, so test it
        
        if recognizer.state == .changed {
            let deltaScale = (recognizer.scale - 1.0)*2
            let convertedScale = recognizer.scale - deltaScale
            let newScale = camera.xScale*convertedScale
            camera.setScale(newScale)
            
            //reset value for next time
            recognizer.scale = 1.0
        }
    }
    

    although i would recommend this slightly more complicated version which centers the pinch around the touch point. makes for a much nicer pinch in my experience.

    //pinch around touch point
    @objc func pinch(_ recognizer:UIPinchGestureRecognizer) {
        guard let camera = self.camera else { return } // The camera has a weak reference, so test it
    
        //cache location prior to scaling
        let locationInView = recognizer.location(in: self.view)
        let location = self.convertPoint(fromView: locationInView)
        
        if recognizer.state == .changed {
            let deltaScale = (recognizer.scale - 1.0)*2
            let convertedScale = recognizer.scale - deltaScale
            let newScale = camera.xScale*convertedScale
            camera.setScale(newScale)
            
            //zoom around touch point rather than center screen
            let locationAfterScale = self.convertPoint(fromView: locationInView)
            let locationDelta = location - locationAfterScale
            let newPoint = camera.position + locationDelta
            camera.position = newPoint
            
            //reset value for next time
            recognizer.scale = 1.0
        }
    }
    
    //also need these extensions to add and subtract CGPoints
    extension CGPoint { 
      static func + (a:CGPoint, b:CGPoint) -> CGPoint {
          return CGPoint(x: a.x + b.x, y: a.y + b.y)
      }   
    
      static func - (a:CGPoint, b:CGPoint) -> CGPoint {
          return CGPoint(x: a.x - b.x, y: a.y - b.y)
      }
    }