サイトアイコン ほろほろりドットコム

[phina.js] ノベルゲームの作り方

ノベルゲーム phina.js 桜の樹の下には

[phina.js]
ノベルゲームの作り方




今回の記事は、”【ノベルゲーム】櫻の樹の下には” でのメインシーンのソースコードを晒しつつ、phina.jsを使ったノベルゲームの作り方について書いていこうと思います。

また、探索・脱出ゲームの作り方の方が知りたい方はこちらの記事がオススメです。

準備

今回の記事では、ローカルサーバー上で動作させる事を前提に進めさせていただきます。いくつか背景用の画像をご用意いただき、assetsに読み込ませてください。もしなければ、どこかのフリー素材サイト様から探してくるか、または、Code and Materialで公開しているイラストをご利用ください。

Code and Material

ソースコードの雛型として置いておきます。

<script src='https://cdn.jsdelivr.net/gh/phi-jp/phina.js@0.2.2/build/phina.js'></script>
// グローバル領域に展開
phina.globalize();

// アセット
const ASSETS = {
    // 画像
    image: {
        "img":"背景画像のパス",
    }
};

/*
 * メインシーン
 */
phina.define("MainScene",{
  // 継承
  superClass:"DisplayScene",
  // コンストラクタ
  init: function(){
    // 親クラスの初期化
    this.superInit();
    // ここに処理を書く
  },
  // 更新
  update: function(){
  
  },
});

/*
 * メイン処理
 */
phina.main(() => {
   // アプリケーションを生成
   const app = GameApp({
     // MainSceneから開始
     startLabel: "main",
     // アセット
     assets: ASSETS
   });
   // fps表示
   //app.enableStats();
   // 実行
   app.run();
});

制作方法においてのポイント

テキスト表示&文字送りのシステムについては、本当にほとんど変えずに、simiraaaa氏のLabelAreaサンプルを使わせて(パクらせて)いただいたので、ここで深く感謝(と謝罪)を述べさせていただきます。本当にありがとうございましたm(_ _)m

表示テキスト

(LabelAreaサンプルの形式がそうだったのもあり)私の場合、表示させたい文章を、以下のように区切って、 配列として最初にまとめて作っておく方式をとりました。最後、””を作っているのは、次のシーンへ遷移させる為に余分に一つに作っておいているのです。

※ノベルゲーム『櫻の樹の下には』、及び、ここで使っているテキストのデータは、青空文庫様からお借りしました。
https://www.aozora.gr.jp/cards/000074/card427.html

