SpriteKit Example without Storyboard - ios

I want to write the iOS Game Example that uses SpritKit in Swift, which is provided with Xcode only in code. That means I don’t want to use the GameScene.sks, actions.sks and the main.storyboard. I know how to write it without storyboard, but I can’t get it working without the .sks files. Can you say what I must change or can you provide me with a full project?

You will first need to have a View Controller. You can adjust the properties how you would like them. Here is mine:
import UIKit
import SpriteKit
class GameViewController: UIViewController {
// MARK: View Controller overrides
override func viewDidLoad() {
super.viewDidLoad()
view = SKView(frame: view.bounds)
if let view = self.view as! SKView? {
// Initialise the scene
let scene = GameScene(size: view.bounds.size) // <-- IMPORTANT: Initialise your first scene (as you have no .sks)
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
// Scene properties
view.showsPhysics = false
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
}
Then, you create a class for your first scene. Mine is called GameScene which was initialised in the view controller. Make sure this is a subclass of SKScene. It will look something like this:
import SpriteKit
class GameScene: SKScene {
/* All Scene logic (which you could extend to multiple files) */
}
If you have any questions, let me know :)

Related

Why can't I set SKScene(fileNamed:) in GameViewController?

The relevant code is copied below and I also put a simple test project on Github to demonstrate this situation:
https://github.com/prinomen/viewPresentSceneTest
I have a GameViewController and a GameScene class. I try to set the scene with SKScene(fileNamed: "GameScene") but that call is not working because the scene does not appear and the print statement after that line is not being called.
I know I could use a different way to set the scene, like this:
let scene = GameScene()
But I'm trying to understand SpriteKit and it bothers me that the code below does not work. In another project I was able to successfully set the scene using SKScene(fileNamed: "GameScene") like in the code below.
Does anyone know why it is not working in this project?
GameViewController.swift
import SpriteKit
class GameViewController: UIViewController {
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
if let scene = SKScene(fileNamed: "GameScene") {
print("SKScene was set")
// Set the scale mode fit the window:
scene.scaleMode = .aspectFill
// Size our scene to fit the view exactly:
scene.size = view.bounds.size
// Show the new scene:
view.presentScene(scene)
}
}
}
}
GameScene.swift
import SpriteKit
class GameScene: SKScene {
override func didMove(to view: SKView) {
self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
let logoText = SKLabelNode(fontNamed: "AvenirNext-Heavy")
logoText.text = "Game Scene"
logoText.position = CGPoint(x: 0, y: 100)
logoText.fontSize = 60
self.addChild(logoText)
}
}
I believe you need an .sks file to load scenes like that. You probably deleted it from this project, but still kept it around in the other one.
Here's what the documentation says:
The name of the file, without a file extension. The file must be in
the app’s main bundle and have a .sks filename extension.

SpriteKit - didMovetoView is not called

