I am working on a SpriteKit project and I'm struggling to pause the game when the iAd is clicked, and unpause when the iAd is dismissed. The main problem is pausing the Scene from the ViewController, I know that if I want to pause the Scene from the Scene.m I should use the code
self.scene.view.paused = YES;
however this code doesn't work in the ViewController.
- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave
{
//pause game
}
- (void)bannerViewActionDidFinish:(ADBannerView *)banner
{
//unpause game
}
I know that I would like to pause the game in the section above but I'm having trouble finding the resources to know how to perform this. Any help is appreciated, thanks.
If you have an SKView that's presenting a scene, you can call pause from within its ViewController like this:
Objective-C:
SKView *skView = (SKView *)self.view;
skView.scene.paused = YES;
Swift
let skView: SKView = self.view as! SKView
skView.scene.paused = true
Related
I'm new to spritebuiler.
I am getting performance issue when i tried to call skscene on uiviewconroller. i.e., I am developing a game on sprite kit.
My project has 2 view controllers named GameViewConroller, LevelSelectController & 2 SKScenes named MainMenuScene & GameScene. MainMenuScene is called when app runs & it contains levelselect button & playbutton, if i press play button button it moves to Gamescene & game is played over here so animations I am plying in game scene are very smooth and fine.
If i press levelselect button on MainMenuScene it moves to LevelSelectController it has 1 to 100 buttons when i press any button it moves to GameScene and game is played over here so animations Im plying in GameScene are very slow.
help me I am stuck !
#implementation GameViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Configure the view.
SKView * skView = (SKView *)self.view;
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = YES;
// Create and configure the scene.
SKScene *scene = [[MainMenuScene alloc] initWithSize:self.view.frame.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
// Present the scene.
[skView presentScene:scene];
}
I am new to the spritekit system. However, I have some questions. I have an app that has a menu screen, instructions page, etc..., none of which recquire me loading a skcene. However, I want to be able to load my "Game" scene on the press of a button. How would I do that regarding code?
FIXED:
I just did not check the IB settings for one of my views: my view type should be SKView.
Create new SKView in your view controller's -viewDidLoad: method
SKView *spriteView = (SKView *) self.view;
Then create new SKScene class in a separate file
#interface GameScene : SKScene
#end
Return to your previous view controller and place this code in your
button's event handler
GameScene* scene = [[GameScene alloc] initWithSize:CGSizeMake(768,1024)];
SKView *spriteView = (SKView *) self.view;
[spriteView presentScene: scene];
More info in Apple's documentation.
I have two SKScene SceneA,SceneB.
I have implemented two methods(willMoveFromView,didMoveToView) in each scene.
Assume, I am currently in SceneA and i want to present SceneB via this code block:
SceneB *sceneB = [SceneB sceneWithSize:self.view.bounds.size];
sceneB.scaleMode = SKSceneScaleModeAspectFill;
[self.view presentScene:sceneB];
When I present this scene, I can see this:
sceneA willMoveFromView
sceneB didMoveToView
sceneA init
sceneB willMoveFromView
sceneA didMoveToView
And finally I return to first SceneA ! There is no other code that pushes SceneA from SceneB . I don't know what to do, please help
UPDATE:
As #LearnCocos2D says, viewWillLayoutSubviews is forced every time I present scene
And I present sceneA in viewWillLayoutSubviews with following code
-(void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
SKView* skView = (SKView*)self.view;
SceneA *sceneA = [SceneA sceneWithSize:self.view.bounds.size];
sceneA.scaleMode = SKSceneScaleModeAspectFill;
[skView presentScene:sceneA];
}
As #LearnCocos2D says, viewWillLayoutSubviews is forced repeatedly , And I used to create new scene everytime it has been called. So I need to check if SKView.scene property is not nil. Here is the code:
-(void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
SKView* skView = (SKView*)self.view;
if(!skView.scene){
SceneA *sceneA = [SceneA sceneWithSize:self.view.bounds.size];
sceneA.scaleMode = SKSceneScaleModeAspectFill;
[skView presentScene:sceneA];
}
}
So when you create a project using the SpriteKit template. You have your View controller and your SKScene.
From my view controller I start my game with the code given by default and present the scene.
In my TCAViewcontroller.m
- (IBAction)startGame:(id)sender {
NSLog(#"Start Game triggered");
mainPageImage.hidden = 1;
// Configure the view.
// Configure the view after it has been sized for the correct orientation.
SKView *skView = (SKView *)self.view;
if (!skView.scene) {
skView.showsFPS = YES;
skView.showsNodeCount = YES;
// Create and configure the scene.
TCAMyScene *theScene = [TCAMyScene sceneWithSize:skView.bounds.size];
theScene.scaleMode = SKSceneScaleModeAspectFill;
// Present the scene.
[skView presentScene:theScene];
}
}
When the user loses in the game I would like to dismiss the scene and go back to my view controller I have. I can't seem to find anything with my searches to going back to the original view controller, just pushing to a game over scene. But I don't want to push to another scene, just dismiss the current scene and go back to my TCAViewController. Please answer using code for clarification Thanks
Your scene needs to offer a line of communication to your controller to indicate that is finished. You could, for example, create a delegate protocol and corresponding property in your scene. An example:
#protocol TCAMySceneDelegate;
#interface TCAMyScene : SKScene
#property (nonatomic, weak> id<TCAMySceneDelegate> delegate;
#end
#protocol TCAMySceneDelegate <NSObject>
- (void)mySceneDidFinish:(TCAMyScene *)gameScene;
#end
Then, in the .m of your TCAMyScene
- (void)endTheGame {
// Other game-ending code
[self.delegate mySceneDidFinish:self];
}
In your view controller, set itself as the delegate for your scene and implement the method:
- (IBAction)startGame:(id)sender {
// Other code
TCAMyScene *theScene = [TCAMyScene sceneWithSize:skView.bounds.size];
theScene.scaleMode = SKSceneScaleModeAspectFill;
theScene.delegate = self;
// Other code
}
- (void)mySceneDidFinish:(TCAMyScene *)myScene {
// logic for dismissing the view controller
}
When Im finished with my SKScene is there a way to dismiss the SKScene from within my SKScene class?
If not back in my Viewcontroller where I present my SKScene [skView presentScene:theScene]; is there a way to restart the scene or remove in from my SKView?
The SKScene Class Reference and SKView Class Reference are no help.
Update:
The following code removes my scene from my SKView [yourSKView presentScene:nil]; but when Im back in my view controller the scene is still running in the background. I can always pause it when the game is over and I'm sent back to my view controller(menu) but I'm wondering is there another method other then pausing it like completely removing it?
-(void)endTheGame {
[highscoreLabel removeFromSuperview];
NSLog(#"Game Over");
//would like to end here before calling the below method in my view controller
[self.delegate mySceneDidFinish:self];
}
Having met a similar issue I stumbled around your question, and since nobody gave a decent answer here's how I solved it:
in my scene I called both lines
[self removeFromParent];
[self.view presentScene:nil];
in my controller (the controller that displays the SKScene) I changed the template code from Apple, which was creating and presenting my scene from viewDidLoad in order to create and present my scene in viewWillAppear, only if the view's scene is nil
here's my Swift code, even if you're using Objective C you'll understand what it does; the key line being the "if skView.scene == nil" test :
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let skView = self.view as SKView
if skView.scene == nil {
let scene = GameScene(size:skView.bounds.size)
scene.controller = self
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
You can use:
[yourSKView presentScene:nil];
to remove the scene.
"You can't go "Back to the View Controller" from a scene. The scene is a View, the view controller controls and displays views. Use the view controller to change views. Remember the view controller itself is not a view." -Wharbio
Best solution here is to create another View Controller. This view controller will be my menu. Then the other viewcontroller will act as a host for the skscene.
In my situation I then use my menu viewcontroller to dismiss the viewcontroller displaying in the skview.
From within your SKScene, you can simply do [self.view presentScene:aNewScene] to present another scene
I completely remove scenes by using this block in my view controller:
Obviously you will need to declare your Size, and "newSKview"
SKView * skView = (SKView *)self.view;
SKScene *newScene = [[newSKView alloc]initWithSize:size];
newScene.scaleMode = SKSceneScaleModeAspectFill;
SKScene *oldScene=(skView.scene);
[oldScene removeFromParent];
[skView presentScene:newScene];
This works fine for me. None of my Scenes are retained or strong.
I prefer to use an additional UIViewController for SKView and Notification Center in where the UIViewController made SkScene.
The callback function is
#objc func cb_dismissingVC(_ notificaiton: Notification) {
self.dismiss(animated: true, completion: nil)
}
Maybe my variant will be helpful:
[[self.scene childNodeWithName:#"YourChildNodeName"] removeFromParent];