[phina.js]
ノベルゲームの作り方
今回の記事は、”【ノベルゲーム】櫻の樹の下には” でのメインシーンのソースコードを晒しつつ、phina.jsを使ったノベルゲームの作り方について書いていこうと思います。
また、探索・脱出ゲームの作り方の方が知りたい方はこちらの記事がオススメです。
準備
今回の記事では、ローカルサーバー上で動作させる事を前提に進めさせていただきます。いくつか背景用の画像をご用意いただき、assetsに読み込ませてください。もしなければ、どこかのフリー素材サイト様から探してくるか、または、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