const MAINNTEXTS = [
    "桜の樹の下には屍体《したい》が\n埋まっている!",
    "これは信じていいことなんだよ。",
    "何故《なぜ》って、\n桜の花があんなにも見事に咲くなんて\n信じられないことじゃないか。",
    "俺はあの美しさが信じられないので、\nこの二三日不安だった。",
    "しかしいま、やっとわかるときが来た。",
    "桜の樹の下には屍体が埋まっている。",
    "これは信じていいことだ。",
    "どうして俺が毎晩家へ帰って来る道で、\n俺の部屋の数ある道具のうちの、\n選《よ》りに選って\nちっぽけな薄っぺらいもの、\n安全剃刀の刃なんぞが、千里眼のように\n思い浮かんで来るのか",
    "――おまえはそれがわからないと言ったが\n――そして俺にもやはりそれがわからないのだが\n――それもこれもやっぱり同じようなことに\nちがいない。",
    "いったいどんな樹の花でも、\nいわゆる真っ盛りという状態に達すると、\nあたりの空気のなかへ\n一種神秘な雰囲気を撒き散らすものだ。",
    "それは、\nよく廻った独楽《こま》が完全な静止に\n澄むように、",
    "また、\n音楽の上手な演奏が\nきまってなにかの幻覚を伴うように、",
    "灼熱《しゃくねつ》した生殖の幻覚させる\n後光のようなものだ。",
    "それは人の心を撲《う》たずにはおかない、\n不思議な、生き生きとした、美しさだ。",
    "しかし、\n昨日、一昨日、\n俺の心をひどく陰気にしたものもそれなのだ。",
    "俺にはその美しさがなにか\n信じられないもののような気がした。",
    "俺は反対に\n不安になり、\n憂鬱《ゆううつ》になり、\n空虚な気持になった。",
    "しかし、俺はいまやっとわかった。",
    "おまえ、\nこの爛漫《らんまん》と咲き乱れている\n桜の樹の下へ、一つ一つ屍体が埋まっていると\n想像してみるがいい。\n何が俺をそんなに不安にしていたかが\nおまえには納得がいくだろう。",
    "馬のような屍体、犬猫のような屍体、\nそして人間のような屍体、屍体はみな\n腐爛《ふらん》して蛆《うじ》が湧き、\n堪《たま》らなく臭い。",
    "それでいて水晶のような液を\nたらたらとたらしている。",
    "桜の根は貪婪《どんらん》な蛸《たこ》の\nように、それを抱きかかえ、\nいそぎんちゃくの食糸のような\n毛根を聚《あつ》めて、その液体を\n吸っている。",
    "何があんな花弁を作り、\n何があんな蕊《しべ》を作っているのか、",
    "俺は毛根の吸いあげる水晶のような液が、\n静かな行列を作って、維管束のなかを\n夢のようにあがってゆくのが見えるようだ。",
    "――おまえは何をそう苦しそうな顔を\nしているのだ。美しい透視術じゃないか。",
    "俺はいまようやく瞳《ひとみ》を据えて\n桜の花が見られるようになったのだ。\n昨日、一昨日、\n俺を不安がらせた神秘から自由になったのだ。",
    "二三日前、\n俺は、ここの溪《たに》へ下りて、\n石の上を伝い歩きしていた。",
    "水のしぶきのなかからは、\nあちらからもこちらからも、\n薄羽かげろうがアフロディットのように\n生まれて来て、溪の空をめがけて\n舞い上がってゆくのが見えた。",
    "おまえも知っているとおり、\n彼らはそこで美しい結婚をするのだ。",
    "しばらく歩いていると、\n俺は変なものに出喰《でく》わした。",
    "それは溪の水が乾いた磧《かわら》へ、\n小さい水溜を残している、\nその水のなかだった。",
    "思いがけない石油を流したような光彩が、\n一面に浮いているのだ。",
    "おまえはそれを何だったと思う。",
    "それは何万匹とも数の知れない、\n薄羽かげろうの屍体だったのだ。",
    "隙間なく水の面を被っている、\n彼らのかさなりあった翅《はね》が、\n光にちぢれて\n油のような光彩を流しているのだ。",
    "そこが、\n産卵を終わった彼らの墓場だったのだ。",
    "俺はそれを見たとき、\n胸が衝《つ》かれるような気がした。\n墓場を発《あば》いて\n屍体を嗜《この》む変質者のような\n残忍なよろこびを俺は味わった。",
    "この溪間では\nなにも俺をよろこばすものはない。",
    "鶯《うぐいす》や四十雀《しじゅうから》も、\n白い日光をさ青に煙らせている木の若芽も、\nただそれだけでは、\nもうろうとした心象に過ぎない。",
    "俺には惨劇が必要なんだ。\nその平衡があって、\nはじめて俺の心象は明確になって来る。",
    "俺の心は悪鬼のように憂鬱に渇いている。\n俺の心に憂鬱が完成するときにばかり、\n俺の心は和《なご》んでくる。",
    "――おまえは腋《わき》の下を\n拭《ふ》いているね。\n冷汗が出るのか。\nそれは俺も同じことだ。",
    "何もそれを不愉快がることはない。\nべたべたとまるで精液のようだと\n思ってごらん。",
    "それで俺達の憂鬱は完成するのだ。",
    "ああ、\n桜の樹の下には屍体が埋まっている!",
    "いったいどこから浮かんで来た空想か\nさっぱり見当のつかない屍体が、\nいまはまるで桜の樹と一つになって、\nどんなに頭を振っても離れてゆこうとは\nしない。",
    "今こそ俺は、\nあの桜の樹の下で\n酒宴をひらいている村人たちと同じ権利で、\n花見の酒が呑《の》めそうな気がする。",
    ""
];

テキスト表示&文字送り

まずは先述の通り、主軸となる文字送りシステムを、simiraaaa氏作成のサンプルから、ほとんど変えずに持ってきます。私の場合は、テキストの背景となるRectangleShapeにまとめて、一つのオブジェクトとしてしまいました。

