Why are the positions of my nodes different on every device? - swift

Ok, so I've been trying to position a line on my iPhone 6s+ and my iPad 2. The line was added in an SKCamera (I don't know if that effects it or not). Here is the code for the line:
var leftWall = SKSpriteNode()
leftWall.size = CGSize(width: 1, height: 10000)
leftWall.position = CGPoint(x: 0, y: 0)
leftWall.color = UIColor.red
leftWall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: leftWall.size.width, height: leftWall.size.height))
leftWall.physicsBody?.affectedByGravity = false
leftWall.physicsBody?.isDynamic = false
leftWall.physicsBody?.categoryBitMask = groundGroup
leftWall.physicsBody?.collisionBitMask = ballGroup
leftWall.physicsBody?.contactTestBitMask = 0
theCamera.addChild(leftWall)
Okay, so the x position is 0,0 right? Here is how it looks on my iPhone 6s+:
As you see, the line is in the middle?
Here is how it looks on my iPad 2:
I just don't understand why the position of the line is completely different.. Please help me!

You are not taking into account the cropping that happens on the iPad, or your scaleMode is all wrong
What you need to do is set all nodes anchor points (Including the scene) to (0.5,0.5), make sure your GameScene has a static size and not based on view.frame (750,1334 is a good one) and that your scale mode is set to .aspectFill. This makes (0,0) the center of the screen, and you will notice everything line up on all devices

Related

SpriteKit Nodes with Gravity False tilted in place

I'm building a menu Game Scene where I have a Logo and 4 buttons, all of those have a SKPhysicsBody with the rectangle size of the image.
All of those I only set:
logo.physicsBody = SKPhysicsBody(rectangleOf: logo.size)
logo.physicsBody?.affectedByGravity = false
Full code of creating the objects (all are the same)
logo = SKSpriteNode(imageNamed: "logo")
logo.anchorPoint = CGPoint.zero
logo.name = "logo"
logo.zPosition = 2
logo.size = CGSize(width: 309, height: 272)
logo.setScale(Generic.utilities.getScale())
self.addChild(logo)
logo.position = CGPoint(x: self.frame.width/2 - logo.size.width/2, y: self.frame.height - logo.size.height - 40)
logo.physicsBody = SKPhysicsBody(rectangleOf: logo.size)
logo.physicsBody?.affectedByGravity = false
and during a button press I change all the nodes affectedByGravity to true so they can fall of the screen and new elements can come in.
The problem I'm having is that when I run the app, the elements are all shifted/tilted on the screen and not in their original position
All I wanted is for them to stay in their position until I click one of the buttons and then they can fall off the screen.
Any reason why when I set a physics body and affectedByGravity they all tilt like this?
Well, Thanks to #RonMyschuk and #Knight0fDragon I found out (didn't know before) that I could add to my Scene loading the following:
skView.showsPhysics = true
Which add border lines around the physicsBody of your nodes, that way you can see them interacting. And by doing that I saw that the physicsBody of one of my nodes was completely in a different position then it should
By taking care of this issue, everything went back to normal

SpriteKit: using SKView in UIView instead of initializing a Game project

Completely new to SpriteKit. Currently I have a UIView, and I want to add a sprite node to it (like a small UIImageView, but I want animation for it so using SpriteKit). Therefore I didn't initialize my project to be a game project, as found in almost all of tutorials for SpriteKit. I've found a note here: link and what I have now is sth like:
func initializeImage() {
let imageView = SKView()
imageView.frame = CGRect(x: self.frame.width / 2 - Constants.imageWidth / 2, y: self.frame.height - Constants.imageHeight, width: Constants.imageWidth, height: Constants.imageHeight)
// so place it somewhere in the bottom middle of the whole frame
let sheet = SpriteSheet(texture: ...)
let sprite = SKSpriteNode(texture: sheet.itemFor(column: 0, row: 0))
sprite.position = imageView.center //basically the same position as the imageView.frame's x and y value
let scene = SKScene(size: imageView.frame.size)
scene.backgroundColor = SKColor.clear
scene.addChild(sprite)
imageView.presentScene(scene)
self.frame.addSubview(imageView)
}
The SpriteSheet is similar to this: sprite sheet; it's essentially cutting an image atlas and divide it into smaller images. I tracked the process and this step is indeed giving the smaller image (the var 'sprite'). But if running I only have a black square now (should be the size as defined by Constants). If I set scene.backgroundColor to be white then it's white. May I know how I should proceed from here, as how should I make the sprite showing up?
All of your code looks good except for this:
sprite.position = imageView.center // basically the same position as the imageView.frame's x and y value
That is basically not the position you think it is. The coordinate system in SpriteKit is a) relative to the (SK)scene, not to whatever view the SKView is contained in, and b) flipped vertically relative to the UIKit coordinate system. If you want a sprite centered in the scene, you probably want to set its position based on the scene's size:
sprite.position = CGPoint(x: scene.size.width / 2, y: scene.size.height / 2)
By the way, the external SpriteSheet code might not be needed (and you're more likely to benefit from Apple's optimizations) if you slice up your sprite sheet and put it in an Xcode asset catalog.

