1

Im wondering how to unhide my node, but once unhidden appear in a different place to the original.

let x3 = rect.origin.x + CGFloat(arc4random()) % rect.size.width
let y3 = rect.origin.y + CGFloat(arc4random()) % rect.size.height
let randomPoint3 = CGPointMake(x3, y3)
self.greencircle.position = randomPoint3
self.addChild(greencircle)
let wait3 = SKAction.waitForDuration(2.0)
greencircle.hidden = true
let wait23 = SKAction.waitForDuration(1.0)
greencircle.hidden = false

So once the 'green circle' is unhidden how do you guarantee to spawn in a different location to the previous and to repeat?

MattB
  • 13
  • 4
  • Is this what you are trying to do : hide node, change its position to some random location, show node? And repeat that sequence certain number of times? Also, do want to do this for just green circle node or with multiple nodes? – Whirlwind Nov 06 '15 at 19:52
  • Yes, however re-spawn randomly within the rect which is rect = CGRectMake(8, 293, 165, 218) is what I'm trying to do but i also have different nodes within that location also, would it be easier combining them together? – MattB Nov 06 '15 at 20:04
  • Not sure if I understand the second part of your comment, but I wrote a simple example for you which will give you basic idea how you can hide, move to random point and unhide the node. Also, I've linked a nice post about "spawning nodes at random positions, but without overlapping" You might find it useful. Good luck and happy hacking ! :) – Whirlwind Nov 06 '15 at 22:43

1 Answers1

0

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 : random spawning

Community
  • 1
  • 1
Whirlwind
  • 14,286
  • 11
  • 68
  • 157
  • Thanyyou so much for this just one thing though for (weakSelf!.rectangle.calculateAccumulatedFrame() says it doesn't have a member named rectangle, so do i have to make the rectangle equal something? – MattB Nov 07 '15 at 10:59
  • @MattB Checkout the edit :) I've added an example to show you where rectangle is defined (its a property of a GameScene). Also I've changed randomPointWithinRectangle method. If you have additional questions, feel free to ask. As I said, this works at my side, but based on your Swift version (if you are up to date) you will probably have to change the code slightly. – Whirlwind Nov 07 '15 at 13:06
  • @MattB The code from touchesMoved which I use to move a rectangle is left intentionally because its not relevant to your original question. – Whirlwind Nov 07 '15 at 13:55