Add nodes at random without overlapping

I am trying to add 20 nodes at random locations on the screen without any of the nodes overlapping. Ive got the adding of the nodes at random locations part but I sill get some that overlap. What I have done so far is: I would be greatful for a point in the right dirrection.


while i < 20 {

let bubbleSize = self.frame.width / 12

let bubble = SKShapeNode(circleOfRadius: bubbleSize)

let widthL = -self.frame.size.width / 2 + bubble.frame.size.width / 2 /

let widthH = self.frame.size.width / 2 - bubble.frame.size.width / 2 /

let heightL = -self.frame.size.height / 2 + bubble.frame.size.height / 2 /

let heightH = self.frame.size.height / 2 - bubble.frame.size.height / 2 /

var randWidth = randomNumber(range: widthL..<widthH)

var randHeight = randomNumber(range: heightL..<heightH)


bubble.fillColor = SKColor.cyan

bubble.position = CGPoint(x: randWidth, y: randHeight)


self.addChild(bubble)

}


func randomNumber(range: Range<CGFloat>) -> CGFloat {

//function that gives a random number of a range of CGFloats entered

let min = range.lowerBound

let max = range.upperBound

return CGFloat(arc4random_uniform(UInt32(CGFloat(max - min)))) + min

}

Replies

Technically, your problem can't be solved. If the shapes are at truly random locations, then they may overlap. If you prevent them from overlapping, they are not at random locations.


One simple alternative would be to divide your scene into a grid whose elements are each big enough for a shape, and choose a grid element at random.


A more subtle approach would be to do it sequentially, a bit like dealing cards. Start by dividing your scene into a grid, where the grid elements are somewhat smaller than the shapes. (How much smaller depends on the relatives sizes of the scene and the shapes, and how much execution time you want to spend on this .) Start with a set of "available" grid elements — those that haven't been used yet (i.e. all of them)


Then, for each shape:


1. Eliminate any grid elements where placing the shape (i.e. the shape center) in the element would overlap grid elements not in the "available" set, making the set a bit smaller. (For the first shape, this would eliminate elements near the edges of the screen, assuming you want to keep the shapes fully visible.)


2. Pick a random grid element from the remaining "available" set. That's the part that's like dealing a card.


Repeat until all shapes are placed, or until there's nothing left in the "available" set (which is an error condition). Note that you could place each shape's center in the center of its chosen grid element, or randomly within the element. Your strategy would affect how you code the elimination process in step 1.


A different kind of solution would be to use the physics engine. Give each of your shapes a physics body, put them in the scene, then "shake" the scene somehow by applying randomized physical effects (impulses, fields, whatever) to it, and finally grab the shape positions at some time later.

I'd vote for the physics body solution too. The body alone should prevent them from occupying the same space. So you might not need to add any kind of physics field. Just add them randomly like you already are, and any two close to each other should separate.