フリーゲーム・フリーソフトの開発過程を記録していく、TDtechnic公式ブログです。製品はカテゴリの「ダウンロード場」からダウンロードして頂けます。
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

こんにちは。今日こそは見える変化が現れましたよ!

まずはフォントテクスチャの背景です。変換文字の色付けのため背景色に対応させたのですが、これは単純に空白を背景色で塗りつぶすだけというものだったため、文字の縁の半透明部分では汚いジャギーが発生していたのです。そこでアルファブレンドの計算式を使用したところ、縁でも背景色が反映されるようになり、見違えるように綺麗になりました。

…まあでも、これは地味な方ですね。まだあります。フォントテクスチャに自動改行機能を追加しました。今までは私が\nを入力してなんとかしていましたが、今回はプレーヤーに入力させた文字列を表示するため、どうしてもこの処理が必要でした。

まあでもこれも普通に考えたらあたりまえのことですね。まだまだありますよ!今まで、日本語入力ができるテキストボックスは「動けばいい」的な実装でした。なのでゲームに組み込めるように様々な改良を施しました。その中で最大の壁である「va_listの壁」を紹介しましょう。

このへんは同業者向けの内容ですかね。皆さんお馴染みprintf関数は、文字列中の%sや%dにそれに対応する引数を埋め込んでくれるという便利なものです。これに似た関数を作りたければva_listとvsprintfなどを使えばいい訳で、私のテキスト表示クラスもこの書式を採用していました。いろんな数値を埋め込む必要がありますからね。

では、これの何が問題なのかというと、例えば「名前を入力して下さい(バッファに入力させる)」→「私の名前は%sです。(%sにはバッファへのポインタが指定されている)」とした際、名前が表示されません。なぜなら、テキスト表示クラスの都合上、「名前を入力して下さい」と「私の名前は%sです。」は同時に生成されているのですが、vsprintfは生成時(即ち、可変長引数関数の呼び出し時)しか埋め込んでくれないため、入力前のバッファ(空文字列)が埋め込まれてしまうからですね。これを解決するには、文字の埋め込みを生成時でなく表示時にする必要があります。命題をここに絞って試行錯誤してみました。

①引数を全部保持しておく
直球な方法ですね。しかしこれはすぐに壁に当たりました。早速引数の配列を作成しようとしたところ、引数の数がわからないのです。ここはとりあえず%の数(%%を除く)を数えて対応したとしましょう。では型はどうしましょう?「%d」などはあくまで最短の書き方であって、printfの仕様では「-5.2d」などとして細かい指定ができるので、単純に「%dならint、%fならdouble…」と判定していてはprintfと同じ使い方ができません。この判定は非常に面倒そうです。さらにこれを乗り越えたとしても、そのあとどうやって埋め込みましょうか?vsprintfにはva_listしか渡せませんし、数が不定なのでsprintfにも渡せません。こうなると結局printfと同じ処理を私が自分で書かなければならなくなります。さすがにこんな非現実的なことはありません。却下です。

②固定長引数にする
最も現実的な答えですね。しかし私はそれに甘えたくありません。今後いくつの引数をどんな書式で入力するか見当もつきませんから、一度printfの柔軟性を味わうとやめられません。却下です。

③新しい変換指定子を追加する
printfの書式と競合しないように、自分専用の処理のための変換指定子を新たに作ります。これなら私でもできそうでした。まず、トークンを決めましょう。他の意味合いで使われている文字でなければなんでもいいのですが(ただしASCII文字以外はマルチバイト対応が面倒なので非推奨)、私は「$」を選びました。これなら普段使うことはありませんし、万一「$」を出力したい場合に備えるなら「$$」を「$」に変換するようにしておけばよいのです(printfの「%%」と同じ解決方法)。

しかし、ここである問題が解決されていないのに気づきます。表示時まで、引数はどこに保持すればよいのでしょうか?はい、私もこれに気づいて諦めかけました。しかし、私はいい格納場所を見つけました。ヒントは「私が渡したがっているものは、名前のバッファへのポインタである」ということです。

答え→ 私の名前は$013B1000です。

今問題なのはバッファの中身が変わることですが、バッファへのポインタ自体は変わりませんよね。だからそれを文字列中に埋め込んでやりました!それをあとで参照すればよいのです。これは、printfの変換指定子にポインタ埋め込みのための「%p」があるのを発見した時に閃いたものです。

つまり上の文字列はvsprintfでポインタを埋め込んだ後のものです。具体的な変換方法を下に示します。
(静的変数pBufferには"Shiro"が代入されており、そのアドレスが013B1000であるとする)

"私の名前は$%pです。", pBuffer

↓vsprintfでポインタを文字列として埋め込み<クラス生成時>

"私の名前は$013B1000です。"

↓$に続く8桁の文字列をポインタに変換、それが示す文字列を埋め込み<表示時>

"私の名前はShiroです。"

これなら、「好きなときに」「何度でも」埋め込むことができますし、引数の渡し方にも困りません!もちろん、printfの書式とも共存できています。さらに、一度このシステムを作ると、様々な改造が簡単にできます。例えば、「$s%pならポインタが示す文字列に置換、$d%pならポインタが示す整数に置換」というように分ければ、他の型へのポインタを指定することもできます。

いつも言いますが、こういうのは私が勝手に考えたものですから、実は他にも思いついた人がいて私が調べ足りなかっただけということがあるかもしれません。でも逆に私がこの方法の創造者(笑)かもしれないので、一応ここで晒してみます。いづれにせよ検索に引っかかって誰かの参考になれば幸いです。では失礼します。

(2014/03/21 追記)
「他の意味合いで使われている文字でなければ」として「$」を挙げましたが、厳密にはこの文字はprintfなどで「引数順指定」をする文字として使われていることがわかりました。誤解を招く表現をしたことにお詫び申し上げます。ただし、この意味で使われた「$」はvsprintfを通した時点で消えてしまうため、トークンとして「$」を使っても問題ないのには変わりありません。

<本日のスクリーンショット>
久しぶりにスクリーンショットを晒しましょう。背景色処理のBefore/Afterです。おわかりいただけただろうか。
Font.png
関連記事

[2014/03/21 17:04] | 不死女 -Immortal girl-
|
コメント:
この記事へのコメント:
コメント:を投稿
URL:

パスワード:
非公開コメント: 管理者にだけ表示を許可
 
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。