I've been getting stuck doing what should be really simple stuff in Xcode, I am trying to add a sprite to the scene and for it to sit in the bottom left corner:
var groundTexture : SKTexture = SKTexture(imageNamed: "dirt-block")
var ground : SKSpriteNode = SKSpriteNode(texture: groundTexture)
ground.position = CGPointMake(ground.size.width/2, ground.size.height/2)
self.addChild(ground)
This doesn't show anything, so I took a look at what the scene dimensions are and self.frame.size.width and self.frame.size.height are returning a width of 1024 and a height of 768, regardless of orientation.
I want this fixed in landscape mode if that makes any difference to the answer?
I'm obviously missing a very fundamental idea to do with setting up the scene, if anybody could shed any light it would be much appreciated.
Thanks.
You have to edit the GameViewController:
Cut everything from viewDidLoad() except super.viewDidLoad()
Overwrite viewWillLayoutSubviews
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
// Configure the view.
var skView = self.view as SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.size = skView.bounds.size
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
Also you should set the scene size as you can see
scene.size = skView.bounds.size
Hope this helps
There is also a great Tutorial where this is explained better:
http://www.raywenderlich.com/49721/how-to-create-a-breakout-game-using-spritekit
(Chapter 1 or 2)
Related
I am trying to adjust SKScene position based on the device the game is running. For example due to 'top notch' area of iPhone XS Max, I need to subtract that height from SKScene height and position the scene accordingly.
So here is how I calculate the height aka safeAreaHeight in the AppDelegate and subtract from scene height aka sceneHeight:
safeAreaHeight = UIApplication.shared.statusBarFrame.size.height
sceneHeight -= safeAreaHeight
In GameViewController I try to re-position the SKScene like below:
if let view = self.view as! SKView? {
// Load the SKScene from 'MainMenuScene.sks'
if let scene = SKScene(fileNamed: "MainMenuScene") {
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFit
scene.size.height = sceneHeight
scene.size.width = sceneWidth
scene.position.y -= safeAreaHeight
// Present the scene
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
However, I am getting below error:
SKScene: Setting the position of a SKScene has no effect.
Additionally, I tried to use SKAction to move position of the SKScene as well, then I received below error:
SKScene: Animating the position of a SKScene has no effect.
Thank you for the help.
Well I figured how to achieve this, I am sharing in case it would help someone else.
Inside AppDelegate you get the correct safe area values and store it in a singleton (in my case: safeAreaHeight) for access throughout the app. Subtract the amount from scene height (sceneHeight).
let kWindow = UIApplication.shared.windows[0]
safeAreaHeight = kWindow.safeAreaInsets.top + kWindow.safeAreaInsets.bottom
screenHeight = screenRect.size.height - safeAreaHeight
Don't forget the adjust the sceneHeight in GameViewController before presenting it:
if let view = self.view as! SKView? {
// Load the SKScene from 'MainMenuScene.sks'
if let scene = SKScene(fileNamed: "MainMenuScene") {
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFit
scene.size.height = sceneHeight
scene.size.width = sceneWidth
// Present the scene
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
Inside loaded scene, in this case it is MainMenuScene, you simply find subview of SKScene and adjust its Y position by subtracting the safeAreaHeight at its center
guard let subView = self.view else { return }
subView.center.y -= safeAreaHeight
PS.: Do not adjust all the views in different scenes (ie.: GameScene, GameOverScene etc.) Once you adjust, it remains throughout the app.
I am trying to add sprites to my SKScene, but the coordinate system seems to be weird. The [0, 0] point is in the middle of the screen and not in the lower left corner like it should be. I have no idea how this could have happened as I have tried correcting using a variety of methods I have found in similar questions.
Here is my GameViewController class:
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
if let scene = MenuScene(fileNamed: "MenuScene"){
scene.scaleMode = .aspectFill
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
I have tried changed the scaleMode which only changed the scale of sprites and didn't fix the issue. I have also tried changing MenuScene(fileNamed: ) to MenuScene(size: view.bounds.size) which gave me errors. If I am missing any details, please ask.
That is happening because by default, SKScenes have an anchorPoint of (0.5, 0.5). This places the point (0,0) in the centre. If you're looking to change the anchorPoint to the bottom-left, add this to the beginning of didMoveToView:
self.anchorPoint = CGPoint(x: 0, y: 0)
Or initialize the scene with that anchorPoint before presenting it (from GameViewController):
scene.anchorPoint = CGPoint(x: 0, y: 0)
Or change it in the scene editor.
FYI: CGPoint(x: 0, y: 0) is the same as CGPoint.zero
Personally, I find it easier to build the scene outwards from the centre because it makes symmetry easier and laying out HUD easier, instead of from a corner, which results in building the scene from the corner, potentially creating difficulties.
I get an error that "Class 'GameScene' has no initializers" when I try to add a level selection to my game.
I present the scene in GameViewController.swift like this:
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene.level(1) {
// Configure the view.
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
skView.showsPhysics = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
And in my GameScene.swift I wanted to handle the level selection like this (got this from Ray Wenderlich iOS Game Development Books)
class func level(levelNum: Int) -> GameScene? {
let scene = GameScene(fileNamed: "Level\(levelNum)")!
scene.currentLevel = levelNum
scene.scaleMode = .AspectFill
return scene
}
But then I get the error as I mentioned and I dont know how to fix this issue :-? Are there any other ways to make a level selection? Currently I have for each level one sks file, which is something I find really handy, since I enables me to lay out the levels visually.
Any recommendations and/or help?
Thanks in advance
I'm currently making a game in Swift/SpriteKit and I'm having a problem. Whenever I make the border for my game, the border is always around the iPhone/iPad FRAME and not the screen. So when my ball bounces it goes off of the screen and bounces off the "iPhone FRAME" and not the "scene/frame."
Can someone help me make it so my border is around the SCENE and not the FRAME?
Here is my code:
let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
borderBody.friction = 0
self.physicsBody = borderBody
I was meant to say (in comments) that you should set the scene's size to match the view's size, like this: In the GameViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene(fileNamed:"GameScene") {
// Configure the view.
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
scene.size = skView.bounds.size
skView.presentScene(scene)
}
}
Note the scene.size = skView.bounds.size which sets the scene's size to a size of the view.
Im making a game with swift and spriteKit with xcode 6.1.
My problem is that, when I run the game on the iPhone 6 or iPhone 6+ the scene/images dont resize properly
I have this on my GameViewController
// Configure the view.
let skView = view as SKView
skView.multipleTouchEnabled = false
// Create and configure the scene.
scene = GameScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
// Present the scene.
skView.presentScene(scene)
And this on my GameScene
override init(size: CGSize) {
super.init(size: size)
anchorPoint = CGPoint(x: 0.5, y: 0.5)
let background = SKSpriteNode(imageNamed: "Background")
addChild(background)
}
I have tried all the scale modes but they dont seem to work. I hope someone can tell me what is going on
The size of the scene is being set to the size of the view in
scene = GameScene(size: skView.bounds.size)
so it is only the images in the scene that are too small to fill the view.
Make these changes to your GameViewController:
if you set the size of the scene to the size of the background image:
scene = GameScene(size: CGSize(width: backgroundImageWidth, height: backgroundImageHeight))
(replace backgroundImageWidth and backgroundImageHeight with actual values)
then set the scene's scale mode to fill the view:
scene.scaleMode = .Fill
(this may make the scene look stretched, you could use other scale modes)