SpriteKit. Why .strokeTexture does not work for SKShapeNode?

I can't understand why the "strokeTexture" option isn't working on a SKShapeNode. Or, how can I do border with texture? Thanks in advance!
let shape = SKShapeNode(circleOfRadius: 100)
shape.position = CGPoint(x: 200, y: 400)
shape.fillColor = SKColor.white
shape.fillTexture = SKTexture(imageNamed: "test")
shape.lineWidth = 50
shape.strokeColor = SKColor.white
shape.strokeTexture = SKTexture(imageNamed: "test(5)")
Output:
Test image:
Test(5) image:
It doesn't work in Simulator!
Try it on your device.
I get the feeling this stroke might be being done with metal, whereas the fill is somehow not being done with metal, so is visible in the simulator.
The fill also doesn't rotate with the object on the device, but the stroke/outline and its texture do.
This would tend to indicate that an SKShapeNode without a fill might have reasonable performance.
Set the width and height of the texture, that is used to render the stroke, multiple of 8 pixels. In your case Test(5) has dimensions 100x100. If you change this texture for another one with dimensions, e.g. 96x96 pixels, the stroke will be rendered correctly and displayed. I don't know, why there are no reference to this fact in the official documentation.

SpriteKit Positioning and containing a button

I want to constrain and position a game center button to the top left and make it constrained for every device, how do I do this. I am really new to sprite kit.
let gameCenterBtn = SKSpriteNode(imageNamed: "Game-Center-icon.png")
gameCenterBtn.size = CGSize(width: 60, height: 60)
gameCenterBtn.name = "gameCenterButton"
gameCenterBtn.position = CGPointMake(320, 730)
gameCenterBtn.position = CGPoint(x: self.frame.width , y: self.frame.height )
For example how do I make a position a node and make it work for any device?
I figured it out. The code below works.
gameCenterBtn.position = CGPoint(x: CGRectGetMidX(self.frame) - 188 , y: CGRectGetMaxY(self.frame) - 25)
Scene cropping is still happening as I said in my old answer I deleted.
Open a brand new Xcode game template and paste your code with a position like this
gameCenterBtn.position = CGPoint(x: CGRectGetMaxX(self.frame) - (gameCenterButton.size.width / 2) , y: CGRectGetMidY(self.frame))
and run on all the simulators to see what happens.
On iPads you see half the image on the right and on iPhones you only see 1/4.
Now go the the GameViewController and change the scene scale mode to ResizeFill and see what happens. You sprits will be at the same spot on all devices but you will have to readjust the image size.
This is how you set the scene size.
How to change SKscene size

Swift- UI Progress Bar not showing up

Here's what I have so far in my didMoveToView() function:
backgroundLayer.zPosition = -1
hudLayer.zPosition = 100
addChild(backgroundLayer)
addChild(hudLayer)
backgroundColor = SKColor.whiteColor()
let healthBar: SKSpriteNode = SKSpriteNode(imageNamed: "Healthbar")
healthBar.position = CGPoint(x: 0, y: 0)
healthBar.anchorPoint = CGPoint(x: 0, y: 1.0)
hudLayer.addChild(healthBar)
My background shows up fine, and I have both a backgroundLayer and a hudLayer. I even made the zposition much higher for the hudLayer to make sure it's in front. As for the positioning, I think I have the anchor point to be at the top-left of the sprite, and tried various ways to position it- it seems to only show up when I use something like:
healthBar.position = CGPoint(x: 0, y: size.width/2)
My question is why? size.width/2 isn't working for when I test on different screen sizes (on an iphone4, the health bar is further down).
Doesn't size take the current size of the screen? I thought using size would make it somewhat 'responsive' but I can't get the behavior to work right. Therefore, I thought maybe the CGPoint coordinate system (0-1.0) would work better, but it's not showing up at all with that.
Thanks for reading, I don't understand why it won't show up :(