Search code examples
iosswiftsprite-kitphysicsskphysicsbody

Move SpriteNode in direction of a swipe at a preset speed


So basically I have the coin object, and I want to launch it across the screen. I have the following code which runs some calculations on the swipe, but not sure what is relevant for my current situation:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    touching = true

    let touch = touches.first
    let loc = touch?.locationInNode(self)
    if coin.containsPoint(loc!){
        touchPoint = loc!
        touchTime = (touch?.timestamp)!
    }
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    touching = false

    let touch = touches.first
    let loc = touch?.locationInNode(self)
    var xDiff = (loc?.x)! - touchPoint.x
    var yDiff = (loc?.y)! - touchPoint.y
    let distance = sqrt(xDiff * xDiff + yDiff * yDiff)
}

I want the coin to be essentially thrown in the direction of the swipe, but I want it to reach a certain y-coordinate on the screen each time, before falling back down due to gravity. So I guess I need to somehow calculate the perfect speed each time to make it reach that y-point, and then push the coin object in the swipe direction at that speed?

Any help much appreciated! I'm online for the next few hours, so ask for more info and I'll be able to get back to you pretty quick.


Solution

  • It depends if you want the coin to be interacting with other physics bodies afterward. You have attached several "physics" tags to the question so I assume you want that :)

    I'd go for a mathematics-based approach indeed. So basically you are just getting a direction from the swipe. The speed itself is dependent on the gravity that's affecting the coin.

    You can separate the speed vector in the vertical and horizontal component. The vertical distance to cover is let verticalDistance = targetHeight - coin.position.y. The coin has to have zero vertical speed at the highest point, and we know that during the animation it decelerates with a constant -9.81 pt/s*s (off the top of my head).

    So the speed graph looks like this:

    enter image description here

    with formula f(x) = -9.81 * x + v where v is the vertical starting speed we are solving for. Algebra tells us that f(x) intersects with the x-axis with x-value v / 9.81. The total distance covered up until the point where f(x) intersects with the x-axis is equal to the surface area of the triangle under f(x). This triangle's surface is 1/2 * v/9.81 * v (which is 1/2 * width * height). Since you know what this distance should be (verticalDistance from previous paragraph), algebra dictates v = sqrt(2 * 9.81 * d). Now you know you starting vertical speed, based on the height the coin has to travel!

    Since you know the coins angle (dictated by user's swipe) and the vertical speed, you can calculate the horizontal speed. I'm leaving that to you ;) Note that we are of course ignoring drag / friction which could impact the coin speed. Also my algebra might be rusty.

    As a side note
    I would replace let touch = touches.first with

    guard let touch = touches.first else {
        return
    }
    

    In this way, touch is a non-optional.