Search code examples
swiftsprite-kituitapgesturerecognizergamekittouchesbegan

UITapGesture and TouchesBegan are producing different locations in view


I'm using SKTileMaps and a CameraNode as well as GameplayKit and SpriteKit

The code I want to work is incorrectly finding a location in the "view"

func handleTapFrom(_ sender: UITapGestureRecognizer)
{
    let location = sender.location(in: self.view)
    if (map.contains(location))
    {
        let tRow = map.tileRowIndex(fromPosition: location)
        let tColumn = map.tileColumnIndex(fromPosition: location)
        let movePosition = map.centerOfTile(atColumn: tColumn, row: tRow)
        let moveAction = SKAction.move(to: movePosition, duration:1.0)
        cam.run(moveAction)
    }

}    

and the code that is working correctly is finding locations in self (rather than self.view) and this is correct

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) 
{
    let firstTouch = touches.first?.location(in: self)
    if (map.contains(firstTouch!))
    {
        let tRow = map.tileRowIndex(fromPosition: firstTouch!)
        let tColumn = map.tileColumnIndex(fromPosition: firstTouch!)
        let movePosition = map.centerOfTile(atColumn: tColumn, row: tRow)
        let moveAction = SKAction.move(to: movePosition, duration:1.0)
        cam.run(moveAction)
    }
}

The columns and rows are correct based on the location, the problem I am having is that the locations (xfloat, yfloat) are different between the two functions even when the touch is at the same location

These two bits of code are all in the class GameScene, but I cannot figure out why they have different locations? And how to fix the tap gesture so that the locations it finds are the same as those found in touchesBegan.

Sorry if this is confusing or unintelligible. I welcome an opportunity to clarify.


Solution

  • In your handleTapFrom function the location should come from convertPoint.

    func handleTapFrom(_ sender: UITapGestureRecognizer) {
        if sender.state != .ended {
            return
        }
    
        let location = sender.location(in: sender.view!)
        let targetLocation = self.convertPoint(fromView: location)
    
        if map.contains(targetLocation) {
            // Your code here
        }
    }