Matt Jahnes
Matt Jahnes

Reputation: 47

Positioning Nodes At Below the Bottom of the Screen (Spritekit)

Hello I'm trying to spawn bullets at the bottom of my screen to travel upwards but the current code that I have spawns the bullets at the top of the screen. I've tried making the height negative and nothing happened. Here's the code I'm working with, thanks.

let randomBulletPosition = GKRandomDistribution(lowestValue: -300, highestValue: 300)
    let position = CGFloat(randomBulletPosition.nextInt())
    bullet.position = CGPoint(x: position, y: self.frame.size.height + bullet.size.height)

Upvotes: 4

Views: 1209

Answers (1)

Knight0fDragon
Knight0fDragon

Reputation: 16827

Some nice conversions will help you.

Now, do not do this all the time, this should be a one and done type deal, like in a lazy property.

First, we want to get the bottom of our view

let viewBottom = CGPoint(x:scene!.view!.midX,y:scene!.view!.frame.maxY)  //In a UIView, 0,0 is the top left corner, so we look to bottom middle

Second, we want to convert the position to the scene

let sceneBottom = scene!.view!.convert(viewBottom, to:scene!)

Finally we want to convert to whatever node you need it to be a part of. (This is optional if you want to place it on the scene)

let nodeBottom = scene!.convert(sceneBottom,to:node)

Code should look like this:

let viewBottom = CGPoint(x:scene!.view!.midX,y:scene!.view!.frame.maxY)  
let sceneBottom = scene!.view!.convert(viewBottom!, to:scene!)
let nodeBottom = scene!.convert(sceneBottom,to:node)

Of course, this is a little ugly.

Thankfully we have convertPoint and convert(_from:) to clean things up a little bit

let sceneBottom = scene.convertPoint(from:viewBottom)

Which means we can clean up the code to look like this:

let sceneBottom = scene.convertPoint(from:CGPoint(x:scene!.view!.midX,y:scene!.view!.frame.maxY))
let nodeBottom = node.convert(sceneBottom,from:scene!)

Then we can make it 1 line as:

let nodeBottom = node.convert(scene.convertPoint(from:CGPoint(x:scene!.view!.midX,y:scene!.view!.frame.maxY),from:scene!)

As long as the node is available to the class, we can make it lazy:

lazy var nodeBottom = self.node.convert(self.scene!.convertPoint(CGPoint(x:self.scene!.view!.midX,y:self.scene!.view!.frame.maxY),from:self.scene!)

This means the first time you call nodeBottom, it will do these calculations for you and store it into memory. Everytime after that, the number is preserved.

Now that you know where the bottom of the screen is in the coordinate system you want to use, you can assign the x value to whatever your random is producing, and you can subtract the (node.height * (1 - node.anchorPoint.y)) to fully hide your node from the scene.

Now keep in mind, if your node moves between various parents, this lazy will not update.

Also note, I unwrapped all optionals with !, you may want to be using ? and checking if it exists first.

Upvotes: 1

Related Questions