Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

An efficient way to find all SKNodes within a certain distance from a given point?

If I want to know which node or nodes cover certain point of the scene I can do either scene.nodeAtPoint(point) or scene.nodesAtPoint(point). Is there an efficient way to do something similar with a circle? That is to be able to find all nodes that have their positions within certain distance from a given point.

I need this to be able to handle user taps better. The scene is rather scarce (not much user-active sprites on it), so there is no need to demand the user to be very precise with tapping. I want to use some sort a tolerance around the coordinates of the tap and detect the node that is just close enough to tap location.

The best idea that I have so far is to do nodeAtPoint() several times: at the location of the tap, and then at various offsets from it (e.g. up, up-right, rigth, ..., up-left).

like image 533
0x416e746f6e Avatar asked Dec 26 '15 18:12

0x416e746f6e


1 Answers

Distance

First of all we need an extension to find the distance between 2 CGPoint(s)

extension CGPoint {
    func distance(point: CGPoint) -> CGFloat {
        return CGFloat(hypotf(Float(point.x - self.x), Float(point.y - self.y)))
    }
}

The closest child

Now we can add an extension to SKScene to find the child closest to a given point and within a maxDistance.

extension SKScene {
    func closestChild(point: CGPoint, maxDistance: CGFloat) -> SKNode? {
        return self
            .children
            .filter { $0.position.distance(point) <= maxDistance }
            .minElement { $0.0.position.distance(point) < $0.1.position.distance(point) }
    }
}

Time

The computational complexity of the extension above is O(n) where n is the number of direct children of the scene.

like image 153
Luca Angeletti Avatar answered Nov 23 '22 05:11

Luca Angeletti