nobu blog

プログラミングやゲーム、ゲーム音楽コンサート周りの話をつらつらと。

*



HTML5とJavaScriptでサウンドノベルを作る(TypeScript使用)

      2015/07/22

概要

現在、TypeScriptの勉強をしています。
折角なので自分の好きなサウンドノベルを作る目標で勉強していこうかと思います。
kama
今回は、単純な以下のようなマウスクリック時に文字を表示していく処理を考えます。
サンプル

スポンサーリンク

TypeScriptとは

まずはTypeScriptに関して簡単に触れようと思います。TypeScriptとは、MicroSoftが提供しているプログラミング言語です。
詳細はWikiをなどを見ていただければわかると思いますが、
簡単に言ってしまうとJavaScriptに色々と機能を追加したもので、コンパイル時にJavaScriptを出力してくれる言語です。
出力される最終的なアウトプットがJavaScriptになるので、これまで通りブラウザ上で動くものになりつつ、コードを記述する際はJavaScriptのちゃらんぽらんな部分を補って、ある程度静的な型付言語のように扱えるようになります。
そのため記述ミスなどを防ぎ、生産性を上げてくれるため、非常に有用な言語だと思います。
また、MS製ということでVisual Studioとの相性も良いので、普段C#を使っている開発者にもなじみやすい言語でもあります。
Visual Studio自体も現在はVisual Studio Communityとして個人開発者は無料で使うことができるため、これからJavaScriptをやってみようと思っている人がTypeScriptから学んで見るのも良いかもしれません。

やりたいこと

折角学ぶのであれば、自分が楽しめるものが良いということで、自分の好きなジャンルであるサウンドノベルの作成を目標にやっていこうかと思います。
複雑なものをいきなり実現は難しいと思いますので、まずは文章表示させるところから学んでいこうと思います。

TypeScriptプロジェクトの作成と内容確認

まずはVisual Studioを立ち上げて、新規プロジェクトでTypeScriptアプリケーションを選択し作成します。
types1

cssとhtmlとtsファイルという非常にシンプルな構成のファイルが出力されています。
Web.configがありますがこれはASP.NETとの連携用でしょうか?
types2
htmlを開くとtsファイルと同名のjsファイルを読み込む記述がされています。
どうやらtsファイルと同名のjsファイルがコンパイル時に出力されるような仕組みなようです。

types3

実際にtsファイルを見て見ると、以下のようなGreeterクラスが記述されています。タイマーで定期的に時刻を取得して画面出力する処理が記述されているようです。
types4

また、ページ起動時に上記クラスを作成する処理が記述されており、これによって実際に処理が行われるようになっています。
types5

実際にコンパイル実行すると、以下のような表示されたページが表示されます。時刻部分は定期的に表示が更新されます。
types6

まずはTypeScriptアプリの起動確認まで行いましたので、実際にコード記述などを行います。

HTMLの記述

TypeScriptを実際に書く前に、まずはサウンドノベルとして文章表示を行いたい領域を作成します。
HTML5で何かを描画というと、Canvasという要素がありますのでそれを使って見ようと思います。
まずはテキトーに幅700と高さ550として宣言します。
また、IEの一部のバージョンでCanvasのコンテキスト取得時にエラーが出るため最新のモードで動くようにメタデータを宣言しておきます。

また、読み込むスクリプトはapp.jsからnovel.jsとして、後ほど作成していきます。

Canvasでの文字の描画

ここで一度、Canvasでの文字の表示方法を考えてみます。

Canvasでの文字の描画1 改行

サウンドノベルとして文章を表示するための方法を考えます。
Canvasには文章を描画するためのインタフェースとして以下のようなfillTextメソッドが用意されてされています。

fillText(text, x, y [, maxWidth ] )
参考URL

ただし、上記のインタフェースを見てもらえばわかる通り、文字の位置指定はx,yによる座標指定になります。
よって、よくあるテキストボックスやラベルのように、ただ表示したい文字列だけを渡すだけではなく、
改行を考えて自分でy座標を位置して描画する必要があります。

