To spawn a node at random point within given rectangle you can use this method(s):
func randomBetweenNumbers(firstNum: CGFloat, secondNum: CGFloat) -> CGFloat{
return CGFloat(arc4random()) / CGFloat(UINT32_MAX) * abs(firstNum - secondNum) + min(firstNum, secondNum)
}
func randomPointWithinRectangle(rectangle: CGRect) -> CGPoint {
var point : CGPoint = CGPoint()
point.x = randomBetweenNumbers(rectangle.origin.x + sprite.size.width / 2, secondNum: rectangle.origin.x + rectangle.size.width - sprite.size.width / 2)
point.y = randomBetweenNumbers(rectangle.origin.y + sprite.size.width / 2, secondNum: rectangle.origin.y + rectangle.size.height - sprite.size.width / 2)
return point
}
Next thing is hiding/unhiding part... Note that I am currently on outdated version of Swift :D, and what works for me, might not work for you. But logic is the same.
To achieve that, you can use SKAction sequence, like this:
func startSpawningSprites(){
let wait = SKAction.waitForDuration(0.5)
let fadeOut = SKAction.fadeOutWithDuration(0.5)
let fadeIn = SKAction.fadeInWithDuration(0.3)
//Use weak reference to self to prevent retain cycle. in Swift 2.0 you should use appropriate syntax.
weak var weakSelf = self
let changePosition = SKAction.runBlock({
weakSelf!.sprite.position = weakSelf!.randomPointWithinRectangle(weakSelf!.rectangle.calculateAccumulatedFrame())
})
let sequence = SKAction.sequence([wait, fadeOut, changePosition, wait, fadeIn])
sprite.runAction(SKAction.repeatAction(sequence, count:10))
}
Here, the code is pretty much straight forward and it does what I stated above(hide,move and unhide the node). A rectangle variable is defined as a property just for easier debugging.
About other part of your question..I am not sure if I understand it...But I can give it a try. If you care about overlapping between nodes and you want to avoid it, then you have to check if there is a node at given point (nodeAtPoint method might be useful). Theoretically this can be resource consuming. If interested why, read more here.
EDIT:
To answer the question from your comment :
Variables sprite and rectangle are defined as properties of a GameScene:
class GameScene:SKScene{
let sprite = SKSpriteNode(color: SKColor.redColor(), size: CGSize(width: 30, height: 30))
//just for debugging purposes
let rectangle = SKSpriteNode(color: SKColor.orangeColor(), size: CGSize(width: 150, height: 150))
override func didMoveToView(view: SKView) {
setupScene()
startSpawningSprites()
}
func setupScene(){
sprite.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
sprite.zPosition = 4
sprite.name = "sprite" //later on, you can access or enumerate node(s) by name
addChild(sprite)
rectangle.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
rectangle.alpha = 0.5
rectangle.zPosition = 3
rectangle.name = "rectangle"
addChild(rectangle)
}
func startSpawningSprites(){
//...
}
}
The end result is intended to look like this :
