制作が止まっているわけではないのだが、また長らく間があいてしまった。ドット絵を打ったり。プログラムを書いたりしていた。
テキストにルビを振りつつ 1 文字ずつ表示するのを作った。基本的なアイデアは大きさと間隔を調整した GUI Text を並べ、表示速度を調整するだけ。テキストは XML 文書というか以下のような HTML 文書から読みこんで使う。指定したノード番号の dl 要素に含まれる、dt 要素をルビ 1 ページ, dd 要素を本文 1 ページとして表示する。
<html>
<head><title>タイトル</title></head>
<body>
<dl>
<dt>ほんじつ せいてん
ほんじつ せいてん </dt>
<dd>本日は晴天なり
本日は晴天なり</dd>
<dt>じゅ げ む じゅ げ む
ご こう す き </dt>
<dd>寿限無 寿限無
五劫の擦り切れ </dd>
<dt>かいじゃ り すいぎょ
すいぎょうまつ うんらいまつ ふうらいまつ</dt>
<dd>海砂利水魚の
水 行 末 雲来末 風来末</dd>
<dt> く ね ところ す ところ
やぶ こう じ やぶこう じ </dt>
<dd>食う寝る処に住む処
藪ら柑子の藪柑子 </dd>
<dt>
</dt>
<dd>パイポパイポ
パイポのシューリンガン
シューリンガンのグーリンダイ</dd>
<dt>
ちょうきゅうめい ちょう すけ</dt>
<dd>グーリンダイのポンポコピーの
ポンポコナーの 長 久 命の 長 助</dd>
</dl>
</body>
</html>
KS コードは以下の通り。Canvas を 2 つ (本文用、ルビ用) 用意して、currentTextType をそれぞれ TextType.Body, TextType.Ruby としておき、それぞれの recoveryTime, fontSizeFactor を調整する。例えば、本文の recoveryTime を ルビの recoveryTime の 2 倍にし、本文のフォントサイズがルビのフォントサイズの 2 倍になるように fontSizeFactor を調整する。あとは、それぞれの LoadSelectedList (int i)を呼べばいいんじゃないかな。
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Xml;
public class DisplayLetterByLetter : MonoBehaviour
{
Text textarea;
float timer;
// 次の文字が表示されるまでの間隔。適当に調整
public float recoveryTime = 0.1f;
XmlDocument xmlDocument;
// 読み込む XML (TextAsset として)
public TextAsset xmlTextAsset;
XmlNodeList[] DefinitionLists;
XmlNodeList currentList;
int currentPage;
string fullText;
int fullTextLength;
// true のときテキストを表示
public bool displayingText = false;
int numberOfLettersDisplayed;
// 全文字表示してから自動ページ送りするまでの秒数
float autopagingTime = -2;
bool paging;
// 自動ページ送り
public bool autopaging;
public enum textType
{
Body,
Ruby,
};
// 本文 Body, ルビ Ruby
public textType currentTextType = textType.Body;
// 画面の高さに対する割合
public float fontSizeRatioToScreenHeight = 0.01875f;
void Start ()
{
textarea = GetComponent ();
textarea.fontSize = (int)(Screen.currentResolution.height * fontSizeRatioToScreenHeight);
xmlDocument = new XmlDocument ();
xmlDocument.LoadXml (xmlTextAsset.text);
XmlNodeList xmlNodeList = xmlDocument.SelectNodes ("/html/body/dl");
int numberOfDefinitionLists = xmlNodeList.Count;
DefinitionLists = new XmlNodeList [numberOfDefinitionLists];
for (int j = 1; j <= numberOfDefinitionLists; j++) {
DefinitionLists [j - 1]
= currentTextType == textType.Body ?
xmlDocument.SelectNodes ("/html/body/dl[" + j + "]/dd") :
xmlDocument.SelectNodes ("/html/body/dl[" + j + "]/dt");
}
}
public void LoadSelectedList (int i)
{
currentList = DefinitionLists [i];
currentPage = 0;
LoadCurrentPage ();
}
//
void LoadCurrentPage ()
{
fullText = currentList.Item (currentPage).InnerXml;
fullTextLength = fullText.Length;
timer = recoveryTime * (currentTextType == textType.Body ? 1 : 2);
numberOfLettersDisplayed = 0;
}
void Update ()
{
// jInput を使っていない人は普通に Input.GetButtonDown ("お好みのボタン")
paging = jInput.GetButtonDown (Mapper.InputArray [5]);
}
void FixedUpdate ()
{
if (displayingText) {
Display (autopaging);
}
}
void Display (bool autopaging)
{
textarea.text = fullText.Substring (0, numberOfLettersDisplayed);
timer -= Time.deltaTime;
if (numberOfLettersDisplayed < fullTextLength) {
if (paging) {
timer = 0;
paging = false;
}
if (timer < 0) {
numberOfLettersDisplayed++;
timer += recoveryTime;
}
} else {
if (paging) {
OnPageEnd ();
paging = false;
} else if (timer <= autopagingTime && autopaging) {
OnPageEnd ();
}
}
}
void OnPageEnd ()
{
if (currentList [currentPage + 1] != null) {
currentPage++;
LoadCurrentPage ();
} else {
CloseMessageWindow ();
}
}
void CloseMessageWindow ()
{
displayingText = false;
}
}
再生の様子を動画でご覧あれ。表示位置とタイミングは半角スペースやら全角スペースやら改行やらを使って調整するという力業なのでいろいろ微妙。力こそパワーの精神でひとつヨロシク。
ルビの表示 displaying ruby text from hide behind on Vimeo.
各文字の位置から表示するタイミングを計算すればもう少しマシになるんだろうかねぇ。