About WonderWitch 今回のお題:
『WonderWitch のテキスト ( とグラフィック ) の管理法』


●概要

沢山の方々が WonderWitch ( 以下 WW ) でのプログラミングに取り組んでいるようで、 このプラットホームの繁栄を願う者としては非常に嬉しいのです。
ですが、やはりこういう感じのゲーム制作には慣れていない方も多いようで、 自前で画像の重ね合わせ処理をするのに慣れてしまい「スプライトって何やねん」状態の方もいるようです。 そこで、WW( というか、一昔前のコンシューマ機全般 )のグラフィックの管理形態の基本とかを、 「分厚いマニュアルは読みたくない人」向けに書いてみようと思い立ったわけです。

それから、text_screen_init() を呼んでからキャラクタを弄ると、たまに画面上の文字が化けたりします。 私も最初の頃は「なんじゃこりゃ?」という状態だったのですが、様々な方のサイトを眺めていたら、 なんだか妙な方法でテキスト画面を実現していることが解りました。 覚え書きを兼ねて書いておこうかと思うのです。

ネタの水増し用? いやいや、そんなことはありませんぞ。えぇ、ありませんとも。

●技術的知識

まず、WWは、以下のような方法でグラフィックを管理しています。

キャラクタ
「風呂場の四角いタイル」を想像すると解りやすいかと思います。8 * 8 ドットの大きさで、 これにグラフィックを貼り付けて使います。グラフィックを扱う際、基本的にはこれが最小単位になります。
スクリーン
「風呂場の四角いタイル」をはめ込む「枠の並び」みたいなもので、これにキャラクタをはめ込む ( 設定する ) ことによって、画面上に表示させます。背景などを実装するのによく使われます。
スプライト
「影絵の人形」を想像すると良いかもしれません。キャラクタ一つ分の「枠」に柄を付けたような物で、 これにキャラクタをはめ込み、動かすことができます。 動き回るモノ ( ミサイル、木の葉、マリオ etc. ) を実装するのによく使われます。

これらは、マシンパワーの比較的貧弱なハードウェアでよく使われる方法です。 最近プログラミングを始めた人なんかには、なじみが薄いかも知れません。
MS-DOS や Windows 等でよく行われる「マスクデータを作成して OR か XOR」とか 「VRAM に逐次書き込み / 消去」に慣れていると、一寸ピンとこないかも知れません。 実際には、それを自動的に行っているのがスプライトだったりするんですが……。

スクリーンとスプライトの例
図: スクリーンとスプライト

これは、皆さんご存知の FC「スーパーマリオブラザーズ 3」(任天堂) の画像です。 裏技を使って、マリオがパネルの裏なんかに隠れている状態にしてあります。 上の要素をこれに当てはめると、

ということになります。

●内容

で、肝心の「WW がどのような方法でテキストを扱っているか」ですが、流れとしては、

  1. text_*_init() が呼ばれると、テキスト画面全体に、全て違う番号のキャラクタを敷き詰めて、
  2. text_put_*() で、指定した位置に敷かれているキャラクタに、フォントデータを設定

というふうになります。text_screen_init() の場合は、キャラクタ座標 ( ( 0, 0 ) 〜 ( 28, 18 ) ) に 8 番 〜 512 番のキャラクタが、text_window_init() の場合は、指定範囲に、 「割り当てるフォントテーブルのベース」で指定した番号から連番で、 必要な数のキャラクタが敷き詰められます。

よって、

#include <sys/bios.h>

/* 文字 code のフォントを charno 番のキャラクタに設定 */
void    set_font2char_mono( unsigned code, int charno )
{
    BYTE    data[8];
    text_get_fontdata( code, data );
    font_set_monodata( charno, 1, data );
}

void    main( void )
{
    text_screen_init();

    set_font2char_mono( 'テ',  8 );
    set_font2char_mono( 'キ',  9 );
    set_font2char_mono( 'ス', 10 );
    set_font2char_mono( 'ト', 11 );
    set_font2char_mono( '表', 12 );
    set_font2char_mono( '示', 13 );

    key_wait();
}

このコードはキャラクタに文字を設定しているだけですが、そのキャラクタは text_screen_init() で既に画面上に配置されているので、これでもテキストを画面上に表示することができるわけです ( 勿論、こんな事をやるより text_put_*() を使う方が良い )。

ということは、キャラクタを弄ったときに、

といったことが起こるときは、

といったものが原因として考えられるわけです。

●備考

WW でプログラミングを始めるときに、「ただの Hello World なのに、何でこんな書き方をせにゃならんのだ」 と思った方もおられると思いますが、テキストよりもグラフィックを扱う頻度の方が圧倒的に多いハードウェア、 特にマシンパワーの貧弱なものでは、テキスト処理はこういった方法で「済ませてしまう」方が、 余分なリソースも必要としないし楽なのです。

にしても、今の 3D バリバリなゲームで育ってきた人たちには、 スプライトとかマスクデータとかパレットとか言っても解らないのかも知れません。 「マニュアルが難しい」ってのは、そういうのも理由としてあるのかも。
ファミコンも FM-TOWNS も、もう記憶の彼方に消え去っちゃったって訳ですか。ああ、我が幼少の時は既に遠く。


戻る