SKSceneのpausedを勝手に変更されないようにする
一番ハードルが高かったのはリリースですね、本当に。。。
前回は、現象を再現したので、次は対策を打っていきたいと思います。
とりあえず、SKViewのpausedが変更されるのは良しとします。
ただし、その下にぶら下がってるSKSceneはダメです。
なので、例のコードをSKSceneを継承したクラスに追加します。
//
// FOOHogeScene.h
//
@property (nonatomic, assign) BOOL stayPaused; // <-- 追加
//
// FOOHogeScene.m
//
// 初期化時に追加
self.stayPaused = NO;
// 適当なところに追加
-(void)setPaused:(BOOL)newValue
{
if ( _stayPaused && !newValue ) {
// ユーザーの操作ではないと判断して、Pauseを解除しない
//NSLog( @"LCWGameScene setPaused rejected! newValue: %d", newValue );
}
else {
//NSLog( @"LCWGameScene setPaused newValue: %d", newValue );
super.paused = newValue;
}
}
// 外からポーズにする関数の例
-(void)pause
{
if ( self.paused ) {
return;
}
self.paused = YES;
self.stayPaused = YES;
[self addCoverSprite];
[self addChild:_resumuHintLabel];
}
// 外からポーズを解除する関数の例
-(void)resume
{
self.stayPaused = NO;
_resumeRequest = YES;
_resumeDelayTime = .5f;
_pauseButton.alpha = .3f; // 押せないので無効っぽい色に設定
[_resumuHintLabel removeFromParent];
[self removeCoverSprite];
}
もう少し補足しますね。
基本的に、SKViewのpausedが勝手に変わっても、
大抵の場合は問題ないかと思います。
ですが、今回のケースでは、
プレイ中にホームボタンが押された場合は、
SKSceneで管理していないBGMの停止を行ったり、
再度、アプリが選択された場合は、
PAUSEボタンをタップするように促した状態を維持する必要があります。
要は、この手(シューティング)のゲームで勝手に再開されたら困る訳です。
なので、SKViewからSKSceneに対して、
pause/resumeを呼んで、停止と再開を実装するようにしました。(*1)
最後に、pause/resumeについて。
1. pause
PAUSEボタンがすでに押されて、ポーズに入っているケースを想定して、
すでにポーズに入っていないかチェックしています。
現在表示されているスプライトを少し薄く表示するために、
SKSceneを覆うようなスプライトを用意して追加しています。
-(void)addCoverSprite
{
UIColor *color = [self.backgroundColor copy];
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithColor:color size:self.size];
sprite.alpha = .3f;
sprite.anchorPoint = CGPointZero;
sprite.position = CGPointZero;
sprite.name = kCoverSpriteName;
sprite.zPosition = 2.0f; // 敵機のミサイルがカバーの上にくるのを防ぐ
[self addChild:sprite];
}
あとで取り除くのに、nameを設定しているのもポイントです。
PAUSEを解除するボタンは、カバーの下になって薄くならないように、
zPositionの値をカバーより少し大きな値を設定しています。
_resumuHintLabelのzPositionも同様です。
ちなみに、_resumuHintLabelは、
「再開するにはPAUSEボタンをタップしてください」といった感じの内容になっています。
2. resume
再開時は、すぐにpausedを変更しないで、若干の間を置いてから実行しています。
そのためのフラグであったり、どの程度時間を置くかだけ設定しています。
それと、先ほど追加したカバーを削除したり、ラベルの削除も行ってします。
-(void)removeCoverSprite
{
SKNode *node = [self childNodeWithName:kCoverSpriteName];
if ( node ) {
[node removeFromParent];
}
}
まとめ
変更した行数は少なかったですが、
SKViewが変更されると、そこにぶら下がってるSKSceneも変更されるのは、
今思うと当然といえば当然ですが、このおかげで変更点は少なくて済みました。
iOSのバージョンを見て切り替えるような方法もあるかもですが、
その手のコードを入れるのは後々面倒を招くので避けた次第です。
あとは、審査が通ることを祈るだけですね!
おしまい。
(*1) この方法が最善かは別(なんせ処女作ですから)
Leave a Comment