GameOver screen position swift - ios

I have implemented a game over screen to pop up when the player loses, the height is perfectly in the middle of the screen however the images stretches to the edge of the screen which i don't want it to do. I want the image to be offset from the screen slightly. I have attached my code for the game over screen below. The height is set just need help setting the width.
gameOverScreen = SKSpriteNode(texture: gameOverScreenTexture)
gameOverScreen.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
gameOverScreen.size.height = self.frame.height / 3
gameOverScreen.zPosition = 0
self.addChild(gameOverScreen)

Managed to sort it out. Just changed this line:
gameOverScreen = SKSpriteNode(texture: gameOverScreenTexture)
To this:
gameOverScreen = SKSpriteNode(texture: gameOverScreenTexture, size: CGSize(width: 600, height: 600))

Related

How do I constrain an SKShapeNode to the device edges in SpriteKit?

Just to test things out I have created a blue square and placed it at the center of the screen like this:
let mySquare = SKShapeNode(rectOf: CGSize(width: 50, height: 50))
mySquare.fillColor = SKColor.blue
mySquare.lineWidth = 1
let myPoint = CGPoint(x: UIScreen.main.nativeBounds.midX, y: UIScreen.main.nativeBounds.midY)
mySquare.position.x = 0
mySquare.position.y = 0
self.addChild(mySquare)
Works great. Now, I would like to use constraints and set up the square constraints to the edges of the device screen. I have tried this, but the blue square doesn't appear, so I think I have the wrong idea on how to capture the CGPoint of the screen edges.
let mySquare = SKShapeNode(rectOf: CGSize(width: 50, height: 50))
mySquare.fillColor = SKColor.blue
mySquare.lineWidth = 1
let myPoint = CGPoint(x: UIScreen.main.nativeBounds.maxX, y: UIScreen.main.nativeBounds.maxY)
let range = SKRange(lowerLimit: 10.0, upperLimit: 10.0)
let myConstraints = SKConstraint.distance(range, to: myPoint)
mySquare.constraints = [myConstraints]
self.addChild(mySquare)
How do I capture the screen edges and constrain the square to those?
SKConstraint doesn't work equally as UIKit Constraints.
SKConstraint functionality is really specific:
Please take a look here: https://developer.apple.com/documentation/spritekit/skconstraint
Anyway, can give you some recommendations:
Transform screen position to scene position:
self.view?.convert(myPoint, to: self)
You can start with this example and get node on a corner
let mySquare = SKShapeNode(rectOf: CGSize(width: 50, height: 50))
mySquare.fillColor = SKColor.blue
mySquare.lineWidth = 1
let myScreenPoint = CGPoint(x: UIScreen.main.bounds.maxX, y: UIScreen.main.bounds.maxY)
if let myScenePoint = self.view?.convert(myScreenPoint, to: self) {
mySquare.position = myScenePoint
}
self.addChild(mySquare)
With this logic, you can get each side of the screen and decrease or increase margin and make each 4 sides; or 1 constraint for the center.

SKLabelNode not appearing in proper position

I am running through an entry level xCode course and I am working with SKLabelNode. I have quadruple checked my code to be duplicate of this, yet my label is appearing 99% off the screen it appears? Please help.
By Default Anchor point of your main scene is set to x= 0.5 and y=0.5, So, when you add a new node, it's coordinates starts from center of screen.
Now, either you can change the anchor points of your scene as
self.anchorPoint = CGPoint(x: 0.0, y: 0.0)
let label = SKLabelNode(text: "Player Score")
label.fontColor = SKColor.white
label.fontSize = 60
label.position = CGPoint(x: self.frame.width/2, y: self.frame.height/2)
self.addChild(label)
or you can change the position of label to :-
label.position = CGPoint(x: 0, y: 0)

Node positioning issue in Swift 3

