I have been trying to learn how to use delegates recently and actually seem to understand it for the most part. However I have one problem.
I have 1 GameViewController, 1 StartScene and 1 MenuScene
In my GameViewController I have 2 methods that I would like to get called from MenuScene. So far I have been using NSNotification, which works fine but I am trying to use delegates.
So I have set up a protocol in MenuScene
protocol MenuSceneDelegate {
func gameOver()
func showGameCenter()
}
I than referenced it like so
var menuSceneDelegate: MenuSceneDelegate?
In GameViewController I added the MenuSceneDelegate at the top. All is very standard so far. However the main problem I have is that when I set the delegate in GameViewController like so
let skView = view as! SKView!
var scene = StartScene(size: skView.bounds.size)
skView.ignoresSiblingOrder = true
scene.scaleMode = .ResizeFill
skView.presentScene(scene)
scene.menuSceneDelegate = self //Sets delegate to StartScene not MenuScene
it only applies to the StartScene. How can I set the GameViewController delegate from StartScene to MenuScene. Everything works fine if I would first present the MenuScene. However I present StartScene first and therefore I am trying to understand how I set the delegate to MenuScene.
I tried something like this below but it doesnt work and just doesnt seem right
var menuScene = MenuScene(size: skView.bounds.size)
menuScene.menuSceneDelegate = self
I would appreciate any help or support. Thank you very much
Basically the solution is to set the delegate when I change from start scene to game scene, not in the beginning.
Related
I'm Trying to make a Start Scene Where you press a "Start" Button, and it goes to the main game scene. Here's the code:
if startBTN.containsPoint(location) {
let gameSceneTemp = GameScene(fileNamed: "GameScene")
self.scene?.view?.presentScene(gameSceneTemp, transition: SKTransition.fadeWithDuration(0.01))
}
But for some reason, whenever the scene loads up, it displays a squished-like scene in the GameScene. Can anyone help solve this problem by displaying a normal size (portarit) scene? Here's the Screen shots between the expected and actual scene:
The Expected Scene
The Actual Scene (The Problem)
It turns out, I didn't set the scene mode. I looked this problem up and I finally found the solution. Here's the code:
if startBTN.containsPoint(location) {
var gameScene = GameScene(size: self.size)
var transition = SKTransition.fadeWithDuration(0.8)
gameScene.scaleMode = SKSceneScaleMode.AspectFill
self.scene!.view?.presentScene(gameScene, transition: transition)
}
I had put the gamescene file and transition, but didn't add the scalemode to it.
I am recently working on sprite kit to create a simple game where user input name as identity and moves forward to play game and has option to edit name or replace name.
Which is best option to use uitextfield: in skscene or viewcontroller? Or any other solutions?
I had tried with uitextfield adding in skscene but got memory issue (since i called scene from viewwilllayoutSubview
override func viewWillLayoutSubviews() {
let skView = self.view as! SKView
skView.ignoresSiblingOrder = true
let scene =
NameEntryScene(size:CGSize(width: 1024, height: 718))
scene.scaleMode = .aspectFill
skView.presentScene(scene)
}
which I followed stackoverflow others answer to add uitextfield in gamesence at didMove(to view: SKView).
Also created uitextfield in viewcontroller and pass its instance all over the gamesence with action of isHidden true and false to remove memory issue, which worked but I can't work like this if i have many uitextfield's at various postions.
Any suggestion and help is very much appreciated. Thanks in advance.
We have a code base that was written and released in 2013, but in iOS 9 the app no longer transitions visibly between SKScenes when the presentScene:transition: message is sent to our SKView. The SKScene receives the didMoveToView: message but the scene itself never shows on screen.
Here's what we tried:
Disabling Metal via the Info.plist
Using [SKTransition transitionWithCIFilter:duration:] instead of the predefined animations
Tweaking zPosition
Switching to regular UIView animations (this made our SKNodes disappear)
Making sure the transition method doesn't get called more than once
Explicitly setting pausesOutgoingScene to YES on the SKTransition
None of the above attempts fixed the issue. Note that everything transitions properly in iOS 8
Here is some sample code that doesn't work:
-(BOOL)presentTitle {
if (!titleSceneLoaded) {
return NO;
}
[skView presentScene:titleScene transition:[SKTransition fadeWithDuration:1.0]];
return YES;
}
Changing it to this makes it work again (without the transitions):
-(BOOL)presentTitle {
if (!titleSceneLoaded) {
return NO;
}
[skView presentScene:titleScene];
return YES;
}
Any suggestions on how to locate/fix/workaround the bug?
There is a bug in iOS9 with presenting a scene with a transition in a subview.
I had the same issue and in my controller I was able to fix the issue by changing the following code in viewWillLayoutSubviews from this:
[self.subview presentScene:self.scene];
[self.view addSubview:self.subview];
to this:
[((SKView *)self.view) presentScene:self.scene];
Another workaround if the scene has to remain in a subview approach is to use presentScene without the transition, which does work.
We were unable to get SKTransition to work. We talked to the developer support team, posted on the developer forums, and tried everything posted here.
It is SpriteKit bug exclusive to iOS 9. If anyone else runs into this bug on iOS 9, we switched to custom transitions utilizing UIView animateWithDuration:animations:completion:.
It is a bit late but my own wrestling with what seems to be this bug may be worth exploring.
As I found out, I had a UIViewController floating around without having being fully deallocated, which had an SKView on it.
The only side-effect from that SKView still being somewhat live was the presentScene(transition) not working, as you have experienced.
It will work if you drag and drop the SKView in the storyboard instead of creating it manually.
Then in the ViewController, create an outlet:
#IBOutlet var skView: SKView!
Then present the scene as:
homeScene = HomeScene(size: self.view.frame.size)
homeScene.scaleMode = .aspectFill
homeScene.backgroundColor = .clear
skView.presentScene(homeScene)
And from this SKScene, you can simply use the navigation with the transition as:
let gameScene = GameScene(size: self.size)
self.view?.presentScene(gameScene, transition: SKTransition.doorsOpenHorizontal(withDuration: 1))
I am doing SpriteKit animation using XCode 7 interface builder means adding SKNodes and SKActions like rotation, move to , fade in and fade out everything through interface builder not even a single line of code for animation.
Everything works fine unless and until I send my app to the background mode. When I send app to background and launch it again animation gets paused. This issue is for iOS 8 only, it is working fine on iOS 9.
Below is the code I have used to present scene:
override func viewDidLoad() {
super.viewDidLoad()
UIApplication.sharedApplication().idleTimerDisabled = true
self.navigationController?.navigationBarHidden = true
let scene = SceneClass(fileNamed: "xxxxxxxx.sks");
self.view = SKView();
let skView = self.view as! SKView
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
scene!.cockViewController = self;
/* Set the scale mode to scale to fit the window */
scene!.scaleMode = .Fill
scene!.view?.autoresizesSubviews = true;
scene?.delegates = self
skView.presentScene(scene)
}
Does anybody know how to solve this?
Thanks.
you need to create a view class for your gamescene view if you do not have one, and add the following code
class GameSceneView : SKView
{
func CBApplicationDidBecomeActive()
{
}
}
In interface builder, on the view that holds the GameScene, make sure you set Class to GameSceneView
There is a bug in SKView where this function gets called with the become active notification and pauses the view.
*Note if this breaks something in iOS 9, then add a wrapper around it so that it should only be used on iOS 8
In my game right now I've got a GameScene.swift and a GameOverScene.swift. When the game loads, GameScene.swift shows up and the game plays great. However, now that I'm done with the gameplay, how can I add a start screen that displays when the app opens?
To create the scene that runs when your app first opens, you will have to make some adjustments to the game's view controller. First change
let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as! GameScene
to
let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as! sceneName
and this line in didMoveToView
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
to
if let scene = GameScene.unarchiveFromFile("GameScene") as? sceneName {
This will change the opening scene from GameScene to sceneName, or whatever you called your scene. Also, you must declare you scene like this: class sceneName:SKScene {...}. You can create a new .swift file (cmd + n) to score this class in for easy file management or you can put it in the GameScene file. Happy coding.