/***************************************
 * テキスト表示&文字送り
 */
phina.define("LabelRect", {
    superClass: "RectangleShape",
    init: function () {
        this.superInit({
            cornerRadius: 5,
            width: 630,
            height: 280,
            stroke: "white",
            fill: "#eee"
        });
        this.alpha = 0.8;

        // テキスト表示用LabelAreaクラス
        this.labelArea = LabelArea({
            text: "",
            width: 600,
            height: 240,
            fontSize: FONT_SIZE
        }).addChildTo(this);

        this.texts = [];
        this.textIndex = 0;
        this.charIndex = 0;

        // 次のテキスト合図の▽
        this.nextTriangle = TriangleShape({
            fill: "black",
            stroke: false,
            radius: FONT_SIZE / 2
        }).addChildTo(this)
            .setPosition(280, 100);
        this.nextTriangle.rotation = 180;
        this.nextTriangle.hide();

    },
    showAllText: function () {
        let text = this.texts[this.textIndex];
            this.labelArea.text = text;
            this.textAll = true;
            this.charIndex = text.length;
        },

    clearText: function () {
        this.labelArea.text = "";
    },

    nextText: function () {
        this.clearText();
        ++this.textIndex
        this.charIndex = 0;
        this.addChar();
    },
    addChar: function () {
        this.labelArea.text += this.getChar();
    },
    getChar: function () {
       let text = this.texts[this.textIndex];
       if (text.length <= this.charIndex) {
           this.textAll = true;
           return "";
       } else {
           this.textAll = false;
           return text[this.charIndex++];
       }
    }
});

これをメインシーンで生成し、 このRabelRectクラスのthis.textsプロパティに、前項のMAINNTEXTSを格納して使うわけです。

/***************************************
 * メインシーン
 */