I'm just starting out looking into Swift 3 - never coded before so I'm completely new to it all. Been looking at a really basic Node tutorial and have the following code:
class GameScene: SKScene {
override func didMove(to view: SKView) {
// SKLabelNode
var exampleLabelNode = SKLabelNode(fontNamed: "Helvetica")
exampleLabelNode.text = "Example Label Node!"
exampleLabelNode.fontSize = 30
exampleLabelNode.fontColor = SKColor.white
exampleLabelNode.position = CGPoint(x: self.frame.size.width / 2, y: self.frame.size.height * 0.75)
self.addChild(exampleLabelNode)
// SKSpriteNode
var exampleSpriteNode = SKSpriteNode(imageNamed: "myImage")
exampleSpriteNode.size = CGSize(width: 180, height: 180)
exampleSpriteNode.anchorPoint = CGPoint(x: 0.5, y: 0.5)
exampleSpriteNode.position = CGPoint(x: self.frame.size.width / 2, y: self.frame.size.height * 0.25)
exampleSpriteNode.zPosition = 100
exampleSpriteNode.name = "exampleName"
self.addChild(exampleSpriteNode)
}
}
It's meant to position exampleLabelNode centre and 3/4 at the top of the screen and exampleSpriteNode 1/4 at the bottom of the screen.
However its positioning exampleSpriteNode 3/4 to the top of the screen and half off to the right with the exampleLabelNode positioned off the screen.
The tutorial is for Swift 2, so is the positioning syntax etc different for Swift 3?
This is happening because the default scene anchorPoint is (0.5, 0.5) meaning the centre of the scene. That's also the default anchorPoint for any node. That makes the point (x: 0, y: 0) at the centre of the scene.
I suggest you read more about this or ask questions to get a better understanding of it if you're having trouble.
Official Apple Docs
SKSpriteNode anchorPoint
SKScene anchorPoint
Note: The docs for the SKScene is incorrect when it says that the default value is (0, 0).
To solve your issue, you can add this line to the beginning of your didMove(to view):
self.anchorPoint = CGPoint(x: 0, y: 0)
This sets the scene anchorPoint to the bottom left of the scene, which used to be how it was (The tutorial is outdated).
Alternatively, you could redo the sprite placement now that you know how anchorPoint works. I suggest this because I find building games to be easier when building the scene from the centre outwards rather than from the bottom left corner.

Change Node Positioning Depending on Screen Size Swift/Sprite Kit

