如何在 Sprite Kit 中初始化所有场景?

Posted

技术标签:

【中文标题】如何在 Sprite Kit 中初始化所有场景?【英文标题】:How do I initialize all scenes at the start in Sprite Kit? 【发布时间】:2014-08-27 11:45:26 【问题描述】:

每当我想转换到某个场景时,SKTransition 甚至需要几秒钟才能开始。是否可以在游戏开始前初始化所有场景?

NewScene *newScene = [NewScene sceneWithSize:self.size];
SKTransition *reveal = [SKTransition moveInWithDirection:SKTransitionDirectionUp duration:0.5];
reveal.pausesIncomingScene = NO;
[self.view presentScene:newScene transition:reveal];

我也用didMoveToView 试过这个:

@implementation NewScene
-(id)initWithSize:(CGSize)size 
    if(self = [super initWithSize:size]) 
    // Load a bunch of stuff like this:
    SKSpriteNode *menuButton = [SKSpriteNode spriteNodeWithImageNamed:@"mainMenu"];
    menuButton.position = CGPointMake(self.frame.size.width/2,self.frame.size.height/4);
    menuButton.name = @"menuButton";
    [self addChild:menuButton];
    [menuButton setScale:0.8];
    

如何确保我的 Sprite Kit 游戏顺利运行?

编辑: 事实证明,问题在于我一直让主线程进入睡眠状态以淡出音乐。我已经让我所有的音频方法在后台运行,现在可以正常工作了。

【问题讨论】:

你能展示一下你用“加载一堆东西”评论替换了什么吗?在需要时创建场景不应该有任何问题,如果是,则更有可能重新考虑处理数据/加载资产的方式。你可以从尽可能多的异步处理开始,preloading textures。 @0x7fffffff - 编辑了我的帖子。我尝试过预加载纹理(为此使用了 Stack Overflow 上的另一个答案),但结果没有改变。我可能在新场景中加载了错误的纹理。也许你可以告诉我如何在新场景中加载纹理? 【参考方案1】:

一个好的方法是在SKScene 的初始化之前异步加载所有资源。 Apple 在Adventure game 中使用了这种方法:

NewScene.h:

typedef void (^AGAssetLoadCompletionHandler)(void);

@interface GameScene : SKScene<SKPhysicsContactDelegate, UIGestureRecognizerDelegate>

+ (void)loadSceneAssetsWithCompletionHandler:(AGAssetLoadCompletionHandler)handler;

@end

NewScene.m:

@implementation NewScene

-(id)initWithSize:(CGSize)size 
    if(self = [super initWithSize:size]) 
    // Load a bunch of stuff like this:
    SKSpriteNode *menuButton = [SKSpriteNode spriteNodeWithTexture:[self menuButtonTexture];
    menuButton.position = CGPointMake(self.frame.size.width/2,self.frame.size.height/4);
    menuButton.name = @"menuButton";
    [self addChild:menuButton];
    [menuButton setScale:0.8];
    


#pragma mark - Shared Assets

+ (void)loadSceneAssetsWithCompletionHandler:(AGAssetLoadCompletionHandler)handler 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^
        // Load the shared assets in the background.
        [self loadSceneAssets];

        if (!handler) 
            return;
        

        dispatch_async(dispatch_get_main_queue(), ^
            // Call the completion handler back on the main queue.
            handler();
        );
    );


+ (void)loadSceneAssets 
    sBackgroundTexture = [SKTexture textureWithImageNamed:@"background"];
    sMenuButtonTexture = [SKTexture textureWithImageNamed:@"mainMenu"];
    // etc.


static SKTexture *sBackgroundTexture = nil;
- (SKTexture *)backgroundTexture 
    return sBackgroundTexture;


static SKTexture *sMenuButtonTexture = nil;
- (SKTexture *)menuButtonTexture 
    return sMenuButtonTexture;


@end

然后只需从您的UIViewController 中呈现NewScene

if (!self.skView.scene) 
    CGSize viewSize = self.view.bounds.size;
    // Here you can present some loading scene or splash screen

    [NewScene loadSceneAssetsWithCompletionHandler:^
        NewScene *scene = [[NewScene alloc] initWithSize:viewSize];
        [self.skView presentScene:scene transition:[SKTransition crossFadeWithDuration:1.f]];
    ];

【讨论】:

以上是关于如何在 Sprite Kit 中初始化所有场景?的主要内容,如果未能解决你的问题,请参考以下文章

Sprite Kit:为所有场景只创建一次节点

如何在场景中放置场景 - Sprite Kit

Sprite Kit:如何在运行场景之上添加场景

如何在我的 Sprite Kit 游戏应用中实现 Facebook 和 Twitter 发布?

在 Sprite Kit 中组合多个 SKScene

如何从 Sprite Kit 场景中引用当前的 Viewcontroller