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
Get Index or Tag Value from Imageview Tap Gesture
Secure Contents in Documents Directory
How to Evaluate the String Equation in iOS
Game Engine Collison Bitmask... Why 0X01 etc
Uploading Image with iOS App to Server File Size Is Too Large
Executefetchrequest Throw Fatal Error: Nsarray Element Failed to Match the Swift Array Element Type
Using Wcsession with More Than One Viewcontroller
How to Change Uibutton Image After Clicking in Swift
About "Slcomposeviewcontroller" in iOS 11 Beta
Dequeuereusablecellwithidentifier:Forindexpath: VS Dequeuereusablecellwithidentifier:
How to Access User Defined Runtime Attribute from the 'Sender' Object
Best Method to Store Data for an iOS App
Custom Font Not Working in Wkwebview Swift
How to Properly Send an Image to Cloudkit as Ckasset
Changing Iphone's Date and Time
Get Created Date and Last Login Date from Firuser with Firebase 3