phina.define("MainScene", {
    superClass: "DisplayScene",
    init: function () {
        this.superInit();

        // 背景色
        this.backgroundColor = "black";

        // 背景用グループ
        this.backImageGroup = DisplayElement().addChildTo(this);

        // テキストエリアの矩形
        this.labelRect = LabelRect().addChildTo(this)
            .setPosition(this.gridX.center(), this.gridY.center(5.5));

        this.labelRect.texts = MAINNTEXTS;
        this.labelRect.textIndex = 0;
        this.labelRect.charIndex = 0;

        this.setPhase();
    },
/*
 * 省略 
 */

そして、メインシーンのupdateのところで、テキストの文字送り、全部のテキストを表示、次のテキストへの切り替えを管理します。

/*
*省略
*/
// 更新
update: function (app) {
    //クリックかEnterキーの入力があった場合
    if (app.pointer.getPointingStart() || app.keyboard.getKeyDown("enter")) {
        if (this.labelRect.textAll) {//テキスト全部表示済み
            this.labelRect.nextText();
            // 次の背景に切替
            this.setPhase();
        } else {
            this.labelRect.showAllText();
        }
    } else {
        this.labelRect.addChar();
    }

    if (this.labelRect.textAll) {
        this.labelRect.nextTriangle.show();
    } else {
        this.labelRect.nextTriangle.hide();
    }
},
/*
*省略
*/

背景画像・音楽素材・場面を管理

前項のinit内の最後のところやupdate内にある、this.setPhase()という、メインシーンに紐付けされているメソッドを使って、背景画像・音楽素材・場面を管理します。RabelRectオブジェクトのtextIndexプロパティ(何番目の文章かのカウント)の数値で、背景や音の処理を進行させていく方式をとりました。
因みに、この時、背景画像をほとんど640×960の大きさに統一して、引数にアセット名を入れたら、それだけで画面中央に表示されるようにするメソッド、setBackImg()を作って管理しました。

前項のupdateの中で、このsetPhase()メソッドを呼び出すようにしています。具体的に説明すると、その時の分の全部の文章が読み込まれた後に、クリックかEnterキーが押された場合、文章が進みます。その毎に、一緒に画像・音楽の切り替えを行っています。

画像の操作についてや、tweenerクラスによるアニメーション設定は、alkn203氏の記事に解説を丸投げさせていただきます。

ちなみに、サウンドの操作については、過去に書いた記事がありますので、わからなければご参考にどうぞ。

/*
*省略
*/
setPhase: function () {
    switch (this.labelRect.textIndex) {
        case 0:
            //メインBGM再生
            SoundManager.playMusic("piano23_bgm");
            //桜木・桜の絨毯画像フェードイン
            this.cherryCarpet2 = this.setBackImg("cherry_carpet2");
            this.cherryCarpet2.alpha = 0;
            this.cherryCarpet2.tweener.clear().to({ alpha: 1 }, 200).play();
            //抽象的な歪みの画像フェードイン
            this.dandan = this.setBackImg("dandan");
            this.dandan.alpha = 0;
            this.dandan.tweener.clear().to({ alpha: 0.3 }, 200).play();
            break;
        case 7:
            //桜木・桜の絨毯画像フェードアウト
            this.cherryCarpet2.tweener.clear().to({ alpha: 0 }, 1000).play();
            //抽象的な歪みの画像フェードアウト
            this.dandan.tweener.clear().to({ alpha: 0 }, 1000).play();
            // カミソリ画像フェードイン
            this.razorBlade = this.setBackImg("razor_blade");
            this.razorBlade.alpha = 0;
            this.razorBlade.tweener.clear().to({ alpha: 1 }, 1000).play();
            break;
        case 9:
            //カミソリ画像フェードアウト
            this.razorBlade.tweener.clear().to({ alpha: 0 }, 1000).play();

            // 桜画像フェードイン
            this.cherry = this.setBackImg("cherry_blossoms");
            this.cherry.alpha = 0;
            this.cherry.tweener.clear().to({ alpha: 1 }, 1000).play();
            break;
        case 10:
            //桜画像フェードアウト
            this.cherry.tweener.clear().to({ alpha: 0 }, 1000).play();

            //桜木・桜の絨毯画像削除
            this.cherryCarpet2.remove();
            //抽象的な歪みの画像削除
            this.dandan.remove();
            //カラフルライン生成・フェードイン
            this.colorfulLines = ColorfulLines().addChildTo(this.backImageGroup)
                .setPosition(this.gridX.center(), this.gridY.center());
            this.colorfulLines.alpha = 0;
            this.colorfulLines.tweener.clear().to({ alpha: 1 }, 1000).play();
            //エフェクト01SE再生
            SoundManager.play("effect01_se");
            break;

        case 14:
            //カラフルラインフェードアウト
            this.colorfulLines.tweener.clear().to({ alpha: 0 }, 1000).play();

            //抽象的な歪みの画像フェードイン
            this.dandan = this.setBackImg("dandan");
            this.dandan.alpha = 0;
            this.dandan.tweener.clear().to({ alpha: 1 }, 1000).play();
            break;

        case 15:
            //カミソリ画像削除
            this.razorBlade.remove();
            //カラフルライン削除
            this.colorfulLines.remove();
            //桜画像フェードイン
            this.cherry.tweener.clear().to({ alpha: 1 }, 1000).play();
            //抽象的な歪みの画像半透明化
            this.dandan.tweener.clear().to({ alpha: 0.4 }, 1000).play();

            break;
        case 18:
            //桜画像フェードアウト
            this.cherry.tweener.clear().to({ alpha: 0 }, 1000).play();
            //抽象的な歪みの画像不透明化
            this.dandan.tweener.clear().to({ alpha: 1 }, 1000).play();
            //桜の絨毯画像フェードイン
            this.cherryCarpet = this.setBackImg("cherry_carpet");
            this.cherryCarpet.alpha = 0;
            this.cherryCarpet.tweener.clear().to({ alpha: 0.6 }, 1000).play();
            break;
        case 21:
            //マンデルブロ集合体フェードイン
            this.mandelbrot = this.setBackImg("mandelbrot");
            this.mandelbrot.setPosition(-50, 500);
            this.mandelbrot.alpha = 0;
            this.mandelbrot.tweener.clear().to({ alpha: 0.5 }, 1000)
                .to({ x: 0, y: 700, scaleX: 1.6, scaleY: 1.6 }, 4000).play();
            break;
        case 22:
            //マンデルブロ集合体フェードアウト
            this.mandelbrot.tweener.to({ alpha: 0 }, 1000).play();
            //スパイラルライン
            this.spiral = SpiralLine().addChildTo(this.backImageGroup).setPosition(this.gridX.center(), this.gridY.center());
            this.spiral.alpha = 0;
            this.spiral.tweener.clear().to({ alpha: 0.6 }, 4000).play();
            break;
        case 24:
            // 抽象的な歪画像フェードアウト
            this.dandan.tweener.clear().to({ alpha: 0 }, 3000).play();
            //桜の絨毯画像フェードアウト
            this.cherryCarpet.tweener.clear().to({ alpha: 0 }, 3000).play();
            //スパイラルラインフェードアウト
            this.spiral.tweener.clear().to({ alpha: 0 }, 3000).play();
            break;
        case 26:
            //メインBGMフェードアウト
            SoundManager.stopMusic(1000);
            //雫画像
            this.drop = this.setBackImg("drop");
            this.drop.alpha = 0;
            this.drop.tweener.clear().to({ alpha: 1 }, 1000).play();

            //川BGMフェードイン
            this.river = SoundManager.playMusic("river_bgm", 700);
            break;
        case 27:
            //マンデルブロ集合体・スパイラルライン削除
            this.mandelbrot.remove();
            this.spiral.remove();
            //水滴SE再生
            SoundManager.play("drop_se");
            break;
        case 28:
            //雫画像フェードアウト
            this.drop.tweener.to({ alpha: 0 }, 2400).play();
            break;
        case 31:
            //川BGMフェードアウト
            SoundManager.stopMusic(2000);
            //油画像
            this.oil = this.setBackImg("oil");
            this.oil.blendMode = "lighter";
            this.oil.alpha = 0;
            this.oil.tweener.clear().to({ alpha: 1 }, 6000).play();
            break;
        case 36:
            //BGM再生していたら、ストップ
            SoundManager.currentMusic = null;
            //心臓音SE再生
            SoundManager.play("heart_beat05_se");
            //パーリンノイズ画像表示
            this.perlin = this.setBackImg("perlin").addChildTo(this);
            this.perlin.alpha = 0.3;
            this.perlin.blendMode = "lighter";
            //抽象的な歪みの画像
            this.dandan = this.setBackImg("dandan");
            this.dandan.blendMode = "lighter";
            this.dandan.alpha = 0;
            this.dandan.tweener.clear().to({ alpha: 0.5, scaleX: 2, scaleY: 2 }, 600)
                .to({ alpha: 0, scaleX: 1, scaleY: 1 }, 1200).play();
            break;
        case 37:
            //エンディングBGMフェードイン
            SoundManager.playMusic("sinfonia01_bgm", 10000);
            break;
        case 41:
            this.oil.tweener.clear().to({ alpha: 0 }, 6000).play();
            break;
        case 44:
            //桜画像フェードイン
            this.cherry.tweener.clear().to({ alpha: 1 }, 2500).play();
            this.oil.tweener.clear().to({ alpha: 1 }, 1000)
                .to({ alpha: 0 }, 1500).play();
            this.dandan.tweener.clear().to({ alpha: 1 }, 1000)
                .to({ alpha: 0 }, 1500).play();
            break;
        case 47:
            this.exit();
            break;
    }
},
// 背景画像セット
setBackImg: function (imgName) {
    let img = Sprite(imgName).addChildTo(this.backImageGroup)
        .setPosition(this.gridX.center(), this.gridY.center());
    return img;
}
/*
*省略
*/

メインシーンのソースコード全文

/***************************************
 * メインシーン
 */
phina.define("MainScene", {
    superClass: "DisplayScene",
    init: function () {
        this.superInit();

        // 背景色
        this.backgroundColor = "black";

        // 背景用グループ
        this.backImageGroup = DisplayElement().addChildTo(this);

        // テキストエリアの矩形
        this.labelRect = LabelRect().addChildTo(this)
            .setPosition(this.gridX.center(), this.gridY.center(5.5));

        this.labelRect.texts = MAINNTEXTS;
        this.labelRect.textIndex = 0;
        this.labelRect.charIndex = 0;

        this.setPhase();
    },
    update: function (app) {
        //クリックかEnterキーの入力があった場合
        if (app.pointer.getPointingStart() || app.keyboard.getKeyDown("enter")) {
            if (this.labelRect.textAll) {//テキスト全部表示済み
                this.labelRect.nextText();
                // 次の背景に切替
                this.setPhase();
            } else {
                this.labelRect.showAllText();
            }
        } else {
            this.labelRect.addChar();
        }

        if (this.labelRect.textAll) {
            this.labelRect.nextTriangle.show();
        } else {
            this.labelRect.nextTriangle.hide();
        }
    },

    // 段階(場面)の管理 サウンドや画像の切り替え
    setPhase: function () {
        switch (this.labelRect.textIndex) {
            case 0:
                //メインBGM再生
                SoundManager.playMusic("piano23_bgm");
                //桜木・桜の絨毯画像フェードイン
                this.cherryCarpet2 = this.setBackImg("cherry_carpet2");
                this.cherryCarpet2.alpha = 0;
                this.cherryCarpet2.tweener.clear().to({ alpha: 1 }, 200).play();
                //抽象的な歪みの画像フェードイン
                this.dandan = this.setBackImg("dandan");
                this.dandan.alpha = 0;
                this.dandan.tweener.clear().to({ alpha: 0.3 }, 200).play();
                break;
            case 7:
                //桜木・桜の絨毯画像フェードアウト
                this.cherryCarpet2.tweener.clear().to({ alpha: 0 }, 1000).play();
                //抽象的な歪みの画像フェードアウト
                this.dandan.tweener.clear().to({ alpha: 0 }, 1000).play();
                // カミソリ画像フェードイン
                this.razorBlade = this.setBackImg("razor_blade");
                this.razorBlade.alpha = 0;
                this.razorBlade.tweener.clear().to({ alpha: 1 }, 1000).play();
                break;
            case 9:
                //カミソリ画像フェードアウト
                this.razorBlade.tweener.clear().to({ alpha: 0 }, 1000).play();

                // 桜画像フェードイン
                this.cherry = this.setBackImg("cherry_blossoms");
                this.cherry.alpha = 0;
                this.cherry.tweener.clear().to({ alpha: 1 }, 1000).play();
                break;
            case 10:
                //桜画像フェードアウト
                this.cherry.tweener.clear().to({ alpha: 0 }, 1000).play();

                //桜木・桜の絨毯画像削除
                this.cherryCarpet2.remove();
                //抽象的な歪みの画像削除
                this.dandan.remove();
                //カラフルライン生成・フェードイン
                this.colorfulLines = ColorfulLines().addChildTo(this.backImageGroup)
                    .setPosition(this.gridX.center(), this.gridY.center());
                this.colorfulLines.alpha = 0;
                this.colorfulLines.tweener.clear().to({ alpha: 1 }, 1000).play();
                //エフェクト01SE再生
                SoundManager.play("effect01_se");
                break;

            case 14:
                //カラフルラインフェードアウト
                this.colorfulLines.tweener.clear().to({ alpha: 0 }, 1000).play();

                //抽象的な歪みの画像フェードイン
                this.dandan = this.setBackImg("dandan");
                this.dandan.alpha = 0;
                this.dandan.tweener.clear().to({ alpha: 1 }, 1000).play();
                break;

            case 15:
                //カミソリ画像削除
                this.razorBlade.remove();
                //カラフルライン削除
                this.colorfulLines.remove();
                //桜画像フェードイン
                this.cherry.tweener.clear().to({ alpha: 1 }, 1000).play();
                //抽象的な歪みの画像半透明化
                this.dandan.tweener.clear().to({ alpha: 0.4 }, 1000).play();

                break;
            case 18:
                //桜画像フェードアウト
                this.cherry.tweener.clear().to({ alpha: 0 }, 1000).play();
                //抽象的な歪みの画像不透明化
                this.dandan.tweener.clear().to({ alpha: 1 }, 1000).play();
                //桜の絨毯画像フェードイン
                this.cherryCarpet = this.setBackImg("cherry_carpet");
                this.cherryCarpet.alpha = 0;
                this.cherryCarpet.tweener.clear().to({ alpha: 0.6 }, 1000).play();
                break;
            case 21:
                //マンデルブロ集合体フェードイン
                this.mandelbrot = this.setBackImg("mandelbrot");
                this.mandelbrot.setPosition(-50, 500);
                this.mandelbrot.alpha = 0;
                this.mandelbrot.tweener.clear().to({ alpha: 0.5 }, 1000)
                    .to({ x: 0, y: 700, scaleX: 1.6, scaleY: 1.6 }, 4000).play();
                break;
            case 22:
                //マンデルブロ集合体フェードアウト
                this.mandelbrot.tweener.to({ alpha: 0 }, 1000).play();
                //スパイラルライン
                this.spiral = SpiralLine().addChildTo(this.backImageGroup).setPosition(this.gridX.center(), this.gridY.center());
                this.spiral.alpha = 0;
                this.spiral.tweener.clear().to({ alpha: 0.6 }, 4000).play();
                break;
            case 24:
                // 抽象的な歪画像フェードアウト
                this.dandan.tweener.clear().to({ alpha: 0 }, 3000).play();
                //桜の絨毯画像フェードアウト
                this.cherryCarpet.tweener.clear().to({ alpha: 0 }, 3000).play();
                //スパイラルラインフェードアウト
                this.spiral.tweener.clear().to({ alpha: 0 }, 3000).play();
                break;
            case 26:
                //メインBGMフェードアウト
                SoundManager.stopMusic(1000);
                //雫画像
                this.drop = this.setBackImg("drop");
                this.drop.alpha = 0;
                this.drop.tweener.clear().to({ alpha: 1 }, 1000).play();

                //川BGMフェードイン
                this.river = SoundManager.playMusic("river_bgm", 700);
                break;
            case 27:
                //マンデルブロ集合体・スパイラルライン削除
                this.mandelbrot.remove();
                this.spiral.remove();
                //水滴SE再生
                SoundManager.play("drop_se");
                break;
            case 28:
                //雫画像フェードアウト
                this.drop.tweener.to({ alpha: 0 }, 2400).play();
                break;
            case 31:
                //川BGMフェードアウト
                SoundManager.stopMusic(2000);
                //油画像
                this.oil = this.setBackImg("oil");
                this.oil.blendMode = "lighter";
                this.oil.alpha = 0;
                this.oil.tweener.clear().to({ alpha: 1 }, 6000).play();
                break;
            case 36:
                //BGM再生していたら、ストップ
                SoundManager.currentMusic = null;
                //心臓音SE再生
                SoundManager.play("heart_beat05_se");
                //パーリンノイズ画像表示
                this.perlin = this.setBackImg("perlin").addChildTo(this);
                this.perlin.alpha = 0.3;
                this.perlin.blendMode = "lighter";
                //抽象的な歪みの画像
                this.dandan = this.setBackImg("dandan");
                this.dandan.blendMode = "lighter";
                this.dandan.alpha = 0;
                this.dandan.tweener.clear().to({ alpha: 0.5, scaleX: 2, scaleY: 2 }, 600)
                    .to({ alpha: 0, scaleX: 1, scaleY: 1 }, 1200).play();
                break;
            case 37:
                //エンディングBGMフェードイン
                SoundManager.playMusic("sinfonia01_bgm", 10000);
                break;
            case 41:
                this.oil.tweener.clear().to({ alpha: 0 }, 6000).play();
                break;
            case 44:
                //桜画像フェードイン
                this.cherry.tweener.clear().to({ alpha: 1 }, 2500).play();
                this.oil.tweener.clear().to({ alpha: 1 }, 1000)
                    .to({ alpha: 0 }, 1500).play();
                this.dandan.tweener.clear().to({ alpha: 1 }, 1000)
                    .to({ alpha: 0 }, 1500).play();
                break;
            case 47:
                this.exit();
                break;
        }
    },
    // 背景画像セット
    setBackImg: function (imgName) {
        let img = Sprite(imgName).addChildTo(this.backImageGroup)
            .setPosition(this.gridX.center(), this.gridY.center());
        return img;
    }
});

おまけ – 画像以外で使ったオブジェクト

実際に”【ノベルゲーム】櫻の樹の下には”で使用した、画像以外のオブジェクトのご紹介。

  • ColorfulLines()
  • SpiralLine()

参考にさせていただいたサイト・ページ一覧

ご意見・ご感想、また、ここ間違ってるよとか、もっといい方法あるよといったご指摘などございましたら、お手数ですがコメント欄やtwitterアカウントほろほろり(@_horo_horori)へお願いしますm(_ _)m

モバイルバージョンを終了