3
votes

I have a ball node and a hole node. I want to detect when will the ball fall into the hold.

Currently I'm using didBeginContact, but it only gives me the distance of two nodes at the begin of contact, in which case the ball won't necessarily fall into the hole (it falls when distance between two centers < hole's radius).

Is there a way I can track the position of the ball after the contact had happened?

4

4 Answers

1
votes

You can add invisible SKSpriteNodes and track when the ball touches them. You would have node1 just in top of the hole (a zone that the ball MUST go through - or touch - before entering the hole) before going into the hole, and node2 just after the hole (again, a zone that the ball MUST go through - or touch - after entering the hole).

enter image description here

If the ball touches node1 but not node2, you know it was almost going into the hole but then it didn't. If the ball touches node2, you know the ball is trying to go through the hole from the bottom part.

0
votes

I guess you can make a physics body of a hole a lot smaller. That way, when contact occurs, you will be sure that ball can fall into a hole. Take a look at this picture (second example):

enter image description here

On top of that as an additional idea, when contact is detected, you can let ball to move little more, and then scale it down to make impression of falling.

0
votes

There is no need to test for a contact between the ball and the hole, since it doesn't tell you if the objective was completed. Alternatively, you can simply add a check in didSimulatePhysics to see if the ball is sufficiently close to the hole before starting the falling animation sequence. For example,

override func didSimulatePhysics() {
    let dx = ball.position.x - hole.position.x
    let dy = ball.position.y - hole.position.y
    let distance = sqrt(dx*dx+dy*dy)
    if (distance < hole.size.width / 2.0) {
        // Start falling animation sequence

    }
}

Optionally, you can test if the ball is moving fast enough to skip over the hole by

override func didSimulatePhysics() {
    let dx = ball.position.x - hole.position.x
    let dy = ball.position.y - hole.position.y
    let distance = sqrt(dx*dx+dy*dy)
    if (distance < hole.size.width / 2.0) {
        // Check if the ball is moving fast
        let vx = ball.physicsBody!.velocity.dx
        let vy = ball.physicsBody!.velocity.dy
        let speed = sqrt(vx*vx+vy*vy)
        if (speed < minSpeedToSkipOverHole) {
            // Start falling animation sequence
        }    
    }
}
0
votes

This problem is solved by this: I maintain a possible_falling_list of all contacted holes for each ball and use another timer to frequently check if a ball is falling into any hole. Since the list is small for each ball, the performance is not an issue.