2014年10月14日火曜日

ルビを表示する

制作が止まっているわけではないのだが、また長らく間があいてしまった。ドット絵を打ったり。プログラムを書いたりしていた。

テキストにルビを振りつつ 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.

各文字の位置から表示するタイミングを計算すればもう少しマシになるんだろうかねぇ。

2014年10月5日日曜日

デザイン変更。

しばらく間が開いてしまったが、ドット絵素材をチマチマと作成していた。全然進んだ気がしない。

夜中に真っ白な背景だと目に堪えるので、背景色を変更した。ちょっとはマシな配色になっただろうか。

ドット絵をやっていると滅入るので、気分転換にフリーの音楽素材を探して整理したりもしていた。ドメイン名/(必要に応じて)ユーザー名/ みたいな感じで分けた。ジングルというかサウンドロゴというかがなかなかイメージに合うものが見つけられない。部分的に切り取るとかも考えた方がいいかも知れない。チップチューン系だと素材探しが大変で、そういうのでないやつだと自作のドット絵がショボすぎて負けるような気がするので品質をあげないとナー。とはいえ KS 品質でもいいから全部のドット絵素材を用意する方が優先順位は高いけども。