This is my code for the view controller
import UIKit
import SpriteKit
import GameplayKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
if let scene = SKScene(fileNamed: "GameScene") {
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
And this is my code for the GameScene
import SpriteKit
import GameplayKit
class GameScene: SKScene {
override func didMove(to view: SKView) {
print("gets called")
}
But for some reasons, in the debug area, it didn't print "gets called", which indicates that didMove didn't even get called. What's happening here? Did I miss anything?
The iOS 9 way
In your GameViewController try to directly present your GameScene instead of a generic SKScene.
if let scene = GameScene(fileNamed: "GameScene") {
...
Remember "fileNamed" is not the name of the .swift file, its the name of the .sks file which is used for the xCode level editor.
The new iOS 10 way
It seems Apple now prefers to pass a generic SKScene like you are trying.
if let scene = SKScene(fileNamed: "GameScene") { ... }
To make it work go to the relevant .sks file and go to the inspector on the right. Click the second last item (custom class) and enter the name of the .swift file into the custom class field.
Hope this helps.
This could happen because you don't have the related SKS (GameScene.sks in your case) file reference to your project, check if you have added it or removed/renamed due to mistake.
I finally sort that out.
My project name contains a period at the end. Like the name "XXXX.". After several experimentations, I discovered that I can simply solve the problem by removing the period.
My suggestion:
use
override func didMoveToView(view: SKView)
instead of
override func didMove(to view: SKView)
Maybe a naming inconsistency in the documentation/API...
I second what Tom Xue said as someone who spent way too long looking for the answer to this. I had a hyphen in my app name and that seems to have been causing the problem. When I renamed my project, the scene was presented as it should have been.

Sprite-Kit Error

Im following a tutorial right now and Im getting an error that I do not know how to fix.
import UIKit
import SpriteKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = StartGameScene(size: view.bounds.size)
let skView = view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
skView.ignoresSiblingOrder = true
scene.scaleMode = .ResizeFill
skView.presentScene(scene)
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
On line 8 the let scene = StartGameScene(size: view.bounds.size)
is giving me an error:
use of Unresolved Identifier ' StartGameScene'.
I have created a CocoaTouch class and named StartGameScene. I dont know what the issue is. How do I fix it?
StartGameScene would need to be a class declared like this:
class StartGameScene: SKScene {...}
Either StartGameScene is not declared as an SKScene or the class itself is not declared.
The cocoa touch class that you have created has to inherit from SKScene. SKScene is the class in which you define your game's scene. Hence your code should look like:
class StartGameScene: SKScene {
}
If you have already done this, then please make sure there isn't any typographic error.
just change StartGameScene to GameScene

Correctly presenting new scene in swift spritekit

I'm using spritekit with swift, and I'm just trying to present a new scene...but something is wrong and throwing errors. I was pretty sure this was the right syntax, and this is really throwing me for a loop.
The line
let skView = self.view as SKView
is giving me the error "SKView? is not convertible to SKView
Any advice is appreciated!
*my current code is below:
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches{
let location = touch.locationInNode(self)
if(self.nodeAtPoint(location) == self.playButton)
{
var scene = PlayScene(size: self.size)
let skView = self.view as SKView
// Configure the view.
/* 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)
}
}
}
The problem is the view property on SKScene is an optional (SKView?) because an SKScene doesn't necessarily have a containing view; what's it contained in before its been presented? Nothing.
To solve your problem you need to check the scene has a view by unwrapping the view property, by using optional binding for example:
if let view = self.view {
let scene = PlayScene(size: self.size)
scene.scaleMode = .AspectFill
view.presentScene(scene)
}
You can be pretty certain your SKScene has been presented (and thus view isn't nil) if someone is pressing on it - therefore you could instead force unwrap view, like so:
let scene = PlayScene(size: self.size)
scene.scaleMode = .AspectFill
view!.presentScene(scene)
Also, it's not required that you configure the SKView again (skView.ignoresSiblingOrder = true) since this, presumably, was already done in GameViewController.
Edit:
The line let skView = self.view as! SKView is likely from GameViewController (a subclass of UIViewController). If you take a look at the documentation for UIViewController and SKScene you'll see they both have a view property:
class UIViewController: /* Superclass and Protocols */ {
var view: UIView!
// ...
}
class SKScene: SKEffectNode {
weak var view: SKView?
// ...
}
However their types differ which means the way you use them differs. In the case of SKScene see above about unwrapping. In the case of UIViewController, you need to cast to SKView with the line:
let skView = self.view as! SKView
because UIView doesn't have the methods necessary for presenting an SKScene. (For more information on casting I'd recommending you take a look at The Swift Programming Language: Type Casting)
Normally you wouldn't be allowed to cast from UIView to SKView (keep in mind that SKView is a subclass of UIView). Try the following in Playgrounds:
let view = UIView()
let skView = view as! SKView
You should get an error something along the lines of:
Could not cast value of type 'UIView' (0x1041d0eb0) to 'SKView'
(0x10da10718)
However you can cast from UIView to SKView in your GameViewController because the Custom Class of GameViewController's view has been set to SKView:
I hope that helps clear up any confusion you had.
try this :
let sKView = self.view?.scene?.view
sKView?.presentScene(scene)
Best regards,
Yassine

Gaming SKScene transitions Swift

I'm new to Swift and have no Objective-c experience. I already have a working Swift game that I programed using SpriteKit and a not functional Menu also in SpriteKit. Im trying to figure out how to integrate this two but I can't find information on how to handle SKScene (I asume).
Currently if I Run the file it goes straight to the game and I want to first launch the menu and when a button is pressed to jump to the game. How or where can I learn to do this?
My two file clases are as follows:
class GameScene: SKScene, SKPhysicsContactDelegate {
// handles the game
}
class Menu: SKScene {
//handles the menu
}
thank you
You should have ViewController.swift after you make standart SpriteKit application. Your game scene is created and displayed in this file. To first show the menu, it is necessary to replace the game scene creating to menu scene creating. And your game scene must be created on menu scene object. It may look something like this:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = Menu(size: CGSize(width: 1024, height: 768))
let skView = self.view as SKView
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
....
}
class Menu: SKScene {
...
func startPlayButtonPressEvent() {
let skView = self.view as SKView
skView.ignoresSiblingOrder = true
let scene = GameScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
...
}

Resources