问题
The concept of being able to return to a previous scene from where you left off is briefly mentioned here: https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/DesigningGameswithSpriteKit/DesigningGameswithSpriteKit.html
Other than that I can't find any more documentation on the subject. I know in other frameworks like Cocos2D you can pop scenes on a stack, and even have multiple scenes running at the same time.
How do I get this to work in SpriteKit.
I have a game with a swiping menu for character selection. Upon selecting a character the scene changes to another menu. I want users to be able to hit a back button and be presented with the previous scene, where the character they selected is in full view.
At the moment I have it presenting the previous scene as a new one. Which of cause creates it in a fresh state, with the first character in plain view, and not the character they selected.
This should be really simple, but for all my googling, I do not have a clue on how to implement this.
回答1:
I don't know if anyone is still checking this, but I believe that I have another way to solve the problem.
I made a custom "PauseScene" and the user can set a return scene, meaning that when you are ready to go back, the PauseScene's view presents the return scene. Here's the code:
PauseScene.h
#import "MAScene.h"
@interface PauseScene : MAScene
@property (weak, nonatomic, readonly) SKScene * returnScene;
-(void)setReturnScene:(SKScene *)otherScene;
@end
PauseScene.m
#import "PauseScene.h"
#import "MASpriteButton.h"
@interface PauseScene ()
@property (strong, nonatomic) MASpriteButton * resumeButton;
@end
@implementation PauseScene
-(void)setReturnScene:(SKScene *)otherScene
{
_returnScene = otherScene;
}
-(void)didMoveToView:(SKView *)view
{
[self createContent];
}
-(void)createContent
{
__weak typeof(self) weakMe = self;
MASpriteButton * resume = [[MASpriteButton alloc] initWithBackgroundImageNamed:@"cardback.png" andSelectedImageNamed:@"cardback.png" andCallbackBlock:^{
NSLog(@"removing...");
[weakMe.view presentScene:self.returnScene];
}];
resume.size = CGSizeMake(self.widthToHeightRatio * 20, self.heightToWidthRatio * 20);
resume.position = CGPointMake(self.size.width/2, self.size.height/2);
self.resumeButton = resume;
[self addChild:self.resumeButton];
[self setBackgroundColor:[UIColor blueColor]];
}
@end
The way I used it was that when the user hits a pause button in the gameplay scene, I call these lines:
self.paused = YES;
PauseScene * pScene = [[PauseScene alloc] initWithSize:self.size];
[pScene setReturnScene:self];
[self.view presentScene:pScene];
Note that self
in this little block is the gameplay scene.
By having the pause scene keep a weak pointer to the gameplay scene, it can keep a pointer to the return scene without dealloc-ing it when the pause scene is dealloc-ed.
PS The MAScene class is just a little extension of the SKScene class, I just added a couple things to it. If anyone wants that too just let me know.
回答2:
Assuming the menu scene is also implemented in Sprite Kit, you could create a modal view controller, present it, and put the Sprit Kit scene over that modal view.
So, specifically, create a new UIViewController inheriting class MenuViewController
, and a new SKScene inheriting class, MenuScene
. The class 'MenuScene' MenuScene
should be the Scene you're looking to present. Hook up MenuScene
and MenuViewController
like you would normally hook up an SKScene
and its view controller. Make sure you have the original scene's view controller as a property of the original SKScene
.
Wherever you want to present this menu, you can call from the original SKScene:
MenuViewController *modalViewController = [[MenuViewController alloc] init];
[self.viewController presentModalViewController:modalViewController];
There are simpler ways to just transition b/w SKScene
instances, but if you want to keep the intial SKScene
running in the background, this is what you would have to do, I believe.
回答3:
You just should keep strong pointer to the leaving scene before you call new
Here is example of realisation via singleton (actually usual singleton with scene pointer, no magic)
@interface Global : NSObject
+ (Global*)sharedInstance;
@property (strong, nonatomic) SKScene *mainScene;
@end
And .m file
@implementation Global
+ (instancetype) sharedInstance{
static Global *_sharedInstance = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedInstance = [[Global alloc] init];
});
return _sharedInstance;
}
@end
来源:https://stackoverflow.com/questions/20507790/spritekit-return-to-a-persistent-scene-in-the-same-state-it-was-left-in