How can I load a spritekit file different than GameScene.swift in my GameViewController.swift? - xcode

In GameViewController.swift, I find this line
if let scene = GameScene(fileNamed:"GameScene") {
and I always thought that if I wanted to load something other than GameScene.swift, I could just change "GameScene" to "LandingPage" and everything would work just dandy. However, as I recently figured out, "GameScene" here actually refers to GameScene.sks and not the swift file.
I'm looking to make a game with a number of levels, each written in its own swift file. Where do I go to/ how do I move from, say, level1.swift to level2.swift?

if you are in one scene for example level selection scene, lets say LevelSelectionScene.swift, you can go to another scene via SKView's -presentScene:transition: method.
class LevelSelectionScene: SKScene {
override func didMoveToView(view: SKView) { /* ... */}
func selectLevel(level: Int) {
let fadeTransition = SKTransition.fadeWithDuration(0.3)
if let selectedLevel = createLevelSceneWithLevel(level) {
self.view?.presentScene(selectedLevel, transition: fadeTransition)
}
}
// Not a good idea if you progressively adding new levels,
// it's totally depend on how you gonna organize your levels.
// Since its level input is not arbitrary, the output of this
// rarely nil, if it does, it must be the developer mistake.
func createLevelSceneWithLevel(level: Int) -> SKScene? {
let levelScene: SKScene?
switch level {
case 1: levelScene = Level1()
case 2: levelScene = Level2()
default: levelScene = nil
}
return levelScene
}
}

As somebody above has said the line "fileNamed: "GameScene" "
if let scene = GameScene(fileNamed:"GameScene") {
references the GameScene.sks file, which is the equivalent of storyboard for games.
If you create a new SKScene class and try to load it this way, either from another SKScene or the gameViewController it will not work because it cannot find the corresponding sks file.
I am not 100% sure how to create a new sks file because I dont use it in my games.
If you just want to load a new scene you created you would use this code in your gameViewController
let skView = self.view as! SKView
let scene = NewScene(size: skView.bounds.size)
skView.ignoresSiblingOrder = true
skView.multipleTouchEnabled = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
If you want to load another scene from a SKScene class its basically the same code
let newScene = NewScene(size: self.size) //size of current scene
let transition = SKTransition.doorsCloseHorizontalWithDuration(0.5) // use transition between 2 SKScenes
let skView = self.view as! SKView
skView.ignoresSiblingOrder = true
skView.multipleTouchEnabled = true
newScene.scaleMode = .AspectFill
skView.presentScene(newScene, transition: transition)
or a slightly cleaner version
let newScene = NewScene(size: self.size)
let transition = SKTransition.doorsCloseHorizontalWithDuration(0.5)
newScene.scaleMode = SKSceneScaleMode.AspectFill
self.view?.presentScene(newScene, transition: transition)

You can specify a custom class name for each scene file in the Custom Class Inspector. That's the right most tab in the Utilities pane.
The custom class (must be a subclass of SKScene) is loaded when the sks file is loaded.

Related

Swift: Can't create UIImageView from ViewController.swift

I have set up my UIImageView using the below setup. I am trying to draw on the view but can not get anything to appear. I am new to Xcode and want my view to automatically change depending on what the screen size is. When I have used the storyboard I could not figure out how to get the view to change with the screen size and/or rotation. As a result I figured it would be easier to make that happen in the ViewController.swift file. When the program wasn't working I tried to see if the view was appearing on the screen. When I made one of the views red, I still could not see anything on the screen. I am very confused. I am open to any feedback. I appreciate you taking time to read this and am looking forward to assistance.
Thanks,
T
import UIKit
import CoreGraphics
class ViewController: UIViewController {
var ResultImageView = UIImageView ( frame: UIScreen.mainScreen().bounds)
var DrawingImageView = UIImageView ( frame: UIScreen.mainScreen().bounds)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
ResultImageView.userInteractionEnabled = true
ResultImageView.backgroundColor = UIColor.redColor()
DrawingImageView.userInteractionEnabled = true
}
I think the problem is you have to create the imageview in viewDidAppear if you're setting the screen size, because the screen size hasn't been set and orientated where you're setting it. Try the below and hope this issue gets resolved soon :)
var ResultImageView = UIImageView()
var DrawingImageView = UIImageView()
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(true)
ResultImageView = UIImageView (frame: self.view.frame)
DrawingImageView = UIImageView (frame: self.view.frame)
ResultImageView.userInteractionEnabled = true
self.view.addSubview(ResultImageView)
self.view.addSubview(DrawingImageView)
ResultImageView.backgroundColor = UIColor.redColor()
DrawingImageView.userInteractionEnabled = true
}

How to change the first SKscene that is presented through gameviewcontroller

So i have created a couple of different SKScenes in my swift project and I've seen on a couple tutorials that you don't have to launch you gameScene.swift as your first scene, however i can not find a tutorial that explains how
import UIKit
import SpriteKit
class GameViewController: UIViewController {
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
skView.presentScene(scene)
}
}
}
Im trying to change the GameScene SKS to my MainMenu SKS, but i keep getting errors and I'm definitely missing something. Can anyone help me out?
import UIKit
import SpriteKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let newScene = MenuScene(fileNamed:"MenuScene") {
// 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 */
newScene.scaleMode = .AspectFill
skView.presentScene(newScene)
}
}
}
So instead of having GameScene as your initial scene, just create MenuScene instance and present it in your viewDidLoad. Note that you have to create coresponding MenuScene.sks file because of this line:
If let newScene = MenuScene(fileNamed:"MenuScene.sks"){
//...}
because you are loading it from a file.
Also to transition to another scene, use following pattern and for example in touchesBegan create new scene, optionally create SKTransition and present the new scene.
Just call that code whenever you want. For example, you can connect it with a button.
#IBAction func playGame(sender: AnyObject) {
if let scene = GameScene(fileNamed:"GameScene") {
...
}
}
this is what I used in a Sprite Kit project. It was I while ago and I dont remember any of the reasoning behind it.
if let scene = DesiredScene.unarchiveFromFile("DesiredScene") as? DesiredScene
perhaps someone else can elucidate whats going on

