SpriteKit - Mouse Snaps to Center On Sprite Drag

2020-08-01 00:35发布

问题:

I'm trying to create an iOS game and I have it so that when the item is touched and moved it is dragged. When it is dragged the mouse is snapped to the center of the sprite. How could I make it so that this wouldn't happen?

Here is an example of what is happening.

Here are the functions dealing with touch input

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {

    var papers = 0

    for touch in (touches as! Set<UITouch>) {
        let location = touch.locationInNode(self)
        let touchedNode = nodeAtPoint(location)

        if ((touchedNode.name?.contains("paper")) != nil) {

            touchedNode.position = location
            touchedNode.position.x = CGRectGetMidX(self.frame)
        }
    }
}
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
        for touch: AnyObject in touches {
            let location = touch.locationInNode(self)
            let touchedNode = nodeAtPoint(location)

            if ((touchedNode.name?.contains("paper")) != nil) {

                touchedNode.position = location
                touchedNode.position.x = CGRectGetMidX(self.frame)
            }
        }
    }

override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
    for touch: AnyObject in touches {
        let location = touch.locationInNode(self)
        let touchedNode = nodeAtPoint(location)
        if ((touchedNode.name?.contains("paper")) != nil) {
            touchedNode.zPosition = 0
            touchedNode.position.x = CGRectGetMidX(self.frame)
        }
    }
}

P.S. contains is an extension off of the String class to check if a substring is in a string

Thanks in advance!

回答1:

It's fairly straightforward to drag a sprite from the touch location instead of from the center of the sprite. To do this, calculate and store the difference (i.e., offset) between the touch location and the center of the sprite. Then, in touchesMoved, set the sprite's new position to the touch location plus the offset.

You can optionally overload the + and - operators to simplify adding and subtracting CGPoints. Define this outside of the GameScene class:

func - (left:CGPoint,right:CGPoint) -> CGPoint {
    return CGPoint(x: right.x-left.x, y: right.y-left.y)
}

func + (left:CGPoint,right:CGPoint) -> CGPoint {
    return CGPoint(x: right.x+left.x, y: right.y+left.y)
}

In GameScene, define the following instance variable

var offset:CGPoint?

and then in touchesBegan, replace

touchedNode.position = location

with

offset = location - touchedNode.position

and in touchesMoved, replace

touchedNode.position = location

with

if let offset = self.offset {
    touchedNode.position = location + offset
}

I generalized the solution to offset the sprite's position in both the x and y dimensions. In your app, you can simply offset the sprite's y position since x is ignored.



回答2:

You don't need touchesBegan and touchesEnded for this. You can use just touchesMoved:

for touch: AnyObject in touches {
        let location = touch.locationInNode(self)
        let touchedNode = nodeAtPoint(location)
        let previousPosition = touch.previousLocationInNode(self)

        if (touchedNode.name == "paper") {

            var translation:CGPoint = CGPoint(x: location.x - previousPosition.x , y: location.y - previousPosition.y )

            touchedNode.position = CGPoint(x: touchedNode.position.x , y: touchedNode.position.y + translation.y)


        }
    }

The idea is to calculate translation. You can read more about this solution here. For future readers Obj-C solution on StackOverflow can be found on this link.