そのためのインタフェースとして、measureTextメソッドが用意されています。

metrics = context . measureText(text)
現在のフォントにおける指定テキストの長さを持った TextMetrics オブジェクトを返します。
metrics . width
measureText() メソッドに引き渡したテキストの幅を前もって返します。

参考URL

このメソッドを使って1文字ずつ、描画前に改行すべきかどうかを判定し、描画領域を超える場合には改行を行うようにします。
文章を表示するためにだけにここまでしないといけないのは正直面倒くさいですね・・・。

Canvasでの文字の描画2 アニメーション表示

一般的なサウンドノベルでは、文章を表示する際に一度に全ての文章の表示を行うのではなく、徐々に表示を行う必要があります。
下記はかまいたちの夜の場合です。

これを実現するためには1文字ずつ、タイマーを用いて文字を描画する必要があります。
JavaScriptでは一定時間ごとに処理を行うためのsetInterval関数が用意されているのでそれを利用します。
参考URL

Canvasでの文字の描画 まとめ

上で説明したように、Canvasを用いてサウンドノベル的な文章表示を行うためには以下の2つの機能を実装する必要があります。
1.改行を意識した文字表示
2.タイマーを用いた1文字ずつの表示

文章表示をするのにここまでしないといけないのは、多機能なUI部材に慣れていると少し億劫ですね。
もう少しCanvasの機能が拡張されると良いのですが・・・。

TypeScript作成

実際にTypeScriptファイルを作成していきます。
ソリューションエクスプローラから新しいTypeScriptファイルを追加します。
types7

作成されたtsファイルに以下のようなNovelDisplayクラスを作成します。

簡単にですが主なポイントの説明を行います。

基本的な考え方

文字列の2次元配列を利用して、ページ、行単位での表示済みの文字を保持しておきます。(sentencesフィールド)
このフィールドと現在の行と列位置を使って文字の表示位置を決めていきます。

showOnecharメソッド

このメソッドは渡された1文字の文字列を描画します。1文字な理由は前述の通り、タイマー処理によって徐々に表示を行うためです。
まず描画前に、measureTextを用いて改行もしくは改ページ判定を行い、必要であれば改行、改ページを行います。
その後、実際に表示位置を計算して描画を行います。

changeRowOrPage, changeRow, changePageメソッド

改行もしくは改ページ処理を行います。
changeRowOrPageメソッドでどちらを行うかを判定します。
現在の文字列描画の高さを計算し、画面下部まで達したかどうかを基準とします。
改行の場合には、現在の行数をインクリメントして、行情報をクリアします。
改ページの場合にはキャンバスの描画をクリアして表示文字を全て消し、行、列どちらの情報もクリアします。

showOneStringメソッド

渡した文字列を表示します。上記のshowOnecharメソッドに1文字ずつ渡す文字を渡すタイマーを定義して表示するように処理します。
文字描画中に処理を呼び出されても進まないようにタイマーのチェックを行います。
描画が終了するとタイマーをリセットして描画を受け入れるようにしています。

呼び出し処理

とりあえず、ここまで作成した処理を呼び出してみましょう。
Canvasのクリックイベント時に処理を呼び出すようにして、3パターンの文章を延々と表示させます。
実際のサンプルはこちらになります。

サンプル

まとめ

ということで、TypeScript(HTML5 + JavaScript)を用いてサウンドノベル風の文章表示を行ってみました。
JavaScript自体そこまで詳しくないため言っていいのかわかりませんが、どうしても汚いコードになってしまうイメージがありました。
しかし今回はTypeScriptを使ってオブジェクト指向的に処理を書くことができたのでだいぶ書きやすくてよかったです。

これから色々と手を加えていこうと思います。
また手法等がまとまりましたら紹介しようと思います。

2015/07/22
その2を追加しました。

 - HTML, TypeScript