投げモナボタンも実装できた!

ブツ

eyecatch.png

元リポジトリdistディレクトリをそのままコピペし、日本語化をほどこし、シナリオを適当に追加した。画像や音声などはフリー素材を使った。

以下タイトル画面でスタート(Start)ボタンを押すと開始する。

20220814092358_020.png

クレジット画面でmpurseによる投げモナボタンを設定できたことを確認した。また、名前をクリックすると各サイトを表示する。

20220814092413_020.png

ドキュメント

ドキュメントはサイトが重かったのでリポジトリ内にダウンロードしたものがある。画像はない。シナリオで使うコマンドはこのドキュメントでわかるはず。

前回まで

前回はMonogatariのデモを日本語化したが、これはバージョンが古くて1系だった。今回は2系を使う。実装方法が異なる。

ソースコード抜粋

engine/core/monogatari.js

ヘルプなどの定型句はengine/core/monogatari.jsファイル内にある。このファイルを開いて巻き戻しなどのヘルプにあるキーワードで検索するとヒットする。そのへんの変数をいじって好きに変えればよい。

...;n.default={AdvanceHelp:"ゲームを進めるためには、スペースキーを押すかクリックします",AllowPlayback:"Click here to allow audio playback",Audio:"オーディオ",AutoPlay:"自動",AutoPlayButton:"自動再生を有効にする",AutoPlaySpeed:"自動再生速度",Back:"巻き戻し",BackButton:"巻き戻し",Cancel:"キャンセル",Close:"閉じる",Confirm:"終了しますか?",Credits:"クレジット",Delete:"Delete",DialogLogButton:"ログを表示する",FullScreen:"全画面表示",Gallery:"Gallery",Help:"ヘルプ",Hide:"隠す",HideButton:"テキストを隠す",iOSAudioWarning:"iOSではオーディオ設定がサポートされていません",KeyboardShortcuts:"Keyboard Shortcuts",Language:"言語",Load:"ロード",LoadAutoSaveSlots:"自動的に保存されたゲーム",LoadButton:"ロード画面を開く",Loading:"読み込み中",LoadingMessage:"ファイルがロードされるのを待つ",LoadSlots:"保存されたゲーム",LocalStorageWarning:"このブラウザではローカルストレージは使用できません",Log:"ログ",Music:"音楽の音量",NewContent:"There is new content available, reload the page to get the latest version",NoSavedGames:"保存されたゲームはありません",NoAutoSavedGames:"自動的に保存されたゲームはありません",NoDialogsAvailable:"No dialogs available. Dialogs will appear here as they show up",OK:"OK",OrientationWarning:"Please rotate your device to play",Overwrite:"上書き",QuickButtons:"クイックメニューボタン",QuickMenu:"Quick Menu",Quit:"終了する",QuitButton:"ゲームを終了する",Resolution:"解像度",Save:"セーブ",SaveButton:"保存画面を開く",SaveInSlot:"スロットにセーブする",SelectYourLanguage:"Select your language",Settings:"環境設定",SettingsButton:"設定画面を開く",Show:"表示",Skip:"スキップ",SkipButton:"スキップモードに入る",SlotDeletion:"本当にこのスロットを削除しますか?",SlotOverwrite:"本当にこのスロットを上書きしますか?",Sound:"効果音の音量",Start:"スタート",Stop:"停止",TextSpeed:"テキストスピード",Video:"動画の音量",Voice:"ボイスの音量",Windowed:"窓"}},{}],bGeZK:[...

js/script.js

シナリオはこのファイル。ゲームに表示されるテキストや画像、音楽などを指定する。

特殊表示

monogatari.action 概要
message ダイアログを表示する
notification デスクトップ通知を表示する
particles パーティクルを表示する
canvas HTMLの<canvas>を表示する
credits タイトル画面のクレジットボタン先で表示される内容
gallery 画像ギャラリー画面の内容

素材定義

それぞれmusicのような種別名をもっている。assetsディレクトリ配下にそれと同じディレクトリがあり、そこに各種別のファイルを配置する。

monogatari.assets 概要
music 音楽ファイルのパスとシナリオ内における指定子
voices 声ファイルのパスとシナリオ内における指定子
sounds 効果音ファイルのパスとシナリオ内における指定子
videos 動画ファイルのパスとシナリオ内における指定子
images 画像ファイルのパスとシナリオ内における指定子
scenes 背景画像のファイルパスとシナリオ内における指定子

キャラクタ定義

monogatari.characters ({
	'y': {
            name: 'ユイ',
            color: '#ffca5b',
                directory: 'yui',
                sprites: {
                    'normal': 'josei06-167x300.png', // https://wataokiba.net/%e7%b4%a0%e6%9d%90%e4%b8%80%e8%a6%a7/
                }
	},
        'k': {
            name: 'キヨタカ',
            color: '#5bcaff',
            directory: 'kiyotaka',
            sprites: {
                'normal': 'dansei01-167x300.png', // https://wataokiba.net/%e7%b4%a0%e6%9d%90%e4%b8%80%e8%a6%a7/
            }
        },
});

ykはシナリオでキャラクタを指定する識別子として使う。spritesでは画像ファイルとその識別子を定義する。show characterコマンドでこれを指定して表示する。

nameはキャラ名として会話窓に表示される。colorはそのキャラ名を表示する色になる。directoryassets/charactersの配下にあるそのキャラクタの画像が入ったディレクトリを指定する。これによりspritesプロパティで指定する親パスを省略できる。

シナリオのソースコード抜粋

monogatari.action ('message').messages ({
	'Help': {
		title: 'ヘルプ',
		subtitle: 'リンク集',
		body: `
			<p><a href='https://developers.monogatari.io/documentation/'>ドキュメント</a> - あなたが知る必要があるすべて。</p>
			<p><a href='https://monogatari.io/demo/'>デモ</a> - 簡単なデモ。</p>
		`
	}
});
monogatari.action ('notification').notifications ({
	'Welcome': {
		title: 'ようこそ',
		body: 'これはMonogatariで作成したテストゲームです',
		icon: './assets/icons/icon_48x48.png'
	}
});
monogatari.action ('particles').particles ({});
monogatari.action ('canvas').objects ({});
monogatari.configuration ('credits', {
    "開発者": {
        "開発者": `<a href="https://ytyaru.github.io/" target="_blank" rel="noopener noreferrer">ytyaru</a><mpurse-send-button></mpurse-send-button><a href="https://ytyaru.github.io/Html.Mpurse.Api.20220517160403/setup.html" title="モナコインを使うには" target="_blank" rel="noopener noreferrer">?</a>`,
    },
    "フリー素材": {
        "背景": `<a href="http://www.aj.undo.jp/material/bg/bg_material.html" target="_blank" rel="noopener noreferrer">(c)安野譲</a>`,
        "立ち絵": `<a href="https://wataokiba.net/" target="_blank" rel="noopener noreferrer">わたおきば</a>`,
        "音楽": `<a href="http://ontama-m.com/ongaku_piano1.html" target="_blank" rel="noopener noreferrer">音楽の卵</a>`,
        "ボイス": `<a href="https://wingless-seraph.net/material-riyoukiyaku.html">ユーフルカ</a>`,
    }
});
monogatari.assets ('gallery', {});
monogatari.assets ('music', {
    'piano1_miagerusora': 'ontama_piano1_miagerusora.mp3', // http://ontama-m.com/ongaku_piano1.html
});
monogatari.assets ('voices', {
    'やるじゃねぇか': 'kiyotaka/17_nekketsu_damage.ogg',
});
monogatari.assets ('sounds', {});
monogatari.assets ('videos', {});
monogatari.assets ('images', {});
monogatari.assets ('scenes', {
    'room-night': 'house_room_weekly_apartment_c.jpg', // http://www.aj.undo.jp/material/bg/bg_material.html
});


// Define the Characters
monogatari.characters ({
	'y': {
            name: 'ユイ',
            color: '#ffca5b',
                directory: 'yui',
                sprites: {
                    'normal': 'josei06-167x300.png', // https://wataokiba.net/%e7%b4%a0%e6%9d%90%e4%b8%80%e8%a6%a7/
                }
	},
        'k': {
            name: 'キヨタカ',
            color: '#5bcaff',
            directory: 'kiyotaka',
            sprites: {
                'normal': 'dansei01-167x300.png', // https://wataokiba.net/%e7%b4%a0%e6%9d%90%e4%b8%80%e8%a6%a7/
            }
        },
});

monogatari.script ({
	// The game starts here.
	'Start': [
                'play music piano1_miagerusora with loop',
                'show scene room-night with fadeIn',
		'show notification Welcome',
		{
			'Input': {
				'Text': 'あなたの名前は?',
                                'Default': '山田太郎',
				'Validation': function (input) {
					return input.trim ().length > 0;
				},
				'Save': function (input) {
					this.storage ({
						player: {
							name: input
						}
					});
					return true;
				},
				'Revert': function () {
					this.storage ({
						player: {
							name: ''
						}
					});
				},
				'Warning': 'You must enter a name!'
			}
		},
                'show character y normal at center with lightSpeedInRight',
		'y こんにちは{{player.name}}さん<br>ようこそ Monogatari へ!',
		{
			'Choice': {
				'Dialog': 'y <a href="https://developers.monogatari.io/documentation/">ドキュメント</a>はもう読んだかしら?',
				'Yes': {
					'Text': 'はい',
					'Do': 'jump Yes'
				},
				'No': {
					'Text': 'いいえ',
					'Do': 'jump No'
				}
			}
		}
	],

	'Yes': [
		'y でかしたわ!',
		'y あなたがどんな素晴らしいゲームを作るか楽しみね!',
                'jump story-1',
	],

	'No': [
		'y あらそうなの?<br>なら今すぐ読むといいわ',
		'show message Help',
		'y さあ、素晴らしいゲームを作りましょう!',
		'y あなたがどんな物語を紡ぐのか楽しみにしてるわよ!',
                'jump story-1',
	],

        'story-1': [
            'show character k normal at left with fadeIn',
            'k え、俺の出番なし?<br>これで終わり?<br>マジか……',
            'y 急に湧いてこないで<br>続くから安心なさい',
            'k よかった<br>もっとはやく呼んでほしかったけど',
            'y これは<a href="https://github.com/Monogatari/Monogatari" target="_blank" rel="noopener noreferrer">Monogatari</a><br>というツールで作成したの',
            'y HTML, CSS, JavaScriptで作成できるから好きにプログラムできるわよ',
            ...
            'end',
        ],
});

monogatari.scriptにシナリオを書く。ここにはさまざまなコマンドが出てくる。各コマンドは画像の表示や音声の再生などがある。

たとえば以下は音楽を再生する。piano1_miagerusoramonogatari.assets ('music'で定義されており、自由に変更できる識別子。

'play music piano1_miagerusora with loop',

たとえば以下は背景画像room-nightを表示する。上記コマンドの書式をみて察せられると思うが、だいたいこんな感じ。

'show scene room-night with fadeIn',

キャラクタ画像の表示は以下。ynormalmonogatari.characters ({で自由に定義できる識別子。ここでは平時のユイというキャラを意味する。その後にあるcenterは画面の中央に配置することを指し、lightSpeedInRightは登場時のアニメーションを指定している。

このアニメーションに関してはshow character ドキュメントに書いてあるようにanimate.cssのキーワードを指定する。

'show character y normal at center with lightSpeedInRight',

会話。最初のyはキャラクタ指定子。monogatari.characters ({で定義された指定子にひもづくnameがキャラクタ名として表示される。{{player.name}}は変数。messageで定義されたダイアログボックスに、ユーザが自由に名前をセットできる。その名前をここで表示する。

'y こんにちは{{player.name}}さん<br>ようこそ Monogatari へ!',

HTMLも使える。a要素でリンクにしたり、ruby要素でルビを振ったりできる。

'y これは<a href="https://github.com/Monogatari/Monogatari" target="_blank" rel="noopener noreferrer">Monogatari</a><br>というツールで作成したの',
'y そうよ<br>気に<ruby>食<rt>く</rt></ruby>わなければ自力で作ればいいのだわ',

選択肢は次のように作れる。Choicejumpコマンドなどが定型句なる。

monogatari.script ({
'Start': [
	...
	{
		'Choice': {
			'Dialog': 'y <a href="https://developers.monogatari.io/documentation/">ドキュメント</a>はもう読んだかしら?',
			'Yes': {
				'Text': 'はい',
				'Do': 'jump Yes'
			},
			'No': {
				'Text': 'いいえ',
				'Do': 'jump No'
			}
		}
	}
],
'Yes': [
	'y でかしたわ!',
	'y あなたがどんな素晴らしいゲームを作るか楽しみね!',
	'jump story-1',
],
'No': [
	'y あらそうなの?<br>なら今すぐ読むといいわ',
	'show message Help',
	'y さあ、素晴らしいゲームを作りましょう!',
	'y あなたがどんな物語を紡ぐのか楽しみにしてるわよ!',
	'jump story-1',
],
'story-1': [
	'show character k normal at left with fadeIn',
	'k え、俺の出番なし?<br>これで終わり?<br>マジか……',
	...
]

クレジット画面

クレジット画面には開発者の情報を表示できる。ここでフリー素材作成者の名前とリンクを掲載した。リンクであるように見えないが、名前をクリックすると各サイトが開く。

さらにmpurseによる投げモナボタンも配置してみた。私のアドレスしかないが、とにかく配置できることはわかった。

20220814092413_020.png

所感

Monogatariを使えば次のようなことができる

  • ノベルゲームを開発できる
  • Linux, ラズパイ4でも開発・実行・公開できる
  • Electronで実装されているためHTML,CSS,JSで開発できる
  • OSを問わず実行できる
  • ネットワーク越しからも実行できる
  • mpurseで投げモナできる

足りない機能があればMonogatariをフォークして自分で実装できると思われる。

私が今回調べたかぎりMonogatariはノベルゲームを作るベストなライブラリ。