Is it possible to have two nodes of the same SKSpriteNode class in swift?

This is very difficult to explain but I will do my best. I am experimenting with SpriteKit and have made a game that has a button that when pressed creates a SpriteNode at a random location. The node is made to move up 100 units, then back down to its original position every time it is touched. My issue is that only the node that was made last responds to touches, so only one node at a time is usable. However, my goal is to have all nodes in the view respond when they are touched. Is such a scenario possible?
In a separate swift file I have:
class balloon:SKPriteNode{
required init?(coder aDecoder: NSCoder){
fatalError("init(coder:) has not been implemented")
}
init (imageNamed: String){
let imageTexture = SKTexture(imageNamed: imageNamed)
let imageSize = CGSizeMake(200,200)
super.init(texture: imageTexture, color:nil, size: imageSize)
}
}
And in GameScene I have the function:
func addBalloon(){
balloonLocation = CGPoint(x:addLocation!.x, y:addLocation!.y) //addLocation is given a value in a different function
balloonImage = "blueBalloon" //name of image in xcassets
balloonNode = balloon(imageNamed: balloonImage!)//balloonNode is the SKSpriteNode of the balloon class
balloonNode?.position = balloonLocation!
self.addChild(balloonNode!)
}
That is the code to add the node which is called on a button press. The code to move it when it is touched is also in GameScene :
override func touchesBegan(touches:Set<NSObject>, withEvent event: UIEvent){
for touch in (touches as! Set<UITouch>) {
let location = touch.locationInNode(self)
let balloonTouched = self.nodeAtPoint(location)
}
if(balloonTouched == balloonNode){
let balloonPosition = balloonNode?.position
let balloonUp = SKAction.moveTo(balloonPosition + 100, duration : 1)
let balloonDown = SKAction.moveTo(balloonPosition, duration: 1)
let balloonMove = SKAction.sequence([balloonUP, balloonDown])
balloonNode!.runAction(balloonMove)
}
}
This is not the full code but it is the bread and butter of it.

OSX SpriteKit Game template in Swift not working - XCode6-b5

