いものやま。

雑多な知識の寄せ集め

変種オセロのルール画面を作ってみた。(その5)

昨日はルール画面を作った。

今日はスタート画面とルール画面の遷移を実装していく。

スタート画面の修正

まずはスタート画面→ルール画面の遷移から。

//==============================
// YWF
//------------------------------
// StartScene.swift
//==============================

import SpriteKit
import Security

public class StartScene: SKScene, PlayButtonNodeObserver, LabelButtonNodeObserver {
  // 省略
  
  public override init(size: CGSize) {
    // 省略

    self.ruleButton.addObserver(self)
    
    // 省略
  }

  // 省略
  
  public func labelButtonIsSelected(button: LabelButtonNode) {
    let scene = RuleScene(size: self.size)
    let transition = SKTransition.fadeWithDuration(NSTimeInterval(1.0))
    self.view?.presentScene(scene, transition: transition)
  }

  // 省略
}

変更は簡単で、LabelButtonNodeObserverプロトコルに準拠するようにし、Ruleボタンが押されたときにルール画面に遷移するようにしている。

ルール画面の修正

次に、ルール画面→スタート画面の遷移。

//==============================
// YWF
//------------------------------
// RuleScene.swift
//==============================

import SpriteKit
import WebKit

public class RuleScene: SKScene, ButtonNodeObserver {
  // 省略

  public override init(size: CGSize) {
    // 省略

    self.exitButton.addObserver(self)

    // 省略
  }

  // 省略
  
  public func buttonIsSelected(button: ButtonNode) {
    UIView.animateWithDuration(NSTimeInterval(0.5)) {
      self.webView.alpha = 0.0
    }
    let scene = StartScene(size: self.size)
    let transition = SKTransition.fadeWithDuration(NSTimeInterval(1.0))
    self.view?.presentScene(scene, transition: transition)
  }
  
  public override func didMoveToView(view: SKView) {
    // 省略

    self.webView.alpha = 0.0

    // 省略
    
    UIView.animateWithDuration(NSTimeInterval(1.5)) {
      self.webView.alpha = 1.0
    }
  }
  
  // 省略
}

こちらもやっていることは簡単。
ButtonNodeObserverプロトコルに準拠するようにして、Exitボタンが押されたときに、スタート画面に遷移するようにしている。

ただし、ちょっと気をつけないといけないのが、RuleScene#didMoveToView(_: SKView)およびRuleScene#willMoveFromView(_: SKView)の呼ばれるタイミング。
これらはそれぞれ、RuleSceneがSKViewに追加された直後、および、SKViewから削除される直前に呼ばれ、トランジションによる画面効果(フェードイン/フェードアウト)は、didMoveToViwe()が呼ばれた後、および、willMoveFromView()が呼ばれる前に表れる。
すなわち、時系列で表すと、

  1. SKViewにRuleSceneを表示しようとする
  2. didMoveToView()が呼ばれる
  3. トランジションによるフェードイン
  4. ルール画面が表示される

および、

  1. SKViewにStartSceneを表示しようとする
  2. トランジションによるフェードアウト
  3. willMoveFromView()が呼ばれる
  4. スタート画面が表示される

という感じになっている。
このため、単にdidMoveToView()でWKWebViewの追加/willMoveFromView()でWKWebViewの削除を行うと、シーンはフェードイン/フェードアウトしているのに、WKWebViewはその間もそのまま表示されることになってしまう。

これを防ぐために、UIViewのアニメーション機能を使って、didMoveToView()ではWKWebViewのアルファを0.0→1.0へ、逆にbuttonIsSelected()ではWKWebViewのアルファを1.0→0.0へ変化させるようにしている。
これによって、RuleSceneがフェードイン/フェードアウトしているときに同じようにフェードイン/フェードアウトしているように見せかけている。
(なお、アニメーションのデュレーションが若干違うのは、その方が見栄えがよかったから)

動作確認

さて、これを動かしてみると、ちゃんと遷移できてるのが分かると思う。

今日はここまで!