【Godot Engine】画面遷移時のアニメーションのやり方を検討してみる

前回

erudoru.hatenablog.com

読み込みスクリプト

前回とほぼ同じですが、今回の用途から少しだけ修正。読み込み完了の状態を保持しておくように finished を追加しました。

SceneLoader.gd

extends Node

# 読込進捗通知シグナル
signal _scene_loading(percent)
# 読込完了シグナル
signal _loaded_scene(scene)
# 読込失敗シグナル
signal _scene_load_error

# ローディング実行時間
const limit_msec = 100
# ローダー
var loader
# 読み込み完了
var finished = false

# 対象シーンパス設定
func set_target_scene(path):
    # ローダー作成
    loader = ResourceLoader.load_interactive(path)
    if loader == null:
        return FAILED
    return OK

# ローディング処理
func process(delta):
    if loader == null || finished:
        return
    var time = OS.get_ticks_msec()
    while OS.get_ticks_msec() < time + limit_msec:
        var ret = loader.poll()
        if ret == OK:
            # 読み込み実行
            continue
        elif ret == ERR_FILE_EOF:
            # 読み込み完了
            finished = true
            emit_signal('_loaded_scene', loader.get_resource())
            return
        else:
            # 読み込み失敗
            emit_signal('_scene_load_error')
            loader = null
            return
    # 進捗通知
    var p = float(loader.get_stage() + 1) / float(loader.get_stage_count())
    emit_signal('_scene_loading', p)

自動ロード

今回は使用しません。登録済みの SceneLoader.gd は解除します。

サンプルシーン作成

今回も3つのシーンを作成します。

  • FromScene.tscn ・・・ 遷移元画面
  • ToScene.tscn ・・・ 遷移先画面
  • Transition.tscn ・・・ ローディング、アニメーション用Node。FromScene と ToScene に組み込んで使用する。

画面遷移用 Node

ルートは ColorRect でカラーは黒を設定します。子にアニメーション用の Tween を追加します。画面表示時用と画面終了用の2つを用意しておきます。

f:id:erudoru:20180402221408p:plain

簡単にフェードイン・フェードアウトアニメーションのみです。

Transition.gd

extends ColorRect

var scene_loader = preload('res://SceneLoader.gd').new()
var next_scene
var exit_anim_completed

# シーン変更
func change_scene(target_path):
    scene_loader.set_target_scene(target_path)
    _start_exit_anim()

func _enter_tree():
    scene_loader.connect("_scene_loading", self, "_on_scene_loading")
    scene_loader.connect("_loaded_scene", self, "_on_loaded_scene")
    scene_loader.connect("_scene_load_error", self, "_on_scene_load_error")
    # 画面表示アニメーション開始
    _start_enter_anim()

func _exit_tree():
    scene_loader.disconnect("_scene_loading", self, "_on_scene_loading")
    scene_loader.disconnect("_loaded_scene", self, "_on_loaded_scene")
    scene_loader.disconnect("_scene_load_error", self, "_on_scene_load_error")

func _process(delta):
    scene_loader.process(delta)

# Enterアニメーション
func _start_enter_anim():
    # Nodeを表示する
    visible = true
    # アニメーション
    $EnterAnim.interpolate_property(
        self,
        "color",
        Color(1, 1, 1, 1),
        Color(1, 1, 1, 0),
        1,
        Tween.TRANS_LINEAR, Tween.EASE_IN)
    $EnterAnim.start()

# Exitアニメーション
func _start_exit_anim():
    # Nodeを表示する
    visible = true
    # アニメーション
    $ExitAnim.interpolate_property(
        self,
        "color",
        Color(1, 1, 1, 0),
        Color(1, 1, 1, 1),
        1,
        Tween.TRANS_LINEAR, Tween.EASE_IN)
    $ExitAnim.start()

# 画面遷移
func _next_scene():
    # Scene読み込み済み、アニメーション終了済みであれば画面遷移する
    if next_scene and exit_anim_completed:
        visible = false
        get_tree().change_scene_to(next_scene)

# Enterアニメーション完了処理
func _on_EnterAnim_tween_completed(object, key):
    # Nodeを非表示
    visible = false

# Exitアニメーション完了処理
func _on_ExitAnim_tween_completed(object, key):
    exit_anim_completed = true
    # 画面遷移
    _next_scene()

# ローディング中
func _on_scene_loading(p):
    # ローディング中の画面表示を更新
    print("Loading... %d" % [int(p * 100)])

# ロード完了
func _on_loaded_scene(scene):
    next_scene = scene
    # 画面遷移
    _next_scene()

# ロード失敗
func _on_scene_load_error(error_type):
    # エラーの場合の表示
    print('error:' + str(error_type))

遷移元画面

ボタン一つと、一番ツリーの下に Transition を追加します。

f:id:erudoru:20180402221228p:plain

FromScene.gd

extends Sprite

func _on_Button_pressed():
    $Transition.change_scene('res://ToScene.tscn')

遷移先画面

こちらも同様

f:id:erudoru:20180402221742p:plain

ToScene.gd

extends Sprite

func _on_Button_pressed():
    $Transition.change_scene('res://FromScene.tscn')

動作確認

f:id:erudoru:20180402222632g:plain