【Pixi.js】切り替え:スライド

シーン切り替え:フェード Pixi.js
シーン切り替え:フェード

はじめに

Pixi.jsについて学んだことの備忘録。
シーン切り替え(フェード)について。

ここではPixi.jsのver4を使用しています。
最新版では書き方が全然違うため動かないため注意が必要です。

シーン切り替え:フェード

場面Aから場面Bにシーンを切り替えたい。
スライド式以外のやり方もやってみよう。

サンプルはこちら

画面をタッチすると、シーンAとシーンBが切り替わります。
画面が暗くなり、明るくなった時にはシーンが変わっている!
全然別のシーンでも違和感なく繋げられそうですね。
(前回は連打するとおかしかったので、今回はその対策もしました)

コードは下記のとおり。

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>シーン切替(フェードスライド) Pixi.js</title>
    <script src="../../pixi.min.js"></script>
</head>

<body style="margin: 0; overflow: hidden;">
    <script>
        // Pixi.jsのアプリケーションを作成
        const app = new PIXI.Application({
            width: 360,                 // 画面の横幅
            height: 548,                // 画面の縦幅
            backgroundColor: 0xcccccc,  // 背景色を設定
        })

        // appをbodyに追加
        document.body.appendChild(app.view);

        // シーンA
        const sceneA = new PIXI.Container();
        const backgroundA = new PIXI.Graphics();
        backgroundA.beginFill(0xFFD1D1);
        backgroundA.drawRect(0, 0, app.screen.width, app.screen.height);
        backgroundA.endFill();
        sceneA.addChild(backgroundA);
        const textA = new PIXI.Text('シーンA', { fontSize: 50, fill: 0x000000 });
        textA.anchor.set(0.5);
        textA.x = app.screen.width / 2;
        textA.y = app.screen.height / 2;
        sceneA.addChild(textA);

        // シーンB
        const sceneB = new PIXI.Container();
        const backgroundB = new PIXI.Graphics();
        backgroundB.beginFill(0xA8D0E6);
        backgroundB.drawRect(0, 0, app.screen.width, app.screen.height);
        backgroundB.endFill();
        sceneB.addChild(backgroundB);
        const textB = new PIXI.Text('シーンB', { fontSize: 50, fill: 0x000000 });
        textB.anchor.set(0.5);
        textB.x = app.screen.width / 2;
        textB.y = app.screen.height / 2;
        sceneB.addChild(textB);

        // フェードエフェクトのシーン
        const blackout = new PIXI.Graphics();
        blackout.beginFill(0x000000);
        blackout.drawRect(0, 0, app.screen.width, app.screen.height);
        blackout.endFill();
        blackout.alpha = 0;
        app.stage.addChild(sceneA);
        app.stage.addChild(blackout);

        let currentScene = 'A';
        let isTransitioning = false;

        // シーン切替(フェード)
        function switchScene() {
            if (isTransitioning) return;
            isTransitioning = true;
            blackout.alpha = 0;
            app.stage.addChild(blackout);
            let fadeIn = true;
            let fadeOut = false;

            function fadeEffect(delta) {
                if (fadeIn) {
                    blackout.alpha += delta * 0.05;
                    if (blackout.alpha >= 1) {
                        blackout.alpha = 1;
                        fadeIn = false;
                        fadeOut = true;
                        if (currentScene === 'A') {
                            app.stage.removeChild(sceneA);
                            app.stage.addChild(sceneB);
                            currentScene = 'B';
                        } else {
                            app.stage.removeChild(sceneB);
                            app.stage.addChild(sceneA);
                            currentScene = 'A';
                        }
                        app.stage.addChild(blackout);
                    }
                } else if (fadeOut) {
                    blackout.alpha -= delta * 0.05;
                    if (blackout.alpha <= 0) {
                        blackout.alpha = 0;
                        fadeOut = false;
                        isTransitioning = false;
                        app.stage.removeChild(blackout);
                        app.ticker.remove(fadeEffect);
                    }
                }
            }

            app.ticker.add(fadeEffect);
        }

        app.view.addEventListener('pointerdown', switchScene);

    </script>
</body>

</html>

◆メインの処理を抜粋

// シーン切替(フェード)
function switchScene() {
    if (isTransitioning) return;
    isTransitioning = true;
    blackout.alpha = 0;
    app.stage.addChild(blackout);
    let fadeIn = true;
    let fadeOut = false;

    function fadeEffect(delta) {
        if (fadeIn) {
            blackout.alpha += delta * 0.05;
            if (blackout.alpha >= 1) {
                blackout.alpha = 1;
                fadeIn = false;
                fadeOut = true;
                if (currentScene === 'A') {
                    app.stage.removeChild(sceneA);
                    app.stage.addChild(sceneB);
                    currentScene = 'B';
                } else {
                    app.stage.removeChild(sceneB);
                    app.stage.addChild(sceneA);
                    currentScene = 'A';
                }
                app.stage.addChild(blackout);
            }
        } else if (fadeOut) {
            blackout.alpha -= delta * 0.05;
            if (blackout.alpha <= 0) {
                blackout.alpha = 0;
                fadeOut = false;
                isTransitioning = false;
                app.stage.removeChild(blackout);
                app.ticker.remove(fadeEffect);
            }
        }
    }

    app.ticker.add(fadeEffect);
}

0.連打対策
処理実行時にフラグを立て、フラグが立っていたら何もせずに返しています
if (isTransitioning) return;
isTransitioning = true;

1.フェード用のコンテナを追加
フェード演出用のコンテナを画面に追加(この時点では透明で黒くない状態)
(シーンの切り替えで画面の前後関係が変わるので、毎回必ず追加する)
app.stage.addChild(blackout);

2.フェードイン、画面を徐々に暗くする
おなじみdeltaを使って透明度を徐々に下げ、画面を黒くする。
function fadeEffect(delta) {
if (fadeIn) {
blackout.alpha += delta * 0.05;

3.シーンの切り替え
真っ暗になったら現在のシーンを削除して、新しいシーンを追加する。
if (blackout.alpha >= 1) {
blackout.alpha = 1;
fadeIn = false;
fadeOut = true;
if (currentScene === ‘A’) {
app.stage.removeChild(sceneA);
app.stage.addChild(sceneB);
currentScene = ‘B’;

4.フェードアウト
フェード演出用コンテナの透明度を徐々に上げて、画面を見えるようにする。
} else if (fadeOut) {
blackout.alpha -= delta * 0.05;
if (blackout.alpha <= 0) {
blackout.alpha = 0;
fadeOut = false;
isTransitioning = false;
app.stage.removeChild(blackout);
app.ticker.remove(fadeEffect);
}

こんな感じです。よく見るやつですがちゃんと動くと嬉しい。

おわりに

きっと一番使いやすいシーン切り替え。
真っ暗じゃなくて真っ白のパターンもありますね。
フェード演出用コンテナの背景色を変えれば好きな色でフェードできるはず。

2週連続のシーン切り替え演出でした。
今週はゲームを公開したかったのだけど製作が間に合わず。

やりたいことはたくさんあるけど思うようにはいかないものです!
健康第一で楽しく過ごしましょう。

おわり

コメント

タイトルとURLをコピーしました