Positioning shape at the edge of the screen - swift

Given a PlaygroundBook page, how can you position a SpriteKit node to the right edge of the screen of the liveView so it "snaps" there?
So far I've tried to position the node like so:
// Context: class _: SKScene
// myNode.frame.size == CGSize(width: self.frame.width / 4, height: self.frame.height)
myNode.position = CGPoint(x: self.frame.maxX - myNode.frame.size.width / 2, y: self.frame.midY)
If I were to position the node at CGPoint(x: self.frame.maxX, y: self.frame.midY), I would expect its center to be right at the right edge of the screen, cropping out half of the node: that doesn't happen, the node gets placed someplace where it isn't visible at all.
Additionally:
the node positions right in the middle if I were to use frame.midX as the x coordinate
the node positions at the bottom-left corner of the screen if I were to use (0, 0) as the position.
What am I missing? Thank you.

Related

Change an SKScene centerpoint

I am working with a simple 2d game and I am trying to switch from level 1 (scene one) to level 2 (scene two). For the sake of testing, both levels contain the same content. This is my code for transitioning:
let transition = SKTransition.push(with: SKTransitionDirection.left, duration: 1)
let nextScene = Scene(size: levelBuilder.scene.size)
nextScene.scaleMode = .aspectFill
nextScene.backgroundColor = UIColor(red:0.17, green:0.24, blue:0.31, alpha:1.0)
levelBuilder.scene.view?.presentScene(nextScene, transition: transition)
nextScene.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
nextScene.physicsWorld.contactDelegate = levelBuilder.scene.physicsWorld.contactDelegate
loadLevelContents(level: 2, world: 1, borderPercentage: 30)
This works perfectly, but the issue is not the transitioning but the loading of nodes into scene two which happens here:
loadLevelContents(level: 2, world: 1, borderPercentage: 30)
The positioning goes fine, but the problem is that everything is based according to the center point, or relative (0,0), being in the middle of the screen.
Scene 2 has the center point at the lower left corner
While I need it to be like scene 1, where it is in the middle of the screen:
How can I change this relative point or center point, not sure what it is called, to the middle of the screen for all SKScenes
The point that you are looking for is called anchorPoint. In Spritekit lower left is 0,0 and upper right is 1, 1. So to put it in the center you would have to set and achorPoint of 0.5,0.5 in the didMove func
self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
For SKScenes the default value is (0,0), but it's not just SKScenes that have anchorPoints, SKSpriteNodes have it as well.

SpriteKit - Nodes not adding to SKCameraNode - Swift

Im trying to pin the game pad controller to the bottom left on my camera node but when i add the node as a child of my camera it doesnt show up?
let gameCamera = SKCameraNode()
var joypadBackground : SKSpriteNode = SKSpriteNode(imageNamed: "a")
override func didMove(to view: SKView) {
//Set game camera
self.camera = gameCamera
joypadBackground.position = convert(CGPoint(x: 0, y: 0), to: gameCamera)
joypadBackground.size = CGSize(width: 50, height: 50)
joypadBackground.zPosition = 1000
gameCamera.addChild(joypadBackground)
}
I had a hard time with this same problem the first time I was working with SKCameraNode and creating a heads up display.
Basically you have to remember that there are two parts to the camera. Running its functionality and rendering its children. By setting the scene's camera to gameCamera you've setup the functionality, but your camera isn't in the node tree for rendering. So, if you ever have a camera that needs to render its children don't forget to add it to the scene as a child, then the camera's children will be displayed.
self.camera = gameCamera
self.addChild(gameCamera)
Hope that helps someone avoid a very common error with a very simple solution.
You don't need
convert(CGPoint(x: 0, y: 0), to: gameCamera)
You can just set the CGPoint position to (0,0) and it should be at that point relative to the camera's space.
Not sure if this helps, at all, but what I do is (generally) position a child node AFTER I've added it to its parent. This is mainly a mental reminder, to me, that the child's position is within the coordinate space of the parent. So I'd do something like this:
gameCamera.addChild(joypadBackground)
joypadBackground.position = CGPoint(x: 0, y: 0)
If you're using a mid screen origin in your SKScene, this should be in the middle of the screen.
Bottom left will be a negative x and negative y value, size of which is relative to your frame size.

Swift 3 Beginner - Position Assets in Scene