I want to change to positioning of my nodes depending on the size of the screen. For example, when I run my app on an iPhone 4s, not all of the nodes fit on the screen, since I developed the app with iPhone 6 dimensions in mind. How can I make it so the nodes reposition themselves depending on which device it's running on? I know I can achieve this with constraints normally, but I don't know how to do that in Sprite Kit. I have included a screen shot down below.
lblRocketCount.position = CGPoint(x: 100, y: 150)
lblRocketCount.text = "Bullets: 30"
self.addChild(lblRocketCount)
lblMissileCount.position = CGPoint(x: -100, y: 150)
lblMissileCount.text = "Missiles: 5"
self.addChild(lblMissileCount)
leftBorder.position = CGPoint(x: -333, y: 0)
self.addChild(leftBorder)
rightBorder.position = CGPoint(x: 333, y: 0)
self.addChild(rightBorder)
topBorder.position = CGPoint(x: 0, y: 187)
self.addChild(topBorder)
bottomBorder.position = CGPoint(x: 0, y: -187)
self.addChild(bottomBorder)
buttonDirUp.position = CGPoint(x: -200, y: -50)
buttonDirUp.setScale(2.0)
self.addChild(buttonDirUp)
ship.setScale(0.33)
shootButton.setScale(0.7)
missileButton.setScale(0.5)
buttonDirLeft.position = CGPoint(x: -250, y: -100)
buttonDirLeft.setScale(2.0)
self.addChild(buttonDirLeft)
buttonDirDown.position = CGPoint(x: -200, y: -150)
buttonDirDown.setScale(2.0)
self.addChild(buttonDirDown)
buttonDirRight.position = CGPoint(x: -150, y: -100)
buttonDirRight.setScale(2.0)
self.addChild(buttonDirRight)
self.view?.multipleTouchEnabled = true
self.backgroundColor = SKColor.blackColor()
self.anchorPoint = CGPointMake(0.5, 0.5)
self.addChild(base)
base.position = CGPointMake(200, -100)
self.addChild(ball)
ball.position = base.position
self.addChild(ship)
ship.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
self.addChild(shootButton)
shootButton.position = CGPoint(x: self.frame.midX, y: -100)
self.addChild(missileButton)
missileButton.position = CGPoint(x: -200, y: 50)
Screen Shot
This is a technique that I've found to be effective for dealing with multiple resolutions. You'll need to create two global variables in your GameViewController that reflect the size of the current view:
import SpriteKit
// global variables
var SKViewSize: CGSize?
var SKViewSizeRect: CGRect?
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let skView = self.view as! SKView
SKViewSize = skView.bounds.size
let scene = GameScene(size: SKViewSize!)
scene.scaleMode = .AspectFill
skView.presentScene(scene)
SKViewSizeRect = getViewSizeRect()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
SKViewSize = self.view.bounds.size
SKViewSizeRect = getViewSizeRect()
let skView = self.view as! SKView
if let scene = skView.scene {
if scene.size != self.view.bounds.size {
scene.size = self.view.bounds.size
}
}
}
func getViewSizeRect() -> CGRect {
return CGRect(x: ((SKViewSize!.width * 0.5) * -1.0), y: ((SKViewSize!.height * 0.5) * -1.0), width: SKViewSize!.width, height: SKViewSize!.height)
}
}
Then create an extension for all SKNode types that allows you to position them using a percentage of the current screen size:
public extension SKNode {
public func posByScreen(x: CGFloat, y: CGFloat) {
self.position = CGPoint(x: CGFloat((SKViewSizeRect!.width * x) + SKViewSizeRect!.origin.x), y: CGFloat((SKViewSizeRect!.height * y) + SKViewSizeRect!.origin.y))
}
}
For example, to create a sprite node and center it on any screen size, you'd use this in your GameScene:
let sprite = SKSpriteNode(color: SKColor.whiteColor(), size: CGSizeMake(32, 32))
addChild(sprite)
sprite.posByScreen(0.5, y: 0.5)
There is no easy answer to what you are looking for, you first need to decide what your game should be like at the different aspect ratios, and plan around that. In a lot of cases, you want to just give the 16:9 phones more FOV (They can see more of the game world). To do this, design your game with 2 layers: a game layer, and a hud overlay.
The game layer will utilize .AspectFill to keep your game the same "size" across devices, with the iPhone 4s folk losing the ability to see some of the screen above and below them (You can adjust where they lose some of the screen by moving the game layer nodes position)
The HUD overlayer will handle the things that need to stay at a fixed position on screen, like buttons and life bars. Now you can use the % based coordinates like some people have mentioned, or you can keep the absolute coordinates, and just add/subtract the pixel difference from your overlay nodes if your game detects a 3:2 (or 4:3 if you want iPad) ratio
Basic principle: (Do not copy verbatum)
Lets say we create a game scene that is 160x284 points
This means on an iphone 4s our resolution is 320x480, aspect fill is going to take the smallest of the distance between top/bottom or left/right and scale to that. In our case 160 is going to scale to 320, 284 is going to scale to 568. Uh oh, iphone only has 480, so you are losing out on 88 pixels, which means in the game world we are losing 44 points.
//This means that the top and bottom will lose out on 22 points each, so lets make that our iphone4s padding
class GameScene
{
let gameNode = SKNode();
let overlayNode = SKNode();
let iPhone4sPadding = 22;
func init()
{
//add all of the games nodes that you would add to the scene to gameNode instead
self.addChild(gameNode);
//add all of your overlay nodes (buttons, lifebars, etc) to the overlayNode
//do a check on uiscreen to see if the height is 480, if it is
// all nodes on the bottom add iphone4spadding to the y
// all nodes on the top subtract iphone4spadding from the y
self.addChild(overlayNode);
}
}

How do I make a border around my whole screen for all the devices in Swift Xcode?

I have this game thats in landscape and I need a border around the whole screen so my heroNode can't go out of the screen on either of the four sides. I have this code but it only works for the iphone 5s and its too small for the other devices. How would I get the code to resize and fit the screen for the other devices? Thanks!
override func didMoveToView(view: SKView) {
let borderBody = SKPhysicsBody(edgeLoopFromRect: CGRect(x: 20, y: -90, width: self.size.width-50, height: self.size.height))
borderBody.categoryBitMask = borderbodycategory
borderBody.collisionBitMask = HeroCategory
borderBody.contactTestBitMask = HeroCategory
borderBody.allowsRotation = false
borderBody.affectedByGravity = false
self.physicsBody = borderBody
}
self.physicsBody = SKPhysicsBody (edgeLoopFromRect: self.frame)
This gives your "World" a physicsbody, which is an edge, a loop, the size of the "World"'s frame.
Instead of using a fixed value for your width, make use of percentage values so it scales with your screen size.
You can use UIScreen 's property instead of the fixed value.
let width = UIScreen.mainScreen().bounds.size.width - 50
let height = UIScreen.mainScreen().bounds.size.height - 50
let borderBody = SKPhysicsBody(edgeLoopFromRect: CGRect(x: 20, y: -90, width: width, height: height))

Resources