I need help moving from a UIViewController that appears after launch. It is sort of a fake splash screen that is animated and I want it to change to the SKScene once done. I have tried using this,
let skView = self.view as SKView
var loading:LevelOne = LevelOne(size: skView.bounds.size)
var loadingScreen:SKView = self.view as SKView
skView.showsFPS = true
skView.showsNodeCount = true
skView.showsPhysics = true
loadingScreen.ignoresSiblingOrder = true
loadingScreen.presentScene(loading)
But I get a log with (lldb) and it marks out
let skView = self.view as SKView
and says the app crashes due to that. What am I doing wrong and is there anybody who can help me out? I can convert Objective-c (simple that is) but I will prefer it in Swift
Thanks!
How can you build you game with this line?
let skView = self.view as SKView
Because you can not downcast from SKView? to SKView. I think it should be
let skView = self.view as SKView!
One another, can you go to storyboard, check the view of ViewController. The view should be an instance of SKView instead of UIView as a normal application (You can see it in "Custom Class" session of "Show the identity inspector")
Related
I have a app that Im making and I need to transition from my single view application view to a GameScene. I added the GameViewController.swift, GameScene.swift and the GameScene.sks to my project. How do I segue from my view controller to my GameScene? Ive looked up examples but none of them help, any quick solutions would be great.
Here is the code Im using to go to my game.
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let gameView: UINavigationController = storyboard.instantiateViewController(withIdentifier: "miniGame") as! UINavigationController
self.present(gameView, animated: true, completion: nil)
but I get an error
Could not cast value of type 'UIView' (0x2d73b00) to 'SKView' (0x1ba878c).
(lldb)
it pops the error on this line of code in my GameViewController
if let view = self.view as! SKView? {
you have to select your view in ViewController then in identity inspector set it's custom class to "SKView".
it will solve your problem.
The following should work for you.
import UIKit
import SpriteKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene(fileNamed:"GameScene.sks") {
// 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 = false
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
}
Make sure (1) that you have GameViewController set to the class name of the view controller scene over the Main.storyboard, (2) that you have SKView set to the class name of View under Game View Controller
I am new to SpriteKit and see the code like let skView = view as! SKView so what is use of this? Also I am confused about the difference between view and skView, scene and GameScene?
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = GameScene(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 var prefersStatusBarHidden: Bool {
return true
}
}
as! means "force cast". The value of view will be casted as SKView. If this fails, because view is nil or of a different type, the code will crash. That's why you should avoid using as! when you are not 100% sure of what type the value is.
Related:
https://stackoverflow.com/a/36024775/4687348
Type Casting - The Swift Programming Language
SKView is a subclass of UIView that has additional capabilities for SpriteKit functionality. The as! operator is downcasting the view of UIView to a SKView, to enable using SKView specific functionality in viewDidLoad().
Generally, the as? operator is recommended because it will gracefully fail to nil if it doesn't succeed, whereas as! will crash the app if the casting is unsuccessful. If you are 100% certain that you will always have the view is of type SKView in this case, then using as! can be an appropriate and less verbose choice.
For more information, I recommend reading this Stackoverflow post that compares the use of as, as?, and as!.
I created a new Swift file called GamePlayController.swift and I hooked it up to one of my Views in Storyboard. I am trying to run this code, but I get a SIGABRT at the line with the double asterisks. What is the reason for this?
import UIKit
import SpriteKit
class GamePlayController: UIViewController, UIGestureRecognizerDelegate {
var scene: GameScene!
override func viewDidLoad() {
super.viewDidLoad()
// 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)
}
view in this case is not an SKView instance. Try making an outlet in your source file to the SKView in the view controller in your storyboard. Google "iOS create storyboard outlet" if you're not sure how.
I wrote an iOS-App that uses multiple Views. Since I did not want to use the storyboard, I created a set of Views (xib files) and corresponding ViewControllers (swift files that extend UIViewController).
The views are created with all "Simulation Metrics" set to inferred, "Use Auto Layout" is on and "Use Size Classes" is also on. For every element, constraints are set, no errors.
In func application(application: UIApplication, didFinishLaunchingWithOptions ...) in AppDelegate.swift, I initiate my ViewControllers, e.g. by
connectVC = ConnectViewController(nibName: "ConnectView", bundle: nil)
On user actions (e.g. button click) and network actions (e.g. game started), I switch views programmatically with an animation by changing the window.rootViewController in AppDelegate.swift, exactly like here but in Swift.
So far, so good. But whenever I show a view for the first time, the view appears with the scaling/size just like in my Xcode interface builder, then resizes about half a second to a second later to the correct size of device's screen. This happens in the iOS Simulator as well as on my real iPhone.
The views use quite a few images in UIImageViews, but reducing the resolution or amount of pictures does not change that behaviour.
I would like to speed up that resize, ideally the users should not see any resizing of elements in my view. How can I do that?
This happened to me. First go into your GameViewController that starts up with the app. Then find this code:
if let scene = GameScene(fileNamed:"GameScene") {
// Configure the view.
let skView = self.view as! SKView!
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
skView.showsFPS = false
skView.showsNodeCount = false
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .ResizeFill
skView.presentScene(scene)
}
Change all of that code to this:
if let skView = self.view as! SKView! {
let scene = GameScene(size: self.view.bounds.size)
skView.ignoresSiblingOrder = true
skView.showsFPS = false
skView.showsNodeCount = false
scene.scaleMode = .ResizeFill
scene.size = skView.bounds.size
skView.presentScene(scene)
}
That should work, if you change GameScene to what ever your first scene is.
The problem was that I was using the ViewController chain incorrectly. Simply changing the window.rootViewController and doing a UIView.transitionFromView is not the indented way to deal with view switching.
So I created a SuperViewController that contains instances of all other ViewControllers and use the two functions below to switch between views. Now works like a charm.
The Creating Custom Container View Controllers article and also View Controller
Programming Guide for
iOS from Apple helped me quite a lot.
func setViewController(vc: UIViewController) {
self.addChildViewController(vc)
vc.view.frame = self.view.bounds
self.view.addSubview(vc.view)
vc.didMoveToParentViewController(self)
self.currentViewController = vc
}
func switchViewController(from: UIViewController, to: UIViewController) {
from.willMoveToParentViewController(nil)
self.addChildViewController(to)
to.view.frame = self.view.bounds
self.transitionFromViewController(from, toViewController: to, duration: 0.5, options: .TransitionCrossDissolve, animations: nil) { finished in
from.removeFromParentViewController()
to.didMoveToParentViewController(self)
self.currentViewController = to
}
}
Inside my main UIViewController, I'm defining two SKScenes. I want to present only gameScene at first, and then present uiScene later, triggered by an action in gameScene (hitting the pause button).
The problem is that skView, the view containing both scenes, is not recognized outside of the UIViewController.
The code is below. Any help would be appreciated.
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let skView = view as SKView
let gameScene = GameScene(size: view.bounds.size)
gameScene.scaleMode = .ResizeFill
skView.presentScene(gameScene)
let uiScene = UIScene(size: view.bounds.size)
uiScene.scaleMode = .ResizeFill
uiScene.backgroundColor = UIColor.clearColor()
//skView.presentScene(uiScene) // I want to present this line from within gameScene.
}
}
let reveal = SKTransition.flipHorizontalWithDuration(0.5)
let scene = uiScene(size: size)
self.view?.presentScene(scene, transition:reveal)
You can transition from one scene to another from within the scene. My code is pulled from http://www.raywenderlich.com/84434/sprite-kit-swift-tutorial-beginners in the last section.
Remember to import the header of the scene you are transitioning TO in the scene you are transitioning FROM.