I am a complete beginner at Swift 3 and programming in general so this will be an incredibly basic question.
I have been following tutorials and am currently positioning a SpriteNode using CGPoint. The tutorial recommends the following to position the Node centrally at the bottom of the screen:
Ground.position = CGPoint(x: self.frame.width / 2, y: 0)
However, that causes it to stick to the top-right of the screen.
When I use the following code:
Ground.position = CGPoint(x: 0 - self.frame.width / 2, y: 0 - self.frame.height / 2)
It positions at the bottom-centre as intended.
I do not understand why this happens as there is very little else done in the tutorial at this point to cause the error.
Set the anchorPoint of the scene to the bottom left corner at the beginning of your didMove(toView: SKView) (or in GameViewController):
scene.anchorPoint = CGPoint(x: 0, y: 0)
Keep in mind that everything you place on the scene is placed based on the anchorPoint. So with this anchorPoint, the origin of your scene is the bottom left corner.
Also note that if you're using .AspectFill as your sceneScaleMode, you don't have to use self.frame and instead set the scene size to 768x1024 (portrait)/ 1024x768 (landscape) then just use number values within the scene size.
Additionally, there are advantages of setting your scenes anchorPoint to the centre:
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
This makes it easier to fit the scene into iPad size as well as iPhone, and also simplifies centering nodes.
See this link for more info on making your app universal: iOS Universal Device App with SpriteKit, how to scale nodes for all views?

Anchor points in Swift Bugging?

I tried to understand the basics of anchor points in swift reading this :
https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Nodes/Nodes.html
I understood that in siwft, with sprite kit, the anchor point of the scene is in the down-left corner of the screen.
So if I position a node like this :
myNode.position = CGPoint(x: 0, y: 0)
self.addChild(myNode)
It doesn't appear on my view. So i tried another thing :
myNode.position = CGPoint(x: middleOfmyView, y: 0)
self.addChild(myNode)
And now I see half of the top of my square. So I see 20 pixels up from the bottom of the screen.
So I added :
myNode.position = CGPoint(x: middleOfmyView, y: 0+myNode.frame.size.height/2)
self.addChild(myNode)
And now I can see my entire square, on the middle of the screen.
Then I put it at x: 0 and let the Y point like that :
myNode.position = CGPoint(x: 0, y: 0+myNode.frame.size.height/2)
self.addChild(myNode)
And now I can't see my node appearing even if there is written "1 Node" in the bottom right corner of my screen!
So i'm wondering is the 0,0 point of the iPhone screen really on the down-left corner of the screen ?
Then where is the anchorpoint of my sprite node? How can I put my square right in the down left corner of my screen ?
This is all just to understand how things work… Thanks a lot in advance for your help :)
I'm using Xcode 7.3.1 and I still do not understand why the point 0 makes that I do not see my stuff… it's definitely a bug ?
SKSpritenodes default to an anchorPoint of (0.5, 0.5) meaning that the middle of the node goes where the position is set to. To change the anchorPoint do this: node.anchorPoint = CGPoint(x: 0, y: 0) this example sets the anchorPoint of the node to its bottom left corner. Keep in mind that changing the anchorPoint also changes the origin of rotation, and that anchorPoint values are between 0 and 1. To put the square in the bottom left corner:
myNode.anchorPoint = CGPoint(x: 0, y: 0)
myNode.position = CGPoint(x: frame.minX, y: frame.minY)
If you need help with anything else (or if I didn't cover what you wanted) feel free to ask me and I'll do my best to help

SKLabelNode Not Showing [SpriteKit]

I created a SKShapeNode called smallScreen and an SKLabelNode with the name screenLabel.
I later attempted to display screenLabel in smallScreen. When I ran the code however, it didn't work. I tried adding screenLabel as a child to self, and that seemed to allow the text to display. Whenever I added screenLabel as a child node to smallScreen, it wouldn't display. Please help, much thanks.
self.smallScreen = (self.childNodeWithName("screen") as? SKShapeNode)!
self.smallScreen.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height * 2/3)
screenLabel.text = "Screen"
screenLabel.fontSize = 30
screenLabel.fontColor = UIColor.redColor()
screenLabel.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height * 2/3)
screenLabel.hidden = false
self.smallScreen.addChild(screenLabel)
In Sprite-kit by default, a scene’s origin is placed in the lower-left corner of the view. Its default value is CGPointZero and you can’t change it. (source).
A sprite’s (SKSpriteNode) anchor point defaults to (0.5,0.5), which corresponds to the center of the frame (source).
SKShapeNode does not have an anchorPoint.
LearnCocos2D answered on this issue:
When you use an image you may need to align it on its node's position.
There's no other way to do so but through anchorPoint because the
image itself can't be modified (not easily anyway).
When you create a shape you have full control over the alignment of
the shape through CGPath. You can simply translate the path to change
the shape's alignment relative to the node's position.
This is my interpretation, not fact.
So , what happened to your code?
I don't know how you have initialized your shape, I make just an example:
/* Create a Shape Node representing a rect centered at the Node's origin. */
#available(iOS 8.0, *)
public convenience init(rectOfSize size: CGSize)
So we create the shape like this:
self.smallScreen = SKShapeNode.init(rectOfSize: CGSizeMake(200,200))
First, you place your SKShapeNode to the X center of the screen for the X coordinates, and Y = self.frame.size.height * 2/3. In fact, your smallScreen is visible.
Speaking about your label, you have add it to the smallScreen, so screenLabel must respect the alignment of his parent.
In fact you can see your label simply by making this change:
From:
screenLabel.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height * 2/3)
To:
screenLabel.position = CGPointZero
and your label is positioned to the center of the smallScreen according to the alignment of his parent.