この記事は、Akashic Engine Advent Calendar 2019の13日目の記事です。
数年前からAkashic製ノベルゲームエンジンを細々と開発しており、その開発中や実際に使ってゲームを作る際にやったことなどを2, 3個書いておきます(ほんとはもっとたくさんあるのですが、時間がないので…ごめんなさい)。
Akashicとフォント
Akashic EngineではDynamicFontとBitmapFontが扱えるわけですが、DynamicFontはとりあえず表示したりするには便利なものの、ちゃんとしたゲームを作るならやはり雰囲気にあったフォントを使いたくなるものです。というわけでBitmapFontを使うための準備をします…といっても基本は公式ガイドに従うだけなのですが。
扱う文字をまとめてから生成
さて、少ない文字数なら公式ドキュメントのやり方で十分なのですが、ノベルゲームはいかんせん文字数が膨大かつシナリオを修正するたびに扱う文字が変わる可能性があるのでスクリプト化して何度も生成できるようにしておきましょう。
const glob = require("glob");
const fs = require("fs");
const font = {
ttf: "./font.ttf",
output: "./font.png"
};
const strings = (files, extra) => {
return files
.map(name => fs.readFileSync(name, "utf-8"))
.reduce((a, b) => a.concat(b))
.split("")
.filter((value, index, self) => self.indexOf(value) === index)
.sort()
.reduce((a, b) => a + b)
.replace(/\r?\n/g, "")
+ extra;
};
// 文字収集対象のファイル群
const files = [
"./text/settings.json",
...glob.sync("./scenario/*.txt")
];
const extra = "シナリオに現れないシステム用文字列";
const generate = `bmpfont-generator ${font.ttf} ${font.output} -H 32 -c ${strings(files, extra)} -m ?`;
const exec = require("child_process").exec;
exec(generate, function(err) {
if (err) {
console.log(err);
}
});
雑な実装なのでスクリプト記述用の文字が含まれてしまったりしますが、十数文字程度は誤差だと思って妥協しています。
akashic-labelと禁則処理
Akashic Engineで文字を描画したい場合はakashic-labelを使います。akashic-labelは禁則処理を設定できるのですが、どういう処理にするかは利用者にゆだねられています。
私はW3Cのものに従えばいいかなと考えたので、以下のように実装しました。
テキスト表示のスピード調整
ノベルゲームによくある機能の1つにテキスト表示スピードの調整やクリック時全文表示があります。
まずテキスト表示スピードの調整ですが、これをAkashic Engineで再現するには g.Scene.setInterval
を使います。あとは呼び出しごとに1文字ずつ表示させるだけでそれっぽい感じに仕上がります(fpsによっては多少ちらついたりするかもしれませんが、まぁ許容範囲です)。
ただし、ルビの場合は1文字削ってから次のルビ付き文字列を追加する、みたいなことをしてあげないと自然にならないので注意が必要です。