iOS - Spritekit - How to Calculate the Distance Between Two Nodes

ios - Spritekit - How to calculate the distance between two nodes?

Here's a function that will do it for you. This is from an Apple's Adventure example code:

CGFloat SDistanceBetweenPoints(CGPoint first, CGPoint second) {
return hypotf(second.x - first.x, second.y - first.y);
}

To call this function from your code:

CGFloat distance = SDistanceBetweenPoints(nodeA.position, nodeB.position);

How to get the distance between two SKSpriteNode objects for use in Potential Fields algorithm?

Larry might be on to something, as your use of centerSourceNode.x += sourceNode.size.width/2 indicates that your nodes have an anchorPoint of (0,0) rather than the default (0.5, 0.5).

With the default value the position of the sprite is the position of its center in the parent-node, meaning you don't need to consider anything but the two nodes' positions.

As I mentioned in my comment this also leads us to the rather neat possibility of solving it with an extension to CGPoint:

extension CGPoint {
func distanceFromCGPoint(point:CGPoint)->CGFloat{
return sqrt(pow(self.x - point.x,2) + pow(self.y - point.y,2))
}
}

Then, wherever you need this you can get the distance with a simple call to this:

let distance = spriteA.position.distanceFromCGPoint(spriteB.position)

How to set up a distance between two nodes using SKConstraint?

SKConstraint's distance class method takes an SKRange as its first argument not a closed range (e.g., 10...50). For an example,

Swift 2

let range = SKRange(lowerLimit:50, upperLimit:100)
let constraint = SKConstraint.distance(range, toNode:cat)
mouse.constraints = [constraint]

Swift 3

let range = SKRange(lowerLimit:50, upperLimit:100)
let constraint = SKConstraint.distance(range, to: cat)
mouse.constraints = [constraint]

Maintaining a constant distance between two sprites

You can use the SKConstraint class to maintain the distance between the two nodes.
For example :

let node1 = SKSpriteNode(color: UIColor.redColor(), size: CGSizeMake(20, 10))
node1.position = CGPointMake(self.size.width/2, self.size.height/2)
self.addChild(node1)

let node2 = SKSpriteNode(color: UIColor.blueColor(), size: CGSizeMake(10, 20))
node2.position = CGPointMake(self.size.width/2, self.size.height/2 - 50)
self.addChild(node2)

// The upper and lower limit is set to 50 to maintain a constant distance.
let constraint = SKConstraint.distance(SKRange(lowerLimit: 50, upperLimit: 50), toNode : node1)
node2.constraints = [constraint]

node1.runAction(SKAction.moveToY(100, duration: 2.0))

In Objective C

SKSpriteNode *node1 = [[SKSpriteNode alloc] initWithColor:[UIColor redColor]
size:CGSizeMake(20, 10)];
node1.position = CGPointMake(self.size.width/2, self.size.height/2);
[self addChild:node1];

SKSpriteNode *node2 = [[SKSpriteNode alloc] initWithColor:[UIColor redColor]
size:CGSizeMake(10, 20)];
node2.position = CGPointMake(self.size.width/2, self.size.height/2 - 50);
[self addChild:node2];

// The upper and lower limit is set to 50 to maintain a constant distance.
SKConstraint *constraint = [SKConstraint distance:[SKRange rangeWithLowerLimit:50 upperLimit:50] toNode:node1];
node2.constraints = @[constraint];

[node1 runAction:[SKAction moveToY:100 duration:2.0]];

SpriteKit - getting closest nodes

As of iOS 10, you can use the Spatial Partitioning features of GampelayKit. In 2D either GKQuadtree or GKRTree depending on your needs.

From the docs:

Quadtrees and R-trees have different performance tradeoffs for different tasks: quadtrees can be faster when objects are more uniformly distributed in space or when their positions change frequently, and R-trees can be faster when searching for all objects in a given region.

Add your enemies to the tree:

    let minX = Float(enemy.frame.minX)
let minY = Float(enemy.frame.minY)
let maxX = Float(enemy.frame.maxX)
let maxY = Float(enemy.frame.maxY)

var enemiesRTree = GKRTree(maxNumberOfChildren: 3)
enemiesRTree.addElement(enemy,
boundingRectMin: vector2(minX, minY),
boundingRectMax: vector2(maxX, maxY),
splitStrategy: GKRTreeSplitStrategy.linear)

Then you can search by area.

    let enemiesInProximity = enemiesRTree.elements(
inBoundingRectMin: vector2(0, 0),
rectMax: vector2(100, 100))

You can then create the search area e.g. relative to the player's position.

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

To determine if one or more nodes in the scene are within a fixed distance of a touch event, 1) compute the distance between the touch and each node and 2) compare if that distance is less than or equal to a constant. Here's an example of how to do that:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
if let touch = touches.first {
let location = touch.locationInNode(self)
let nodes = nodesNearPoint(self, point:location, maxDistance: 30)
if nodes.count > 0 {
print("node is near touch point")
}
}
}

// Returns an array of all SKNode objects in the subtree that near the specified point.
// If no nodes are near the point, an empty array is returned.
func nodesNearPoint(container:SKNode, point:CGPoint, maxDistance:CGFloat) -> [SKNode] {
var array = [SKNode]()
for node in container.children {
// Only test sprite nodes (optional)
if node is SKSpriteNode {
let dx = point.x - node.position.x
let dy = point.y - node.position.y

let distance = sqrt(dx*dx + dy*dy)
if (distance <= maxDistance) {
array.append(node)
}
}
}
return array
}

Get the closest SpriteKit node in a certain direction

I assume that your sprite has some radius, and crossing my line denotes that distance from line to sprite center is smaller than radius.

Let playur point is P, direction angle is Fi, so unit direction vector is

dx = cos(fi)
dy = sin(fi)

and line equation is

 - x * dy + y * dx + q = 0
where
q = dy * p.x - dx * p.y

To find distance from sprite center to this line, substitute x and y with center.x and center.y

dist = - center.x * dy + center.y * dx  + q

So walk through sprite list, check whether sprite is intersected (dist < spriteRadius) and choose the closest from intersected sprites



Related Topics



Leave a reply



Submit