Well, that's odd: I wanted to try creating a little Mac Game using Swift and Xcode6-b5, but when I open the a new project template, and without changing ANYTHING, the GameScene isn't loaded and the console shows these two lines when I try to run it:
2014-08-09 20:50:21.294 PokemonSK[3808:303] +[PokemonSK.GameScene nodeWithFileNamed:]: unrecognized selector sent to class 0x100009150
2014-08-09 20:50:21.295 PokemonSK[3808:303] +[PokemonSK.GameScene nodeWithFileNamed:]: unrecognized selector sent to class 0x100009150
I saw similar topics like this one Link1 but they don't explain how to fix it, and i don't want to upgrade to Yosemite...
Has anybody an idea to solve this ?
Thanks
(here is the AppDeleguate code, it might help)
import Cocoa
import SpriteKit
class AppDelegate: NSObject, NSApplicationDelegate {
#IBOutlet var window: NSWindow!
#IBOutlet var skView: SKView!
func applicationDidFinishLaunching(aNotification: NSNotification?) {
/* Pick a size for the scene */
let scene = GameScene(fileNamed: "GameScene")
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
self.skView!.presentScene(scene)
/* Sprite Kit applies additional optimizations to improve rendering performance */
self.skView!.ignoresSiblingOrder = true
}
func applicationShouldTerminateAfterLastWindowClosed(sender: NSApplication) -> Bool {
return true;
Apple is apparently adding new APIs and using them before they are widely available. This is more annoying than it should be, especially as the code in question doesn't really add anything.
You can get the basic demo code working with a single change. Look for:
let scene = GameScene(fileNamed:"GameScene")
In the AppDelegate.swift file, and change that to:
let scene = GameScene(size:self.skView.bounds.size)
Im not sure if it is the same thing but I experienced a similar issue trying to run a project from beta 5 on an iOSdevice.
Rather than
let scene = GameScene(fileNamed: "GameScene")
try
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
....
}
with a function unarchiveFromFile, which I think came in earlier templates.
extension SKNode {
class func unarchiveFromFile(file : NSString) -> SKNode? {
let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks")
var sceneData = NSData.dataWithContentsOfFile(path, options: .DataReadingMappedIfSafe, error: nil)
var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)
archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as GameScene
archiver.finishDecoding()
return scene
}
}
FYI everyone, this problem has been fixed in B6. Now the solution noted above will cause linker errors instead. Be sure to remove your unarchiveFromFile and revert the original code to use fileNamed:. Somewhat annoying, especially given the error is so opaque.

iAd in xcode 6 with Swift

I'm working to implement a banner ad in the scene, but it always reports "Thread 1: EXC_BREAKPOINT(code=EXC_ARM_BREAKPOINT, subcode=Oxdefe) and the program stops running.
I referenced Mr. T's answer in another question about iAd("Swift - ADBannerView") but still couldn't make it.
The code looks like this:
import UIKit
import SpriteKit
import iAd
class GameViewController: UIViewController, ADBannerViewDelegate {
#IBOutlet var adBannerView: ADBannerView
override func viewDidLoad() {
super.viewDidLoad()
println("view loaded")
//iAd
self.canDisplayBannerAds = true
self.adBannerView.delegate = self
self.adBannerView.alpha = 0.0
if let scene = GameScene.unarchiveFromFile("GameScene") as? 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
skView.presentScene(scene)
}
}
//iAd
func bannerViewWillLoadAd(banner: ADBannerView!) {
println("sort of working1")
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
self.adBannerView.alpha = 1.0
println("sort of working2")
}
func bannerViewActionDidFinish(banner: ADBannerView!) {
println("sort of working3")
}
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
println("sort of working4")
return true
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
}
}
And I created an ADBannerView in the Main.storyboard and linked it with the #IBOutlet adBannerView.
Anyone helps me figure out?
This is how I did it, possibly not all of it is necessary.
I did not use the banner in the Storyboard, so the IBOutlet is not necessary.
Also, if you manually create a banner, you do not need to set self.canDisplayBannerAds
This function (ported from ObjC) is how I display the ads.
func loadAds(){
adBannerView = ADBannerView(frame: CGRect.zeroRect)
adBannerView.center = CGPoint(x: adBannerView.center.x, y: view.bounds.size.height - adBannerView.frame.size.height / 2)
adBannerView.delegate = self
adBannerView.hidden = true
view.addSubview(adBannerView)
}
This is called in viewDidLoad. Then, in the didLoadAd delegate method, I set adBannerView.hidden = false and in didFailToReceiveAdWithError, adBannerView.hidden = true
I think hidden is better than alpha in this situation, as it feels more natural. I believe (but am not sure) that when hidden, the view is not drawn at all by the GPU, while with an alpha of 0, it is still drawn, but made invisible (correct me if I am wrong).
This is my setup, and it worked for me, so hopefully it will work in your case too!

Resources