■top■ システム
* Using Allegro

構造体
*オブジェクト一覧

ユニコード
* Unicode routines

コンフィグ
* Configuration routines

出入力
* Mouse routines
* Timer routines
* Keyboard routines
* Joystick routines
* Graphics modes

画像関連
* Bitmap objects
* Loading image files
* Palette routines
* Truecolor pixel formats

図形描画
* Drawing primitives

画像転送&スプライト
* Blitting and sprites
* RLE sprites
* Compiled sprites

テキスト
* Fonts
* Text output

レンダリング
* Polygon rendering
* Transp and patterned
* Conv color format
* Direct access to VRAM

動画
* FLIC routines

サウンド
* Sound init routines
* Mixer routines
* Digital sample routines
* Music routines (MIDI)
* Audio stream routines
* Recording routines

ファイル
* File and compression
* Datafile routines

数学関連
* Fixed point math
* 3D math routines
* Quaternion math

GUI
* GUI routines

アーカイブ・ツール
* GrabberとDAT
*ttf2pcx, bdf2pcx
* fixbundle

Allegro API (4.2.0) メモ

 
Allegro( バージョン 4.2.0 現在)のAPIに関するメモです、オフィシャルのThe Allegro manual を完全に網羅はしていません。 例になるコードは基本的にAllegroのマニュアルやサンプルを参照しているほか、不明な部分は自分で検証したり 新規に補足した部分もある反面、 分からないところは省略したり、意訳部分もあります。また、バージョンアップに伴いAllegroのAPI仕様が変更される可能性も考えられます。 ここに書かれたメモや仕様の正確性は保証しません。もし利用する場合は自己責任でお願いします。

API

Transparency and patterned drawing (ブレンド処理)は別ページに分けてあります。
#include <std_disclaimer.h>
"I do not accept responsibility for any effects, adverse or otherwise, that this code may have on you, your computer, your sanity, your dog, and anything else that you can think of. Use it at your own risk."
このコードによって、あなたや、あなたの気分、PC、愛犬、あなたがその他思いつく何かに対して損害が発生したとしても
私はどのような責任も受け入れない。使う場合は自己責任で。

Randomize 乱数

乱数の取得
rand()%6 この場合 0〜5 までのランダムな数字を返す。ただし、乱数の出るパターンはいつも同じ周期に偏る。

AL_RAND() これも、ランダムな数字を返す。

乱数生成を補正
srand(time(NULL)); プログラムの最初(allegro_init()の直後)で呼び出せば、rand() 関数の値の偏りを防止できる。

SYSTEM システム

Allegroの初期化
int allegro_init();
Allegro ライブラリを有効にするマクロ。どんなAllegroアプリケーションも、たいていこのマクロによって初期化されている。

Allegroの終了処理
Macro END_OF_MAIN();
Allegroライブラリを終了するマクロ。Linux , Windows , MacOSX それぞれに対応した終了処理を行う。普通にAllegroを使う場合はmain();関数の最後にこのマクロが配置される。

Allegroの初期化(手動,詳細設定)
int install_allegro(int system_id, int *errno_ptr, int (*atexit_ptr)());
特になにも問題がなければ、allegro_init();で済ます事ができるらしい、install_allegro();を使う局面は 特殊な状況下に限られる。

allegroのライブラリを初期化する。 allegro_init (); と同じく、UTF-8以外のテキストモードを使用したければ、そのまえに set_uformat();関数を呼び出しても良い。 set_config_file();のような他の機能もまた同じである。

system_id には、利用可能なシステム を 限定しなければ、ほとんどの場合 SYSTEM_AUTODETECT を引数として渡せるかもしれない。
その代わりに SYSTEM_NONEを指定すると、 それぞれのOSのシステム固有のハードウェアドライバを使用せずに allegro を使う設定になる。 これは、 メモリビットマップを操作したり、WindowsのGDIインターフェイス機能を利用するときに有用かもしれない。

` errno_ptr ' 及び` atexit_ptr ' 変数 には あなたが使う lib から、 エラーナンバーや 終了機能を指す。 これらは、Allegro がダイナミックリンクライブラリ(DLL)としてリンクしている場合、直接呼び出せないので `atexit_ptr' が、 NULLになった場合、 あなたはallegro_exit(); を手動で呼ぶ必要がある。 通常は&errno , atexit関数を引数に渡す。 
install_allegro(SYSTEM_AUTODETECT, &errno, atexit);
返値:
0..... 成功
0以外..... 失敗。 使えるドライバが見つからない。


Allegro システムの終了(手動)
int allegro_exit();
Allegro システムの終了。 これは、マウス、キーボード、タイマー 処理を終了させ無効にする。atexit() のルーチンに従って、 Allegro のプログラム終了時に、allegro_exit(); が自動的に呼び出されるので、通常はこの関数を明確に呼び出すことに注意を払う必要はない。
これも手動で終了させる場合に使用するのかもしれない。


ウインドウタイトルを表示する
void set_window_title(const char *name);
Allegroアプリケーションのウインドウタイトルバーに文字を表示する。
allegro_init(); 直前に set_uformat( U_UTF8 ); を呼び出しておけば、 タイトル部分に 日本語を含むユニコード文字列を表示することができる。

エラーダイアログを出す
void allegro_message(const char *text_format, ...);
エラーダイアログを出して、ユーザーにメッセージを表示する。 この関数には、printf と同じ書式が使える、また、改行により数行にわたる長文も表示可能(OSX)。
allegro_message("ダイアログには日本語が通る。エラーは`%s'\n", err_number); 


日付を取得する
#define ALLEGRO_DATE
日付は `yyyymmdd'形式で格納されている。
const int year = ALLEGRO_DATE / 10000;
const int month = (ALLEGRO_DATE / 100) % 100;
const int day = ALLEGRO_DATE % 100;

allegro_message("Year %d, month %d, day %d\n", year, month, day);

時間を取得する
Allegroには、時分秒を取得する関数が存在しない。(4.1.1.18 現在)
フレームレートを求めるには、time_int で 周期的にフレームを更新して得る。

もし時間表示や時分秒を取得してフレームレート等を求めたい場合には、
time.h と localtime関数を使う。
http://www.allegro.cc/forums/view_thread.php?_id=265165

C/C++ リファレンス → 標準 C ライブラリ:localtime
http://www.shibu.jp/cppreference/stddate_details.html#asctime
#include <time.h>

time_t temptime;
struct tm *curtime;

time(&temptime);  
curtime = localtime(&temptime);
struct tm 構造体の使い方 hogehoge->tm_hour

構造体(ストラクチャ)

各項目を参照。
もし、自作の関数にAllegro の bitmap ストラクチャを渡さなければいけないときは、引数にストラクチャの型名も記述する。 ストラクチャは、ポインタとして渡されたり、メンバ変数にアクセスできたりする。
void my_function( BITMAP *bitmap ){
〜処理〜
int height = bitmap->h; /* ビットマップの高さ */
int width = bitmap->w; /* ビットマップの幅 */
}

メンバ変数にアクセスする場合
構造体ポインタの場合 は アロー演算子を使う。
int width = bitmap->w;

そうではない場合は。ドット演算子を使う。
int width = bitmap.w;

ユニコード関連

プログラム中で扱う文字コードを指定する
void set_uformat(int type);
int type には 次のいずれかのエンコーディングモード を指定します。
●Allegroに初めから用意されているエンコーディングモード
U_ASCII - 固定長 8-bit ASCII 文字
U_ASCII_CP - 拡張 8-bit ASCII コード (set_ucodepage()関数を参照)
U_UNICODE - 固定長 , 16-bit Unicode 文字
U_UTF8 - 可変長, UTF-8 形式の文字 
日本語文字列を扱うには、U_UNICODE か U_UTF8 を指定すると良いです。
たとえば、 set_uformat( U_UTF8 ); と書く事で、プログラム中でUTF8文字列を使うことができます。
重要:この関数はAllegroの初期化 allegro_init(); よりも 先に 呼び出す必要があります。


現在設定されている文字コードの種類を取得する
int get_uformat(void);
文字コード別に処理を振り分ける時に使う。 
switch(get_uformat()) {
case U_ASCII:
do_something();
break;
case U_UTF8:
do_something_else();
break;
...
} 
返値:現在使用している 文字コートの種類を返す。


拡張ASCIIコードを設定する。
void set_ucodepage(const unsigned short *table, const unsigned short *extras);
set_uformat()関数で、エンコーディングモードを U_ASCII_CP を指定した場合は、この関数で拡張ASCIIコードを設定しておきます。拡張ASCIIコードは、ASCIIコードを多言語に拡張したもので、ラテン、ウムラウト文字やアラビア文字、トルコ語文字、キリル文字を表示できるようになります。*table にはコードテーブルを配列に格納し、256文字ぶん割り当てることができます。しかし、日本語文字コードとは関係ないので、日本語を使う場合あまり役に立たないかもしれません。


文字コードの変換が必要か調べる
int need_uconvert(const char *s, int type, int newtype);
文字コード type の 文字列 s を 文字コード newtype に変換する必要があるか教えてくれる。 変換が必要ない場合というのは、文字コードが一致する( type == newtype ) の時。 type, newtype に指定するパラメータは、U_ASCII U_UTF8 , U_CURRENT などが使える。
if (need_uconvert(text, U_UTF8, U_CURRENT)) {
/* 変換処理 */
}
返値:
変換可能であれば 0以外 を返す
そうでなければ 0 を返す


(仮)エンコーディングモードを追加、拡張する
void register_uformat(int type, int (*u_getc)(const char *s), int (*u_getx)(char **s), int (*u_setc)(char *s, int c), int (*u_width)(const char *s), int (*u_cwidth)(int c), int (*u_isok)(int c));
set_uformat()関数で指定可能なエンコーディングモードを追加します。

ただし、実際のエンコード処理や文字列処理関数は自前で用意しなければいけません。
登録された 各関数はフック関数として呼び出されます。
register_uformat(int type, AllegroIDで定義した定数
int (*u_getc)(const char *s), ugetc 関数に相当する関数名を登録
int (*u_getx)(char **s), ugetx 関数に相当する関数名を登録
int (*u_setc)(char *s, int c), usetc 関数に相当する関数名を登録
int (*u_width)(const char *s), uwidth 関数に相当する関数名を登録
int (*u_cwidth)(int c), ucwidth 関数に相当する関数名を登録
int (*u_isok)(int c) uisok 関数に相当する関数名を登録

);
例えば EUC_JP エンコーディングで何かしたい場合は、次のようになるそうです。
文字コードのデータ形式に関するの知識が必要です。
// まず、 ugetc, ugetx, usetc, uwidth, ucwidth, uisok 関数に相当する日本語文字コード処理関数を書いて下さい。
int euc_getc(const char *s) {
// 日本語文字コード処理を書く
}


// これは AL_ID 関数といって、Allegroシステムが使用可能な定数を追加したりする時に使用します。
// 定義に必要なID識別子は英大文字の4文字(この例では E,U,C,J)で指定します。各文字は必ずシングルクォートで囲みます。
//エンコーディングモード定数の定義
#define U_EUC_JP AL_ID('E','U','C','J')

//register_uformat関数を使い、新しいエンコーディングモード定数 U_EUC_JP と 各フック関数を登録。 register_uformat( U_EUC_JP, euc_getc, euc_getx, euc_setc, euc_width, euc_cwidth, euc_isok);

// ここで初めてエンコーディングモード定数として U_EUC_JP が使えるらしい。
set_uformat( U_EUC_JP );
他には、uconvert() 等の関数に、U_EUC_JP を定数として指定可能にもなるので、うまくすれば変換もできる!?
この項目を書くにあたって、register_uformat()? のトピックを参考にしました:


文字からユニコードを得る(文字列の一番最初の文字だけ)
int ugetc(const char *s);
Unicode テキストデータを読むための 低レベル機能サポート関数です。
int first_unicode_letter = ugetc(text_string);
textprintf_ex(screen, font,10, 96, makecol(255, 155, 0), -1, "code:%d " ,first_unicode_letter );
返値:
現在のエンコーディングモードの形式で、文字あるいは、文字列の一番最初の文字のコードが返ります。

文字からユニコードを得る
int ugetx(char **s);
int ugetxc(const char **s);

Unicode テキストデータを読むための 低レベル機能サポート関数です。ugetc()関数 と違い、文字列を構成する すべての文字のコードデータを扱うことができます。この関数は、const がついた文字変数でも使えます。
char *p = string;
int first_letter, second_letter, third_letter;
first_letter = ugetx(&p);// *p の最初の文字
second_letter = ugetx(&p);// *p の2番目の文字にポインタが移動
third_letter = ugetx(&p);// *p の3番目の文字にポインタが移動
textprintf_ex(screen, font,10, 96, makecol(255, 155, 0), -1, "code: %d %d %d " ,first_letter, second_letter, third_letter );

結果:
string="abc" code: 97 98 99

string="あいう" code: 12354 12356 12358
( 16進表記では、それぞれUTF16コードの 3042 3044 3046 を表している)

string="\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86" code: 12354 12356 12358
( UTF8表記で同様に書いても UTF16コードが返ります。 )

set_uformat( U_UTF8); でエンコードをUTF8にしても、UTF16で返るようです。
返値:
現在のエンコーディングモードの形式で、数値が返ります。この関数は、同じポインタに対して 使用するたびに、前回指し示すポインタのアドレスから、さらに1つ前進したアドレスを指し示すという特徴をもっています。


アドレスに書き込む
int usetc(char *s, int c);
Unicode テキストデータを書き込むための 低レベル機能サポート関数です。 s によって指定されたアドレスに、文字 c を書き込みます。
返値:
現在のエンコーディングモードの形式のbyte数と等しければ。書き込まれたbyte数が返ります。


文字のbyte数を得る(文字列の最初の一文字から)
int uwidth(const char *s);
Unicode テキストデータを調べるための 低レベル機能サポート関数です。
返値:
現在のエンコーディングモードで、指定した文字列が占めているbyte数を返します。


文字のbyte数を得る(文字コード値から)
int ucwidth(int c);
Unicode テキストデータをを調べるための 低レベル機能サポート関数です。
返値:
現在のエンコーディングモードでエンコードされた場合に、指定した文字コード値が占めている byte数を返します。


エンコーディングの変換
int uisok(int c);
Unicode テキストデータをを調べるための 低レベル機能サポート関数です。
文字コード値 c が現在の現在のエンコーディングモードでエンコード可能なら、それを探し出します。 もし、Unicode から ASCII やその他のエンコーディングに変換したとしても、役立つ 文字アドレスの範囲 は限定されます。
返値:
返値 が 0 以外なら エンコーディングの変換が正常に行われたことを示します。そうでない場合は、0 が返ります。



文字コードの変換 type→ newtype
void do_uconvert(const char *s, int type, char *buf, int newtype, int size);
指定した文字列 s を 文字コード type から 文字コード newtype 変換する。 変換データは 文字列 buf に size バイト出力される。 文字コードを示す type パラメータ には現時点で選択している文字コードを意味する 「U_CURRENT」 を指定する事ができる。
char temp_string[256];
do_uconvert(input_string, U_CURRENT, temp_string, U_ASCII, 256);
注意:空文字列を指定する場合でも、バッファに終端文字列を考慮したサイズを与えなければいけない。 さもなければ、デバッグ版のAllegroは Assert により中断し、通常のAllegroでは展開バッファをオーバーランすることになる。


文字コードの変換 type→ newtype
char *uconvert(const char *s, int type, char *buf, int newtype, int size);
do_convert() 関数で実行される、より高機能な関数。この関数は文字コード type 形式の文字列 s を newtype 形式に変更する。 変換された文字列は buf に size バイト(終端文字列含む)出力される。 type, newtype に指定するパラメータは、U_ASCII U_UTF8 , U_CURRENT などが使える。
もし、buf が NULL なら、一時的な内部バッファに文字列が格納され、sizeパラメータは無視される。 そして次にこの関数が呼ばれた時に上書きされる。 内部バッファは1Kにも満たないので、内部バッファで大きな文字列を扱う事はできない。
char *p = uconvert(input_string, U_CURRENT, buffer, U_ASCII, 256);
返値:
buf への ポインタ/ buf をnull に指定した場合は 内部バッファの内容。
そうでなければ、 文字列 s のコピーを返す。
常にbufのポインタは移動されるが、いずれにせよ、いつも 返り値 を使用しなければならない。


ASCII→現在使用している文字コード
char *uconvert_ascii(const char *s, char buf[]);
ASCII コード文字列 を現在の文字コード に変換する補助マクロ
uconvert(s, U_ASCII, buf, U_CURRENT, sizeof(buf)) を指定するのと同じ。


現在使用している文字コード→ASCII
char *uconvert_toascii(const char *s, char buf[]);
現在の文字コード を ASCII コード文字列 に変換する補助マクロ
uconvert(s, U_CURRENT, buf, U_ASCII, sizeof(buf))を指定するのと同じ。


空文字列
extern char empty_string[];
どの文字コードでも 有効な 空文字列を表現できる。この グローバル変数のバッファはいくつかの連続したゼロを含んでいる。 そのため ASCII, Unicode, UTF-8 モード 等 でも 問題なく対応することができる。


文字列の長さを取得(文字数)
int ustrlen(const char *s);
文字列 s の 長さ(文字数)を返す。

文字列の長さ(連続したスペース抜き, byte数)
int ustrsize(const char *s);
文字列 s の長さ(byte)を返す。ただし 連続した空白文字列は数えない。

文字列の長さ(連続したスペース含む, byte数)
int ustrsizez(const char *s);
文字列 s の長さ(byte)を返す。 連続した空白文字列を含む。
set_uformat( U_UTF8 );
int dist =ustrlen("花");
int dist2 = ustrlen("ひまわり");
int dist3 = ustrlen("Summer");
結果:
dist = 1, dist2 = 4 , dist3 = 6
ustrsize との違い
set_uformat( U_UTF8 );
int dist =ustrsize("花");
int dist2 = ustrsize("ひまわり");
int dist3 = ustrsize("Summer");
結果:
dist = 3, dist2 = 12 , dist3 = 6
なお、文字列をスクリーンに描画した時の幅(pixel)を取得するには text_length( ); 関数を使う。

n番目の文字を得る。
int ugetat(const char *s, int index);
文字列 s から index 番目の 文字を 探し出す。 index に 0 を指定した場合は 文字列 s の 先頭の文字を 探し出す。 index に -1 等 負の数を指定した場合は、 文字列 s の最後から index 番目の文字探し出す。
int third_letter = ugetat( "abcdefg", 2);
textprintf_ex( screen font, x, y , makecol(0, 0, 0), -1,"3rd letter: 0x%04x", third_letter );
// 文字列「c」 ではなく、「99」 = 文字コード「0x0063」 が返ってくる。 
返値: コードそのものを返す


n番目の文字を置き換える
int usetat(char *s, int index, int c);
文字列 s の index 番目 にある 文字データを変数 c のコードデータ に置き換える。 可変的に文字列データを調節するための処理( 直前の文字と 変数 c の エンコードが 違っている場合)。 もし index が 負の数ならば、 文字列の最後から数えて index 番目の文字が指定される。
usetat(text_string, 2, letter_a);
返値:文字列が移動したbyte数を返す。
( UTF-8 エンコード のような可変長データであっても)


文字列のn番目に文字を挿入
int uinsert(char *s, int index, int c);
変数 c ( コードデータ ) を 文字列 s の index 番目 に挿入する。場所を空けるためにデータの残りがずらされる。 もし index が 負の数ならば 文字列 c の最後から数えられる。
uinsert(text_string, 0, prefix_letter); 
返値:挿入によって文字列が移動したbyte数



文字列の比較とマッチング
int ustrcmp(const char *s1, const char *s2);
文字列 s1 と s2 を比較する。

返値:
0 マッチした。
正の数 照合順序 ( collating sequence) が s2 の後に s1 がくる場合。( s1 > s2)
負の数 s2 の後に s1 がくる場合。( s1 < s2 )



文字列の比較とマッチング(最初のn文字)
int ustrncmp(const char *s1, const char *s2, int n);
文字列 s1 と s2 の 最初から n 文字 を比較する。
接頭語 prefix が long_string に含まれているかどうかを調べる。
if (ustrncmp(prefix, long_string, ustrlen(prefix)) == 0) {
/* long_string starts with prefix */
}
返値:
0 マッチした。
正の数 照合順序 ( collating sequence) が s2 の後に s1 がくる場合。( s1 > s2)
負の数 s2 の後に s1 がくる場合。( s1 < s2 )


文字列の比較とマッチング(大文字/小文字無視)
int ustricmp(const char *s1, const char *s2);
文字列 s1 と s2 を比較する。ただし大文字か小文字どうかは無視する。
( case ignoring とは 大文字小文字を無視するという意味。)
if (ustricmp(string, user_input) == 0) {
/* string and user_input are equal (ignoring case) */
}
返値:
0 マッチした。
正の数 照合順序 ( collating sequence) が s2 の後に s1 がくる場合。( s1 > s2)
負の数 s2 の後に s1 がくる場合。( s1 < s2 )


文字列の比較とマッチング(大文字/小文字無視,最初のn文字)
int ustrnicmp(const char *s1, const char *s2, int n);
文字列 s1 と s2 の 最初から n 文字 を比較する。ただし大文字か小文字どうかは無視する。

返値:
0 マッチした。
正の数 照合順序 ( collating sequence) が s2 の後に s1 がくる場合。( s1 > s2)
負の数 s2 の後に s1 がくる場合。( s1 < s2 )
 
 
printf書式な表示
int uszprintf(char *buf, int size, const char *format, ...);
バッファのサイズに合わせて、書式に合ったテキストを表示する。文字列のほかに、変数の書き出しもできる。  返値は、NULL terminated を含む 文字数を返す。
(Allegro に収録されている unicod.dat 内にある DATAFILE形式のフォントを利用するとひらがな、カタカナの表示は可能)
  char buffer[10];
int player_score;
...
uszprintf(buffer, sizeof(buffer), "Your score is: %d", player_score);

文字列のコピー
char *ustrncpy(char *dest, const char *src, int n);
ポインタ dest へ 文字列 src の n文字ぶんをコピーする

文字列の連結
char *ustrncat(char *dest, const char *src, int n);
ポインタ dest の最後に 文字列 src の n文字ぶんを連結する


printf書式な表示(配列全体)
int uvsprintf(char *buf, const char *format, va_list args);
上の uvsprintf と同じですが、これは 配列全体を 渡すタイプである。
   返値は、 NULL terminated を含む 文字数を返す。
  
特定の文字列の出現位置を記録
char *ustrrchr(const char *s, int c);
c が最後に現れた部分のポインタを返す、なければNULLを返す。
char *p = ustrrchr("one,two,three,four", ',');
特定の文字列と一致した位置を記録
char *ustrpbrk(const char *s, const char *set);
*set に渡された文字列 のどれかとマッチする最初の位置のポインタを 返す。
なければNULLを返す。
char *p = ustrpbrk("one,two-three.four", "-. ");
文字列の検索
char *ustrtok(char *s, const char *set);
該当する 文字列 を検索する(文字列中に同じパターンが複数見つかっても、最初のものしか発見しない。)
char *word;
char string[]="some-words with dashes";
char *temp = ustrdup(string);
word = ustrtok(temp, " -");
while (word) {
allegro_message("Found `%s'\n", word);
word = ustrtok(NULL, " -");
}
free(temp);
返値: トークン(字句)へのポインタがもし見つからなければ NULLを返す。
あなたは NULLが返ってきた場合にメモリを解放することができる。
  
文字列の検索(複数マッチ対応)
char *ustrtok_r(char *s, const char *set, char **last);
該当する 文字列 を検索する(文字列中に複数見つかってもOK)。
最後のパラメータは、char ポインタのポインタ last です。
char *word, *last;
char string[]="some-words with dashes";
char *temp = ustrdup(string);
word = ustrtok_r(string, " -", &last);
while (word) {
allegro_message("Found `%s'\n", word);
word = ustrtok_r(NULL, " -", &last);
}
free(temp);
返値: トークンへのポインタor もし見つからなければ NULLを返す。
あなたは NULLが返ってきた場合にメモリを解放することができる。

Configure コンフィグ


コンフィグファイルはWindows95以前に使われていた初期設定ファイルで、アプリケーション毎にその設定を記録したものです。Allegroでは、Allegroアプリケーションのためのコンフィグファイル(拡張子.ini)を扱います。

このコンフィグファイルのデータ形式は「セクション」ごとに、それぞれ「キー」と「値」 のデータの組み合わせがあります。たとえば、ジョイスティックのキーコンフィグや、色深度、画面モードなどの設定がセクションそして設定する事ができます。

Allegroのコンフィグ関数を使えばWindowsと同じように、LinuxやMacOSXでも共通の初期設定を扱う事ができます。

.INIファイル
# セクション
[graphics]
# キー と 値
windowed= TRUE

INIファイルを使う方式は、古いといえば古い仕様(DOS に対応するため?)ですが、編集方法や使い方もシンプルです。
(Windows環境なら、設定をレジストリに書き込んだりしないアプリケーションが作れると思います..)

例えば、ゲームのオプション画面で、ゲーム中のBGMの音量や、キー入力の設定、画面解像度を設定すると 次に起動したときはその設定でゲームを開始させたい、といった場合に役に立ちます。

コンフィグファイルを読み込む
set_config_file(const char *filename);
初期設定ファイルの拡張子は 「.ini」で、allegroアプリケーションと同じディレクトリに置く必要があるようです
set_config_file("configure.ini");

読み込んだコンフィグデータを代入する
const char *get_config_string(const char *section, const char *name, const char *default );
*section セクション名 と *name 変数名 を指定すると configure.ini から読み込んだ対応データを返す。
もし設定したい 値が存在しなければ *default の値が 初期値として 返る。
int xxx = get_config_int("sound", "sound_quality", 4);
初期設定ファイルconfigure.ini に書かれているセクション名と変数は予約されているものがある。
[sound] ←セクション名 system , mouse , sound 等。
digi_volume = x← 音量や 解像度やジョイスティックの設定マウスの位置等。


ここでは紹介しませんでしたが、
get_config関数には コンフィグ設定の各変数型に合った関数がそれぞれ用意されています。
例えばget_config_string関数 なら 文字型のデータ。 get_config_int 関数なら int型のデータに対応してます。

Mouse マウス

マウス入力を有効にする
int install_mouse();
マウス関連の関数を利用するには、まずこのマウスハンドラをインストールする必要があります。

マウスの状態を調べる
int poll_mouse(); // マウスの情報に問い合わせる(ポーリング)関数
int mouse_needs_poll(); //マウスがポーリングモードかを調べる、返値が TRUEならポーリング状態

マウスカーソルの表示
void select_mouse_cursor(int cursor);
マウスカーソルは以下の定数を指定することができます。
MOUSE_CURSOR_NONE:カーソルを透明にする show_mouse(NULL);と同じ
MOUSE_CURSOR_ALLEGRO:Allegroカーソル set_mouse_sprite() でカスタマイズ可能。
MOUSE_CURSOR_ARROW: OS デフォルトの矢印カーソル
MOUSE_CURSOR_BUSY:ビジー状態の時のカーソル
MOUSE_CURSOR_QUESTION:?マークカーソル
MOUSE_CURSOR_EDIT:エディット時のカーソル(文字入力時など)

void show_mouse(BITMAP *bmp); マウスカーソルを表示する
void scare_mouse(); マウスカーソルを隠す
void enable_hardware_cursor(void); OS標準のカーソル使用を有効にする(ハードウェアカーソル)
void disable_hardware_cursor(void); OS標準のカーソル使用を無効にする

マウスの位置情報や押されたボタン情報が格納されている
extern volatile int mouse_x; // 現在のマウスカーソルのある x座標
extern volatile int mouse_y; // 現在のマウスカーソルのある y座標
extern volatile int mouse_z; // マウスのホイールの位置
extern volatile int mouse_b; // マウスボタン
extern volatile int mouse_pos; // 上位16bitに x座標,下位16bitに y座標の位置を格納している

マウスカーソル表示位置の指定・変更
void position_mouse(int x, int y);
マウスカーソルをスクリーンの指定位置に表示。カーソルが既に表示されている時でも使える。

マウスの移動量
void get_mouse_mickeys(int *mickeyx, int *mickeyy);
この関数が最後に呼ばれてからマウスがどのくらい移動したのかを計測します。マウスがスクリーンの端に到達していても、計測しつづけます。マウスの移動範囲が無限大の処理が必要な場合に利用されます。
MOUSE_FLAG_MOVE, MOUSE_FLAG_LEFT_DOWN, MOUSE_FLAG_LEFT_UP, MOUSE_FLAG_RIGHT_DOWN, MOUSE_FLAG_RIGHT_UP, MOUSE_FLAG_MIDDLE_DOWN, MOUSE_FLAG_MIDDLE_UP, and MOUSE_FLAG_MOVE_Z
マウスのコールバック関数

  • その他
    リアルタイムに頻繁な画面書き換え処理とマウスカーソル描画を同時に行う場合、プログラムが強制終了してしまうことがあります。 この問題は、カーソル位置は捕捉されるので、マウスカーソルの描画をAllegroのマウスカーソル描画関数ではなく、スプライト( draw_sprite() )等を使って描画することで回避できます。
  • Keyboard キーボード

    キーボード入力を有効にする
    int install_keyboard();
    キーボード割り込みを行う為には、必ず最初にこの呼び出す必要がある。さもなければキーボード関連の関数を呼べなくなってしまう。

    キーボードに入力された状態を取得
    int poll_keyboard();
    key[]配列を使って、押されたキーが何であるか 調べたりする場合、キーボードの状態を取得 するには定期的にこの関数を呼び出すことが必要である。 ただし、 keypressed(), readkey(), and ureadkey()関数は自動的に、この poll_keyboard()関数を呼ぶ。
    返値: 0を返せば成功、マイナス値を返せば失敗

    ポーリングモード かどうかを調べる
    int keyboard_needs_poll();
    キーボードがポーリングモードかを調べる、返値が TRUEならポーリング状態

    押されたキー
    extern volatile char key[KEY_MAX];
    Allegroシステム変数 scancode によって得られたフラグの配列。 poll_keyboard 関数を呼ぶたびに、この配列の値は更新される。 値がTRUEなら、そのキーが押されたことを示す。
    if (key[KEY_SPACE]) printf("Space is pressed\n");
    キーボードのscancode 一覧
    例えばキー「A」が押されると、key[KEY_A] の値はTrueになる。
    KEY_A ... KEY_Z,  KEY_0 ... KEY_9, KEY_0_PAD ... KEY_9_PAD, KEY_F1 ... KEY_F12,

    KEY_ESC, KEY_TILDE, KEY_MINUS, KEY_EQUALS,
    KEY_BACKSPACE, KEY_TAB, KEY_OPENBRACE, KEY_CLOSEBRACE,
    KEY_ENTER, KEY_COLON, KEY_QUOTE, KEY_BACKSLASH,
    KEY_BACKSLASH2, KEY_COMMA, KEY_STOP, KEY_SLASH,
    KEY_SPACE,

    KEY_INSERT, KEY_DEL, KEY_HOME, KEY_END, KEY_PGUP,
    KEY_PGDN, KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN,

    KEY_SLASH_PAD, KEY_ASTERISK, KEY_MINUS_PAD,
    KEY_PLUS_PAD, KEY_DEL_PAD, KEY_ENTER_PAD,

    KEY_PRTSCR, KEY_PAUSE,

    KEY_ABNT_C1, KEY_YEN, KEY_KANA, KEY_CONVERT, KEY_NOCONVERT,
    KEY_AT, KEY_CIRCUMFLEX, KEY_COLON2, KEY_KANJI,

    KEY_LSHIFT, KEY_RSHIFT,
    KEY_LCONTROL, KEY_RCONTROL, KEY_ALT, KEY_ALTGR,
    KEY_LWIN, KEY_RWIN, KEY_MENU,
    KEY_SCRLOCK, KEY_NUMLOCK, KEY_CAPSLOCK

    KEY_EQUALS_PAD, KEY_BACKQUOTE, KEY_SEMICOLON, KEY_COMMAND
    NumLock 等、特殊キー
    extern volatile int key_shifts;
    これらはSHFTやControl やWindow のaltキーや 特殊文字キーの状態を含んでいる。
    poll_keyboard 関数によってこれらの値が更新されるが、現在の状態を調べるには、
    現時点で poll_keyboard 関数を呼ぶ必要がある。
    KB_SHIFT_FLAG KB_CTRL_FLAG KB_ALT_FLAG KB_LWIN_FLAG KB_RWIN_FLAG
    KB_MENU_FLAG KB_COMMAND_FLAG KB_SCROLOCK_FLAG KB_NUMLOCK_FLAG
    KB_CAPSLOCK_FLAG KB_INALTSEQ_FLAG KB_ACCENT1_FLAG KB_ACCENT2_FLAG
    KB_ACCENT3_FLAG KB_ACCENT4_FLAG
       if (key[KEY_W]) {
          if (key_shifts & KB_SHIFT_FLAG) {
          /* User is pressing shift + W. */
          } else {
          /* Hmmm... lower case W then. */
          }
       }
    たとえば、capslockキーで、カタカナひらがな入力の切り替えを行う例。 capslockキーが押されている間は カタカナを入力するという場合。
    if ( key_shifts & KB_CAPSLOCK_FLAG ) {
    ustrcat( tests , rtok_table[j].dist);//カタカナ
    }else{
    ustrcat( tests , rtok_table[j].disth); //ひらがな
    }

    if ( key_shifts & KB_CAPSLOCK_FLAG ){ mode="カナ"; }else{ mode="かな";}
    textprintf_ex(keybuffimage, font, 30, list_pos , makecol(250, 0, 0), -1,"【キー入力情報】[%s]" , mode);

    何かキーが押されたか判断する
    int keypressed();
    返値:TRUE なら、何かキーが押されたことを示す
    readkey(); は入力待ちのためプログラムの進行がストップしてしまう。それを回避するには keypressed(); を使って判断し、 キーが押されたときだけキー入力を拾うようにするとよいです。

    キー入力を拾う
    int readkey();
    キーで入力された文字を得る。
    int val;
    val = readkey();
    バッファが空の間は、キー入力までプログラムの進行を待機させるので ユーザーの入力に対して次の場面に進ませるという使い方もできる。
    textout(screen, font, 30, 20, 0 , -1," -PUSH ANY KEY - なにかキーを押してネ" );
    readkey();
    // スクリーンを消去して 次の場面へ
    clear_to_color(screen , makecol(255, 255, 255));
    キー入力を拾う(Unicode版)
    int ureadkey(int *scancode);
    readkey 関数と同じくバッファが空の間は、キー入力までプログラムの進行を待機させるが、 ureadkeys関数は 255以上の値も扱える点が違っている。また、スキャンコードのアドレスを引数に入れなければいけない。

    キー入力からコードに変換
    int scancode_to_ascii(int scancode);
    キー入力からキーの名称を取得
    const char *scancode_to_name(int scancode);
    int val, scancode,ascii;
    char keyname;
    if( keypressed() ){
      val = ureadkey(&scancode);
      ascii = scancode_to_ascii( scancode);
      keyname = scancode_to_name( scancode);
    }

    textprintf_ex(screen, font, 30, 20, 0 , -1,"Scancode: 0x%04x ", scancode );
    textprintf_ex(screen, font, 30, 30, 0 , -1,"ASCII  : 0x%04x ", ascii );
    textprintf_ex(screen, font, 30, 40, 0 , -1,"Val   : 0x%04x ", val );
    textprintf_ex(screen, font, 30, 50, 0 , -1,"keyname: %s ", keyname );
    textprintf_ex(screen, font, 30, 60, 0 , -1,"String  : %c ", val );

    結果:(スペースキーを押した場合)
    Scancode:0x004b
    Ascii   :0x0020
    Val    :0x0020
    Keyname :SPACE
    String  : //実際に入力された文字
    UTF8では、"ん"= E38293 なので "\xE3\x82\x93" のように書いても"ん" と表示できます。 (※ 「¥」は実際には、バックスラッシュ)
    textout_centre_ex(screen, font, "\xE3\x82\x93" , 160, 96, makecol(0, 255, 0), -1);
    textout_centre_ex(screen, font, "ん" , 160, 96, makecol(0, 255, 0), -1);

    キー入力のシミュレート
    void simulate_keypress(int key);
    キーを押さなくても、 キーバッファにキー入力情報を渡すことで、ユーザーがキーを押したようにみせかける。 キーバッファの内容は、それぞれreadkey();、 ureadkey(); を使って判別する。
    simulate_keypress(KEY_SPACE << 8);
    if (readkey() == (KEY_SPACE << 8))
    allegro_message(" Alt+Space キーを押しましたか?");

    キー入力のシミュレート(Unicode版)
    void simulate_ukeypress(int keyy, int scancode );
    simulate_ukeypress(0x00DF, 0);
    if (ureadkey(&scancode) == 0x00DF)
    allegro_message("シャープ記号を入力した");
    使っている キーボードの種類によってキーが存在しなくても 、この関数によってフォローすることができる。 また、 キーボード以外の ソフトウェアキーボードやストロークを利用して文字入力する場合にも使えるかもしれない。

    キー入力設定
    void set_keyboard_rate(int delay, int repeat);
    リピート入力認識までの時間と、キーのリピート速度を設定する。 それぞれ ミリ秒 単位 で指定する。 もし 引数に 0 を指定した場合は リピート入力認識が「切」になる。

    キーバッファをクリアする
    void clear_keybuf();
    キーバッファの内容をクリアしたい場合に使うことができる。

    Timer タイマー関連

    時間やタイミングに関する分野。ウェイトをかけたり、定期的に関数を呼び出したい場合に使える。

    タイマー機能を有効にする
    int install_timer(void);
    Allegro システムによる割り込みハンドラを有効にする。

    インターバル機能を有効にする
    int install_int(void);
    ユーザーによる割り込みハンドラを有効にする(int = interval のことか?)

    ウェイトをかける
    int rest(unsigned int time);
    この関数は install_timer() に属し、指定した 時間(ミリ秒)だけ プログラムを待機させる。
    他には、 画面の書き換えと同期するには vsync() 関数を使う方法がある。

    メモリの保護
    Macro LOCK_VARIABLE(variable_name);
    Macro LOCK_FUNCTION(function_name);
    Macro END_OF_FUNCTION(function_name);
    タイマー関数や変数のメモリを保護する。 END_OF_FUNCTION は、タイマー関数の最後に必須。
    volatile int counter;

    void my_timer_handler()
    {
    counter++;
    }

    END_OF_FUNCTION(my_timer_handler)
    メモリ保護の詳細については install_int_ex() の説明を見ること。

    Joystick routines ジョイスティック

    (仮)
    Allegroはマウスやキーボードでもないハードウェア、ジョイスティック入力を実装する。
    しかし、ほとんどのプラットホームがジョイスティックの割り込みに対応していないので、
    正しいジョイスティックの入力を得るには、プログラム中で、すくなくとも1フレームにつき1回は
    入力を監視(ポーリング)されなければならない。

    ジョイスティックの初期化
    int install_joystick(int type);
    ジョイスティックの初期化と、中心位置を調節する。
    ジョイスティック関連の関数を呼び出す前に必ず初期化を行う。
    通常パラメータ int type は JOY_TYPE_AUTODETECT を指定する。
    textout_centre_ex(screen, font,
    "Center the joystick and press a key",
    SCREEN_W/2, SCREEN_H/2, red_color, -1);
    readkey();
    if (install_joystick(JOY_TYPE_AUTODETECT) != 0)
    abort_on_error("Error initialising joystick!");
    返値:
    0 成功


    ジョイスティックの使用を終了
    void remove_joystick();
    ジョイスティックの使用を終了する。これは allegro_exit()が自動的に行うので、呼び出す必要はない。


    ジョイスティックのポーリング
    int poll_joystick();
    ジョイスティックには割り込み機能が備わっていない。
    そのため、ジョイスティックからの入力を調べるにはこの関数をそのつど呼び出さなければいけない。
    コードの例:
    do {
    /* Get joystick input */
    poll_joystick();

    /* Process input for the first joystick */
    if (joy[0].button[0].b)
    first_button_pressed();

    if (joy[0].button[1].b)
    second_button_pressed();
    ...
    } while(!done);
    返値:
    0 成功
    マイナス 失敗


    接続しているジョイスティックの数
    extern int num_joysticks;
    グローバル変数。 有効なジョイスティックの番号が格納されている。
    現在サポートされているドライバーは4つまで認識する。


    ジョイスティックの情報
    extern JOYSTICK_INFO joy[n];
    ジョイスティックの情報が格納されているグローバル配列
    この内容は、poll_joystick() 関数が呼ばれるたびに更新される。

    はじめは、num_joysticks と同じ値しか入っていない。
    typedef struct JOYSTICK_INFO
    {
    int flags; - このジョイスティックの状態フラグ 
    int num_sticks; - 何個のジョイスティックが接続されているか?
    int num_buttons; - いくつのボタンがあるか?
    JOYSTICK_STICK_INFO stick[n]; - スティックの状態
    JOYSTICK_BUTTON_INFO button[n]; - ボタンの状態
    } JOYSTICK_INFO;
    int flags;が返す値
    JOYFLAG_DIGITAL - 現在提供されているコントローラはデジタル入力モードである。
    JOYFLAG_ANALOGUE - 現在提供されているコントローラはアナログ入力モードである。
     
    JOYFLAG_CALIB_DIGITAL - デジタル入力の提供可能だが、一度調整されなければ今使用することはできない。

    JOYFLAG_CALIB_ANALOGUE- アナログ入力の提供可能だが、一度調整されなければ今使用することはできない。

    JOYFLAG_CALIBRATE - 調整が必要。このフラグが取り除かれるまで、calibrate_joystick() 関数を呼び出して機能を有効にしなければ動かない。


    JOYFLAG_SIGNED - アナログスティックの位置が signed format (-128 to 128)で表されている。これは2D 方向の制御である。
    JOYFLAG_UNSIGNED - アナログスティックの位置が unsigned format( 0 to255)で表されている。これは1D スロットル制御である。

    ボタン情報。
    typedef struct JOYSTICK_BUTTON_INFO
    {
    int b; - boolean on/off フラグ
    char *name; - 押されたボタン名に関する情報
    } JOYSTICK_BUTTON_INFO;
    機能がどのボタンに割り当てられるか表示したければ、これらの情報が利用できる。
    各ジョイスティックに備わっている、1つまたは複数のスティック入力の変化や、指定位置にあるかコントロールする事ができる。

    スティック入力に関するストラクチャはこのようになっている。
    typedef struct JOYSTICK_STICK_INFO
    {
    int flags; - 入力に関する 状態フラグ
    int num_axis; - コントローラが装備しているスティックの数
    JOYSTICK_AXIS_INFO axis[n]; - スティックの軸の状態に関する情報
    char *name; - この入力に対する記述
    } JOYSTICK_STICK_INFO
    ひとつのジョイスティックは、複数の違ったスティック入力が提供されるかもしれないが、
    安心してスティックの初期配列をメインのコントローラの方向性に委ねることができる。


    スティックの初期位置やボタン割り当てがストラクチャに格納されている。
    typedef struct JOYSTICK_AXIS_INFO
    {
    int pos; - アナログスティックの 軸位置
    int d1, d2; - デジタルスティックの 軸位置
    char *name; - 軸に関する記述
    } JOYSTICK_AXIS_INFO;
    int pos の部分にはアナログ入力( 制御方式によっては 値は -128〜128 または 0〜255の範囲をとる)
    int d1 と d2 の部分にはデジタル入力の値が格納される。

    たとえば、 X軸に対する入寮があったとき pos には 水平位置が、 d1 にはそれが左に傾いた、d2にはそれが右に傾いたという情報が入る。 Allegroは、これらすべての値がアナログジョイスティックからの入力なのか、デジタルジョイスティックからの入力なのかどうかを気にせずに取得する。 つまり、デジタルスティックからの入力の場合、 pos には、 min, middle , maximum の位置から割り出された 値が エミュレートされる。 また、アナログスティック から入力したの場合、d1とd2 は アナログスティックの中心位置と現在位置を比較して計算された値がエミュレートされることになる。
     


    ジョイスティックの 調整
    const char *calibrate_joystick_name(int n);
    あなたが調整したいと思うジョイスティックの番号をint n に渡す。

    返値:
    テキスト - 指定されたジョイスティックのタイプ
    NULL  -  調整が得られなかった場合



    ジョイスティックの 調整
    int calibrate_joystick(int n);

    ほとんどのジョイスティックは完全なアナログ入力を提供する前に調整する必要がある。
    この関数はスティックの軸を設定するために、calibrate_joystick_name() の前に呼び出される必要がある。
     
    例えば、十分にジョイスティックすべてが有効かどうか調整するには次のようにする
    int i;

    for (i=0; i<;num_joysticks; i++) {
    while (joy[i].flags & JOYFLAG_CALIBRATE) {
    char *msg = calibrate_joystick_name(i);
    textprintf_ex(..., "%s, and press a key\n", msg);
    readkey();
    if (calibrate_joystick(i) != 0) {
    textprintf_ex(..., "oops!\n");
    readkey();
    exit(1);
    }
    }
    }
    返値:
    0 - 成功
    0以外 - 調整はうまくいかなかった。

    ジョイスティックの 調整データのロード
    int save_joystick_data(const char *filename);
    頭痛の種になりそうなジョイスティックの調整作業を、をユーザーにまた繰り返させたいは思わないかもしれない。 この関数によって、コンフィグファイルに、ジョイスティックの調整データを保存することができる。 このデータは、後でload_joystick_data() を呼び出す事で読み込む事が出来る。 ファイルネームに NULLを 渡すと、現在選択されているコンフィグファイルが指定される。

    返値:
    0 -  コンフィグファイルへ調整データの記録が成功した
    0以外 - データは記録されない。


    ジョイスティックの 調整データのセーブ
    int load_joystick_data(const char *filename);
    save_joystick_data() または セットアップユーティリティによって記録された ジョイスティック調整データを読み込む。
    なお、この関数を呼んだ場合には、install_joystick() を呼ぶ必要はない(内部で呼び出しているため)。
    ファイルネームに NULLを渡すと、現在選択されているコンフィグファイルが指定される。


    返値:
    0 -  読み込みが成功した
    0以外 - もしジョイスティックが未定義で読み込みが失敗するなら、再びジョイスティックを初期化しなければならない。


    Graphics modes 画面モードの設定。

    Allegro の画面を設定する機能を提供する。これがなければ画面に文字や画像を貼付けることもできない。
    Allegroは 主に「フルスクリーンモード」 と 「ウインドウモード」 の2つのタイプの表示方法を扱う事が出来る。

    この項では、最低限知っておいたほうがいい関数だけ紹介。
    他にも機能はたくさんありますが、説明は割愛する。
    ( mode-X 、create_video_bitmap() 、スクロール関数 や トリプルバッファリング等)


    スクリーンを設定する
    int set_gfx_mode(int card, int w, int h, int v_w, int v_h);

    パラメータ:
    int card には グラフィックモードを設定するAllegro magic drivers を設定する。
    int w: スクリーンの幅
    int h :スクリーンの高さ
    int v_w: 仮想スクリーン  の幅
    int v_h :仮想スクリーン  の高さ

    仮想スクリーン は トリプルバッファリングなどによる ハードウェアスクロールや Page Flipping を利用する時に活用されます。  仮想スクリーン  についてあれこれ心配したくなければ、 それぞれ 0 を指定してください。
    色深度を設定する場合は、この関数を呼ぶ前に設定してください。

    Allegro magic drivers - int card の パラメータに設定する引数。
    * GFX_AUTODETECT:
    Allegro は、まず、フルスクリーンモードで 現在の 色深度に対応した 解像度を設定しようとする。もし該当する解像度をを見つけられなければ 今度はウインドウモードで同じように 試みる。 set_gfx_mode() 関数 呼び出しに成功すると、解像度と色深度が保証されるが、プログラムが フルスクリーンで動くか ウインドウモードで動かされるのかは、ユーザーのPC環境やビデオカードに左右される。

    * GFX_AUTODETECT_FULLSCREEN:
    Allgro はフルスクリーンモードで指定された 解像度と色深度 を設定しようとする。もしその指定が設定でなければ、 set_gfx_mode() 呼び出しは失敗する。

    * GFX_AUTODETECT_WINDOWED:
    Allgro はウインドウモードで指定された 解像度と色深度 を設定しようとする。もしその指定が設定でなければ、 set_gfx_mode() は失敗する。 ウインドウモードが実行されるとき、'指定した解像度' は、そのウインドウ内のグラフィック描画エリアの縦横のサイズを意味する。 もし、Allegro ウインドウ内の色深度と デスクトップ画面の色深度と一致しない場合は、描画速度に差が出る可能性がある。 この場合は desktop_color_depth() 関数を使って解決する。

    * GFX_SAFE:
    Allegro ドライバは、指定された解像度が見つからなければ、 グラフィックカードに用意されている解像度に正しく設定する。320x200 , 640x480 など。 もしどんな解像度設定も不可能な場合は -1 を返してプログラムを終了させる。

    * GFX_TEXT:
    あらゆるグラフィックモードを閉じて、グローバルなscreen オブジェクトを利用できなくして、テキストモード (ふつうは 80x25) に入る。 このドライバモードをセットした場合、他のパラメータはどんな意味もなさなくなるので、他のパラメータには 0 を指定しておく。
    返値:
    0 = 成功
    負の数 = 失敗, allegro_error. が記録されるらしい。

    この関数の呼び出しに成功すると、以下のマクロにスクリーンの情報が反映される。
    SCREEN_W, SCREEN_H, VIRTUAL_W, VIRTUAL_H


    リフレッシュレートの要求(WIN, DOSのみ)
    void request_refresh_rate(int rate);
    この関数を事前に呼び出しておくと、次に set_gfx_mode() が呼ばれたときにリフレッシュレートを取得する。 現在、 DOS VESA 3.0, X DGA 2.0 といくつかの Windows DirectX drivers しかサポートしていない。
    request_refresh_rate(60);
    if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0)
    abort_on_error("Couldn't set graphic mode!");
    if (get_refresh_rate() != 60)
    abort_on_error("Couldn't set refresh rate to 60Hz!");


    リフレッシュレートの参照(WIN,DOSのみ)
    int get_refresh_rate(void);
    もし取得可能であれば リフレッシュレートを返す。

    返値
    正の数 = リフレッシュレート
    0 = リフレッシュレートが不明


    色深度のセット
    void set_color_depth(int depth);
    set_gfx_mode() や create_bitmap() で呼び出される 色深度を設定する。
    デフォルトでは、 8 が設定されており 15, 16, 24, 32 (bits) の深度が設定できる。
    ※必ず、set_gfx_mode()関数 の前に呼び出してください。
    set_color_depth(32); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) { abort_on_error("Couldn't set a 32 bit color resolution"); }


    色深度の取得
    int get_color_depth(void);
    現在の画面モードの 色深度を取得する。

    BITMAP Object ビットマップ

    画面表示領域
    extern BITMAP *screen;
    Allegroのシステムで予約されているグローバルなポインタ。画面表示を受け持つ特殊なオブジェクトであり、 他のビットマップオブジェクトと違って仮想領域に内包される形で、画面表示領域が存在する。

    仮想領域の大きさは、VIRTUAL_W x VIRTUAL_H , 画面表示領域は SCREEN_W x SCREEN_H という定数で表される。 通常は左上隅(0,0)が起点になっていますが、もし興味があればハードウェアスクロールや page flipping によってこの制限を無視する事もできるらしい。 基本的には画面表示領域の窓となる部分を変更することで、表示領域の大きさを変えることになる。

    画面表示領域は、左上隅(0,0)が起点になっている。例えば画面上に点を描画するにはこのようにする。
    putpixel(screen, x, y, color);

    画面表示領域の幅と高さ
    #define SCREEN_W;
    #define SCREEN_H;
    Allegroのシステムであらかじめ定義されている定数。
    画面モードを設定した場合、表示画面の幅と高さはそれぞれこの定数で得る事ができる。
    SCREEN_W , SCREEN_H


    ビットマップオブジェクトの宣言
    BITMAP *images;
    画像データを扱うオブジェクト。画像を表示するだけではなく、スプライトパターン格納領域や オフスクリーンバッファ の入れ物としても使える。 宣言しただけでは、まだ使えない。create_bitmap 関数によって描画領域を指定する必要がある。

    描画領域の作成
    BITMAP *create_bitmap(int width, int height);
    BITMAP *create_bitmap_ex(int color_depth, int width, int height); 色深度を指定するタイプ
    ビットマップオブジェクトのメモリ上に 高さx,幅yのビットマップ領域が作られる。これによってはじめて描画か可能となる。

    ビットマップ画像ファイルの読み込み
    BITMAP *load_bitmap(const char *filename, RGB *pal);
    BMP, LBM, PCX, TGA 画像ファイルを読み込むことができる。(一応、各画像形式を読み込む関数も用意されている)  256色のRGBパレットを読み込むことも可能。
    BITMAP *images;
    images = load_bitmap("picture.pcx", NULL);
    if (!bmp) abort_on_error("Couldn't load picture.pcx!");
    blit( screen , 0,0,0,0,320,200);//画面に表示
    destroy_bitmap(images);

    PackFile内の bmpファイルの読み込み
    BITMAP *load_bmp_pf(PACKFILE *f, RGB *pal);
    AllegroのPackFile圧縮 がかけられたbmpファイルを読み込む。

    ビットマップ画像をファイルとして保存
    int save_bitmap(const char *filename, BITMAP *bmp, const RGB *pal);
    BMP, PCX , TGA 形式で保存できる。この関数は、画面上に表示された ビットマップ オブジェクトの内容をファイルに出力するが   スクリーンショットを保存する場合は注意が必要である。

    BITMAP *screen オブジェクトは特殊で 実際に見えてる画面領域の 外側に 仮想画面領域 を持っているため、そのまま保存すると仮想画面領域まで含んでしまうのでファイルサイズが大きくなる。 この問題を回避するには sub-bitmap 関数を使って *screen オブジェクトの一部分を切り取った内容をファイルに出力する。
    BITMAP *bmp;
    PALETTE pal;
    ...
    get_palette(pal);
    bmp = create_sub_bitmap(screen, 0, 0, SCREEN_W, SCREEN_H);
    save_bitmap("screenshot.pcx", bmp, pal);
    destroy_bitmap(bmp);

    システム描画領域の作成
    BITMAP *create_system_bitmap(int width, int height);
    システムメモリ上に割り当てる。ほかのビットマップオブジェクトとは違い特殊な性質を持つ。

    サブ描画領域の作成
    BITMAP *create_sub_bitmap(BITMAP *parent, int x, y, width, height);
    このcreate_sub_bitmap関数によって作られたビットマップオブジェクトは、 親である *parent の描画領域の内容を共有している。 sub_bitmap で指定する場合、幅と高さwidth, height は、親ビットマップの描画領域よりも小さくなければならない。
    返値:NULL なら 作成に失敗。
    注意:親ビットマップオブジェクト をdestroy_bitmap を解放する場合は、先に sub_btmap で作られた ビットマップを解放しなければいけない。さもなければメモリリークが発生する。

    ビデオメモリ領域の作成
    BITMAP *create_video_bitmap(int width, int height);
    指定サイズのビデオメモリビットマップを割り振る。ハードウェアアクセラレーションによって行われる画像の転送のために割り振られたビデオメモリが使われる。またはshow_video_bitmap() の呼出しによって表示することができる多数のビデオ記憶ページを作成するのに使用することができる。

    注意:ビデオメモリビットマップは通常スクリーンビットマップと同じスペースから割り振られている。それゆえ、この関数と グローバルなビットマップスクリーン (*screen オブジェクトのこと) を同時に使用するのはあまりよい考えとはいえない。


    マスクカラーの取得
    int bitmap_mask_color(BITMAP *bmp);
    マスクカラーは、スプライトやblitting を使う場合、背景を透過する透明色となる色のことで、色深度によってそれぞれ定義されている。 この関数は、該当ビットマップの色深度に応じたマスクカラーを返す。

    返値:
    0. - 256色モードのマスクカラーは「0」
    makecol(255,0,255)にあたるピンク色 - TrueColor の場合は。
    /* マスクカラーを他の色に変更するサンプル. */
    for (y = 0; y < bmp->h; y++)
    for (x = 0; x < bmp->w; x++)
    if (getpixel(bmp, x, y) == bitmap_mask_color(bmp))
    putpixel(bmp, x, y, another_color);


    メモリの解放
    void destroy_bitmap(BITMAP *bitmap);
    使い終わったら destroy_bitmap によってデータを破棄します。

    Truecolor pixel formats 色形式

    色指定についての関数はたくさんある。初めはこれ1つだけ知っておくと便利。

    色指定
    int makecol(int r, int g, int b);
    RGB それぞれ0-255の範囲で指定した形式で、色データを指定する汎用の関数。 例えば、文字色や画面消去や様々な場面に使われる。 ここでは紹介しないが、ビデオモードや色深度 8, 15, 16, 24, 32-bit 専用の関数もある。
    /* どんな色深度モード でもこれは緑色に見える */
    int green_color = makecol(0, 255, 0);

    /* 透明色の指定 (truecolor の場合) */
    int masked_color = makecol(255, 0,255);
    返値:
    色深度と指定したパラメータに対応した RGB 三項値

    この関数は、他の関数内のパラメータに直接書く事もできる。
    textprintf_ex( screen font, x, y , makecol(0, 0, 0), -1,"3rd letter: 0x%04x", third_letter );

    Drawing primitives 図形描画

    ビットマップからピクセル値を取得
    getpixel — getpixel().の高速版
    _getpixel15 — getpixel().の高速版
    _getpixel16 — getpixel().の高速版
    _getpixel24 — getpixel().の高速版
    _getpixel32 — getpixel().の高速版

    ビットマップにピクセル値を書き込む
    putpixel — putpixel().の高速版
    _putpixel15 — putpixel().の高速版
    _putpixel16 — putpixel().の高速版
    _putpixel24 — putpixel().の高速版
    _putpixel32 — putpixel().の高速版

    円や直線 、ポリゴン等を描画
    arc — 円弧を描画 
    calc_spline — スプライン曲線を計算する
    circle —円を描画 
    circlefill — 塗られた円を描画 
    do_arc — すべての点を通る円弧を描画 
    do_circle —すべての点を通る円を描画 
    do_ellipse — すべての点を通る楕円体を描画
    do_line — すべての点を通る直線を描画
    ellipse — 楕円体を描画
    ellipsefill — 塗られた楕円体を描画
    fastline — line()の高速版
    floodfill — 閉じた領域を塗る
    getpixel — ビットマップピクセルを読み込む
    hline — 水平線を描画
    line — 直線を描画
    polygon — 塗られた多角形(ポリゴン)を描画
    putpixel — ビットマップピクセルを書き込む.
    rect — 長方形を描画
    rectfill — 塗られた長方形を描画
    spline — コントロールポイントを持ったスプライン曲線を描画
    triangle — 塗られた三角形を描画
    vline — 垂直線を描画

    blitting & Sptite 矩形領域のコピー

    ビットマップオブジェクトの指定領域のデータをコピーして、スクリーン画面の指定した場所へ表示する。

    単に画像を表示するだけでなく、画面上にマップチップなどを配置したり、カウンター数字を表示したり、画面上に見えないバッファとして利用したり 様々な場面でよく使われる。

    画像の転送
    void blit( BITMAP *src コピー元
    , BITMAP *dest 転送先
    , int cx コピー元 x座標
    , int cy コピー元 y座標
    , int dx 転送先 x座標
    , int dy 転送先 y座標
    , int width 幅 width
    , int height 高さ height
    );

    コピー元 描画領域 の (cx,xy)-(cx+width,cy+height)の矩形領域を、
    転送先のメモリ領域 (dx,dy)-(dx+width,dy+height)へコピーする。
    コピー元 と 転送先が同じでも問題ないとか。

    BITMAP *bmp 転送元 --- 画面に表示されない オフスクリーン
    ↓ 転送ー
    BITMAP *scren 転送先が screen の場合 画面上に表示される

    画像の転送(拡大)
    画像を拡大して表示する。
    void stretch_blit( BITMAP *source コピー元
    , BITMAP *dest 転送先
    , int source_x コピー元x座標
    , source_y コピー元y座標
    , source_width
    , source_height高さ
    , int dest_x転送先x座標
    , dest_y 転送先y座標
    , dest_width 拡大後の幅
    , dest_height拡大後の高さ
    );

    引数は、コピー元の( x , y , 幅 , 高) 転送先(x,y,幅,高)の順になっているので注意する。 コピー元のビットマップ画像データのメモリ領域 から(cx,xy)-(cx+original_width,cy+original_height)の矩形領域を、 転送先のメモリ領域 (dx,dy)-(dx+dist_width,dy+dist_height)へコピーする。 画像サイズ以上の座標を指定するとエラーになる。

    blit と blit stretch は内部処理が微妙に違うそうです。32000色モード上で、白黒2色のbmp形式の画像を正常に表示するには 必ずset_gfx_mode()関数の直前で、set_color_depth 関数で色深度を設定しておけば問題ありません。

    画像の転送(透過)
    void masked_blit( BITMAP *src コピー元
    , BITMAP *dest 転送先
    , int cx コピー元 x座標
    , int cy コピー元 y座標
    , int dx 転送先 x座標
    , int dy 転送先 y座標
    , int width 幅 width
    , int height 高さ height
    );

    画像中のピクセルRGB(255,0, 255)=「濃いピンク」 を 透明色として扱い、透過させることができる。ただし、コピー元と転送先の色深度は同じでなければならない。

    画像の転送(透過 拡大)
    void masked_stretch_blit(BITMAP *source コピー元
    , BITMAP *dest 転送先
    , int source_x コピー元x座標
    , source_y コピー元y座標
    , source_width
    , source_height高さ
    , int dest_x転送先x座標
    , dest_y 転送先y座標
    , dest_width 拡大後の幅
    , dest_height拡大後の高さ
    );

    ↑上記の拡大処理

    Sprite スプライト

    スプライトは、前述の blit 関数 よりも高速で、重い処理をしてもゴミが残らない。 また、ビットマップオブジェクト全体を一度に送るので、幅や高さのパラメータを指定する必要がないという特徴をもっている。

    Allegro のスプライトには、通常のスプライト, 圧縮スプライト,コンパイルスプライト の3方式が存在する。

    スプライトを表示させる
    void draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y);
    転送先の領域 *bmp の座標 (x,y)の位置に、スプライト *sprite を表示する。

    スプライトの拡大処理
    void stretch_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int w, int h);


    スプライトの反転処理 (垂直方向/水平方向)
    void draw_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y);
    void draw_sprite_h_flip(BITMAP *bmp, BITMAP *sprite, int x, int y);
    void draw_sprite_vh_flip(BITMAP *bmp, BITMAP *sprite, int x, int y);


    スプライトの回転処理 (回転の中心座標は画像の左上)
    void rotate_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle);


    半透明スプライト  
    void draw_trans_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y);
    void draw_trans_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite, int x, int y);
    ブレンド関数に依存 こちらを参照。

    RLE圧縮スプライト

    メモリ消費を抑えたい場合はこの圧縮スプライトを使う。処理速度は通常のスプライトとあまり変わらないようだ。 RLE圧縮スプライトは 拡大、回転処理は用意されていないが、半透明処理 はサポートしている。

    RLE_SPRITE *get_rle_sprite(BITMAP *bitmap );RLEスプライトを定義。
    void draw_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite, int x, int y);表示

    RLEスプライトを使用する方法。
      通常の画像をスプライトをRLEスプライトとして使用するには一行足すだけで済む。
    しかし、get_rle_sprite でRLEスプライトを定義するタイミングを間違えるとプログラムは強制終了する。
    これは、 blitして画像データを転送した後のタイミングでRLEスプライトを定義すると問題なく動作する。
    BITMAP *image;//画像
    BITMAP *tako_bitmap_pat[4];//スプライト用
    RLE_SPRITE *tako_pat[4];//RLEスプライト用
    //タコ画像→スプライト用領域へコピー
    int i;
    for(i=0;i<3;i++){ ;
    //tako_bitmap_pat[i] = create_bitmap(25,33);
    blit(image, tako_pat[i] , 26*i, 0 ,0,0 ,25,33);//画像を転送。
    tako_pat[i]=get_rle_sprite(tako_bitmap_pat[i]);//このタイミングで RLEスプライトを定義
    }
    // tako_pat が BITMAP でもなぜか動くけど 構造体自体が違うので間違いです。.... tako_pat[i]=get_rle_sprite(tako_pat[i]);。
    メモリの解放や、表示は 関数はRLEスプライト用のものが用意されている。
    draw_rle_sprite( buffer, tako_pat[pat], tako[j].x, tako[j].y );//RLEスプライト用の関数
    destroy_rle_sprite(tako_pat);//RLEスプライトを破棄

    COMPILED_SPRITE

    COMPILED_SPRITE *get_compiled_sprite(BITMAP *bitmap, int planar);
      Compiled Sprite の処理速度はシステムのハードウェアに依存する。比較的高速だがメモリを多く消費するという。  二番目のパラメータ int planar は、 FALSEなら ビットマップメモリを利用し、TRUE なら mode-X or Xtended mode を利用する。 詳細は不明だが 通常使用するならFALSE を指定しておく。

    COMPILED_SPRITEを表示
    draw_compiled_sprite( BITMAP *dist_screen, BITMAP *charachip, int x, int y );
    COMPILED_SPRITEのメモリを解放
    destroy_compiled_sprite( BITMAP *charachip ); //スプライトを破棄
    Compiled Sprite の導入法も RLEスプライトと同じやり方。

    Font & Text - フォント関連とテキスト表示

    拡張子 .fnt の bios 形式または、Allegro のDATAFILE 形式のUnifontによる文字表示を行う。 FONTオブジェクト に格納されている フォントデータをもとに文字を描画する。

    これらの関数で日本語を表示するには、プログラムで使うコードをユニコードにして、DATAFILE形式のUnifontを自作するか、拡張ライブラリによってTrueTypeフォントを bios フォントに適用するしかない。
    UTF8 エンコードを使っている場合、"ん"は UTF8では「E38293」と表されるので "\xE3\x82\x93" のように書いても"ん" と表示できます。
    textout_centre_ex(screen, font, "\xE3\x82\x93" , 160, 96, makecol(0, 255, 0), -1);
    textout_centre_ex(screen, font, "ん" , 160, 96, makecol(0, 255, 0), -1);
    (※ 「¥」は実際には、半角バックスラッシュ)

    システムフォント・オブジェクト
    extern FONT *font;
    Allegro システム内部で定義されているオブジェクト。
    GUI や textout_ex 関数で表示される文字は この font オブジェクトが使われる。
    デフォルトのフォントサイズは 8x8 pixel で、ASCII (U+20 to U+7F), Latin-1 (U+A1 to U+FF), Latin 拡張(U+0100 to U+017F)キャラクタの範囲が割り当てられている。

    見つからない文字
    extern int allegro_404_char;
    Allegro システム内部で定義されている定数。
    デフォルトでは「^」に設定されている。フォント内にない文字は、すべてこれで表現される。


    文字列の幅を取得
    int text_length(const FONT *f, const char *str);
    テキストの幅(pixel)を返す。byte数ではないので注意。

    文字列の高さを取得
    int text_height(const FONT *f);
    テキストの高さ(pixel)を返す。フォントが画像データとして扱っているから px なのです。


    メモリを解放
    void destroy_font(FONT *f);
    フォントデータの解放。ただし、AllegroFont のようなテキスト補助ライブラリを利用する場合、
    必ず拡張ライブラリにincludeされている関数を使って解放する必要がある。
    この関数を併用して用いると競合し、クラッシュする場合があるので注意。

    テキスト表示

    通常表示 (左揃え)
    void textout_ex(BITMAP *bmp, const FONT *f, const char *s, int x, y, color, bg);
    テキストを(x,y) の位置に 表示する
    (描画領域 , フォント , 文字列 , x座標 , y座標 , 文字色 , 背景色)

    中央揃え
    void textout_centre_ex(BITMAP *bmp, const FONT *f, const char *s, int x, y, color, bg);
              に比べて中央よりに表示。

    右揃え
    void textout_right_ex(BITMAP *bmp, const FONT *f, const char *s, int x, y, color, bg);
                               に比べて右よりに表示

    間隔を開ける
    void textout_justify_ex(BITMAP *bmp, const FONT *f, const char *s, int x1, x2, y, diff, color, bg);
    文 字 を 一 定 の 間 隔 を 空 け 表 示 す る 。
    diff : スペースの最小値

    Printf 書式で表示
    void textprintf_ex(BITMAP *bmp, const FONT *f, int x, y, color, bg, const char *fmt, ...);
    void textprintf_centre_ex(BITMAP *bmp, const FONT *f, int x, y, color, bg, const char *fmt, ...);
    void textprintf_right_ex(BITMAP *bmp, const FONT *f, int x, y, color, bg, const char *fmt, ...);
    void textprintf_justify_ex(BITMAP *bmp, const FONT *f, int x1, x2, y, diff, color, bg, const char *fmt, ...);
    文字列中に、変数を含めて表示することができる。 printf()な書式で便利ですが長文に向かない。 (...文字列、文字列, )

    Polygon rendering ポリゴンレンダリング

    (仮)これらのルーティンは、「Allegro3D」 と呼ばれる。
    Allegro3D が使えるレンダリングは、スキャンライン方式と Zバッファ方式の2種類。  マスク、半透明、テクスチャも使用することができ他の機能との共存が可能。 ビットマップオブジェクトに対してレンダリングを行うので、 これらの関数はAllegro 専用の3Dポリゴン 関数となっている。

    メリット
  • ソフトウェアレンダリングなのでハードウェアを選ばない。
  • Allegro 2D描画エンジンとの共存。2D と3D の長所を組み合わせたエフェクトも可能

  • デメリット
  • ソフトウェアレンダリングなので遅い
  • 独自仕様

  • 参考:3次元コンピュータグラフィックス
    参考:OpenGLを使いたい場合は外部ライブラリの AllegroGL を導入する。
       ( この場合、Allegro2D,3D描画機能を使っても効果はない)

    関連
    * Fixed point math
    * 3D math routines
    * Quaternion math
    半透明処理 DrawMode
    * Transp and patterned

    Allegro の 3Dポリゴン表示のサンプル「ex3d.c」の内部処理を、ex3d.cのソース と A simple 3D tutorial を参考に、図にまとめてみたもの (※完全ではない)

    頂点データについて

    頂点データを表すデータは2つの型、固定小数点数用にV3D と、浮動小数点数用に V3D_f のストラクチャが用意されている。 また、それぞれの変数型に合った ポリゴン描画関数 (浮動小数点数なら *_f )を使用しなければならない。

    これらの引数 int type については「ポリゴン レンダリングモード 定義」を参照。

    実際には、各頂点やら面の構造体を用意する必要がある。
    サンプルコードを見ると、V3Dオブジェクト以外にも頂点データを管理する為の構造体を使っている
    typedef struct V3D
    {
    fixed x, y, z; - 位置
    fixed u, v; - テクスチャマップの頂点
    int c; - 色深度
    } V3D;
    typedef struct V3D_f
    {
    float x, y, z; - 位置
    float u, v; - テクスチャマップの頂点
    int c; - 色深度
    } V3D_f;


    3Dポリゴンをビットマップオブジェクトに描画する。
    void polygon3d(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D *vtx[]);
    void polygon3d_f(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D_f *vtx[]);


    BITMAP *bmp ポリゴンを描画するビットマップオブジェクト
    int type, 描画方式(「ポリゴン レンダリングモード 定義」を参照)
    BITMAP *tex テクスチャ画像に使うビットマップオブジェクト
    int vc The vertex count parameter 頂点ストラクチャの配列が何番目かカウントする。
    V3D *vtx[] 頂点ストラクチャの配列
    テクスチャビットマップの幅と高さはそれぞれ 2のベキ乗でなければいけない。例えば 64x16ピクセルサイズ。 敷き詰められたパターンは無限平面となる。

    (x,y,z )は点の位置。 (u,v)はテクセル(テクスチャのピクセルの最小単位)の左上の座標を示す。 もしあながたがポリゴンを引いて、そこに32x32ピクセルの大きさのテクスチャを貼り込みたいと思ったなら、 まず、テクスチャの頂点s (0,0), (0,32), (32,32),(32,0)を使って反時計回りに頂点を定めると仮定する。 そうすればこのポリゴンは正しくテクスチャが貼付けられる。

    メモ:u=32 と指定した場合、実際のデータは31テクセルあることに注意してほしい。(これは v にも当てはまる) これは、テクセルの頂点左上であるためで、事実上、テクスチャの右と下の頂点が限定される。


    もしあなたが1つの辺を共有する2つのポリゴン(紙を半分に折ったような状態)を配置した場合、 2つのポリゴンに渡ってつなぎ目なしに描画するテクスチャを貼ることができる。 たとえば、一つ目のポリゴンに貼るテクスチャの頂点がそれぞれ BITMAP *tex に対応する (0,0), (0,32), (32,32) , (32,0) 二つ目のポリゴンに貼るテクスチャの頂点がそれぞれ(32,0), (32,32), (64,32), (64,0)である場合、 テクスチャは継ぎ目なしに貼付けることができる。


    三角形のポリゴン
    void triangle3d ( BITMAP *bmp, int type, BITMAP *tex, V3D *v1, *v2, *v3);
    void triangle3d_f ( BITMAP *bmp, int type, BITMAP *tex, V3D_f *v1, *v2, *v3);

    3点を指定した三角形のポリゴンを描く。

    長方形のポリゴン
    void quad3d(BITMAP *bmp, int type, BITMAP *tex, V3D *v1, *v2, *v3, *v4);
    void quad3d_f(BITMAP *bmp, int type, BITMAP *tex, V3D_f *v1, *v2, *v3, *v4);

    4点を指定した長方形のポリゴンを描く。

    3D空間のクリッピング
    int clip3d(int type, fixed min_z, fixed max_z, int vc, const V3D *vtx[], V3D *vout[], V3D *vtmp[], int out[]);
    int clip3d_f(int type, float min_z, float max_z, int vc, const V3D_f *vtx[], V3D_f *vout[], V3D_f *vtmp[], int out[]);

    指定した視体積の空間をクリップする。 この関数は、perspective projection の前に呼び出しておく必要がある。

    返値:
    数字 - 成功。

    ポリゴン レンダリングモード 定義

    サンプルコード:ex3d.c

    `type' パラメータのあるすべての3D 関数は、POLYTYPE_* 変数によりレンダリングモードを設定しなければならない。 もし、グローバル変数 cpu_capabilities = CPU_MMX フラグが立っていたら、GRGBをセットし、 truecolor *LIT ルーティンはMMXに最適に動作する。 もし、cpu_capabilities = CPU_3DNOW フラグが立っていたら、truecolor PTEX*LIT ルーティンは3DNOWを最大限に利用する。

    MMX で truecolor *LIT ルーティンを使う場合は MMXなしの環境では 副作用をもたらす。これらの ルーティンは、set_trans_blender() or set_blender_mode() などの照明関数 を使っている。 MMX 版では、RGB値を渡すのに、set_trans_blender() のみ使用でき、線形補完を自分で行わなければならない。そのため set_blender_mode() 関数は無視される。

    レンダリングモード一覧
    int type に設定するモード。OR集合「|」によって複数のモードを併用することが可能。
    polygon3d(bmp, POLYTYPE_ATEX | POLYTYPE_ZBUF, tex, vc, vtx);
    # POLYTYPE_ATEX —   アフィン変換テクスチャ ポリゴン
    # POLYTYPE_ATEX_LIT —256色カラーテーブル
    # POLYTYPE_ATEX_MASK —マスク付き(zero texture map ピクセルがスキップされる)
    # POLYTYPE_ATEX_MASK_LIT —マスク付き,256色カラーテーブル
    # POLYTYPE_ATEX_MASK_TRANS — マスク付き,半透明
    # POLYTYPE_ATEX_TRANS — 半透明

    # POLYTYPE_PTEX —perspective-correct テクスチャ ポリゴン 
    # POLYTYPE_PTEX_LIT— 256色カラーテーブル
    # POLYTYPE_PTEX_MASK — マスク付き
    # POLYTYPE_PTEX_MASK_LIT — マスク付き,256色カラーテーブル
    # POLYTYPE_PTEX_MASK_TRANS —マスク付き,半透明
    # POLYTYPE_PTEX_TRANS — 半透明

    # POLYTYPE_FLAT — drawing_mode()関数に影響を受ける。 XOR or 半透明 向き
    # POLYTYPE_GCOL — 高速だが256色モードでしか動作しない。
    # POLYTYPE_GRGB — 24ビットRGB 三重項として格納される。

    Zバッファについて

    サンプルコード:exzbuf.c
    Zバッファは通常 POLYTYPE_* モードで動作するように設計されている。

    int type OR集合「|」によって複数のモードを併用することが可能。
    polygon3d(bmp, POLYTYPE_ATEX | POLYTYPE_ZBUF, tex, vc, vtx);
    サンプルコード exzbuf.c を参考にする。

  • 通常の POLYTYPE_FLAT のレンダラ とは違い、Z バッファ はDRAW_MODE では何も効果を得られない。
  • *LIT* ルーティンは、ブレンダールーティンを通じた従来の方式で動作する。
  • Zバッファ方式は通常のルーティンより大いに遅い。


  • Zバッファを生成
    ZBUFFER *create_zbuffer(BITMAP *bmp);
    ビットマップオブジェクトから z-buffer を生成 する。 いくつもZバッファを定義することはできるが、同時に使う事ができるのは1つだけである。 Zバッファを有効にするには、call set_zbuffer()関数を呼ぶこと。


    Zバッファを有効に
    void set_zbuffer(ZBUFFER *zbuf);
    create_zbuffer()関数で作ったZバッファ機能を有効にする。


    サブZバッファ
    ZBUFFER *create_sub_zbuffer(ZBUFFER *parent, int x, int y, int width, int height);
    親ZBUFFER に内包するサイズの サブZバッファを生成する。

    返値:
    sub ZBUFFER へのポインタ - 成功
    NULL - エラー

    Zバッファ深度の初期化
    void clear_zbuffer(ZBUFFER *zbuf, float z);
    任意の z-bufferに深度の値 float z を書き込む。z = 0 であれば メモリの開放を意味する?

    もしポリゴンを10切りたい場合、あなたは、 clear_zbuffer(zbuf, 0.1).を呼び出さなければ行けない。 これはちょうどポリゴン数 z に対して、z-buff 書き込みが 1/z という関係はに相当する。


    Zバッファのメモリ開放
    void destroy_zbuffer(ZBUFFER *zbuf);
    Z-bufferのためのメモリを開放する。


    シーンギャップ
    extern float scene_gap;
    シーンの Z-ソートアルゴリズムのふるまいを制御する。 デフォルトは 100 ( Z-ソートアルゴリズム(隠面消去の一種、ポリゴンの奥行きを調べて、奥のほうから表示していく方法)

    スキャンラインレンダリングについて

    サンプルコード:exscan3d.c
    3Dシーンのためのメモリを割り当てる。
    int create_scene(int nedge, int npoly);
    シーンとは、3次元仮想空間全体のことあなたがエッジをいくつ、ポリゴンを何個 レンダリングしたいかの 概算値を設定する。 もし同じ値で再度呼び出した場合は、メモリ空間は再利用される。

    割り当てメモリの計算式を参考にしてください。
    少なくとも
    150 * (nedge + npoly) bytes
    以上必要である。
    返値:
    0 成功
    マイナス 割り当て失敗


    シーンの初期化。
    void clear_scene(BITMAP *bmp);
    シーンが描画されるビットマップを初期化してまっさらにする。 以降そのビットマップオブジェクトに対してレンダリングができるようになる。


    レンダリングリストに入れる
    int scene_polygon3d(int type, BITMAP *texture, int vc, V3D *vtx[]);
    int scene_polygon3d_f(int type, BITMAP *texture, int vc, V3D_f *vtx[]);

    レンダリングリストにポリゴンを置く。実際には 今すぐ変化が反映されるわけではない。 この関数を使う場合は clear_scene() と render_scene().の間で呼ぶ必要がある。


    シーンのレンダリング
    void render_scene();
    clear_scene() で設定したビットマップオブジェクトにレンダリングを行う。


    3Dシーンのためのメモリを開放する。
    void destroy_scene();
    使い終わったら最後に。

    Sound サウンド関連(サンプル再生)

    Allegro は WAVE サウンドデータを再生する方法を 3種類もっている。 (※ MIDI を除く)
    * Sound init routines : 通常の サンプリング再生
    * Digital sample routines :ミキシング と Voice 再生
    * Audio stream routines:波形加工 と ストリーム再生

    これらの機能を利用するには、まずサウンドモジュールを有効にする必要がある。

    サウンドモジュールを有効にする。
    int install_sound(int digi, int midi, const char *cfg_path);

    サウンドドライバに、DIGI_AUTODETECT や MIDI_AUTODETECT といったパラメータを渡してサウンドモジュールを有効にする。パラーメータは、 コンフィグファイルから読み込むことも出来るようだ。OS固有のドライバ(DIGI_CORE_AUDIO, MIDI_QUICKTIME等)については、マニュアルの the platform specific documentation for a list of the available drivers. が参考になる。
    int digi
    DIGI_NONE :サウンド機能を使用しない
    DIGI_AUTODETECT :サウンドデバイスを 自動的に検出

    int midi
    MIDI_NONE :MIDIを使用しない
    MIDI_AUTODETECT :MIDIデバイスを 自動的に検出

    const char *cfg_path
    コンフィグファイルのパス
    NULL = コンフィグファイルを使用しない場合。
    返値:   0 = 成功   -1 = 失敗 (allegro_error)
    参考:サウンド録音 * Recording routines:


    この項では、主にサンプル再生について説明する

    Allegroでは、WAVE形式とVOC形式のファイルを利用することができる。複数の音を同時に鳴らせるので、効果音とBGMに分けて使えるかもしれない。

    サンプルの準備
    SAMPLE *spl;
    サンプル(音データのこと)を用意する

    WAVファイルを読み込む
    SAMPLE *load_sample(const char *filename);
    vocフォーマットあるいは wav フォーマットのファイルを読み込む。このwavファイルは、コンパイルされたAllegroアプリケーションと同じディレクトリに置かなければならない。
    spl = load_sample("samples.wav");

    サンプルを再生する
    int play_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop);
    vol : 音量 MIN 0--------255 MAX
    pan : 音の出る方向 LEFT 0 - 127 - 255 Right
    freq: 周波数の調節 1000 = 通常再生、 2000 = 再生スピード2倍&音高UP
    loop: ループフラグを有効にすると adjust_sample().が呼び出されて loopフラグが変更されるか、stop_sample()されるまでループ再生される。
    返値 が 正の数なら 再生に成功した事を示す。
    play_sample( spl,127, 127 , 1000 , 1);
    readkey();
    play_sample( spl,127, 127 , 2000 , 1);
    readkey();
    このようにすると、同じ音楽が二重に再生され輪唱のようになる。
    もし、再生途中で何かを変化させたいならadjust_sampleを利用する。
    play_sample( spl,127, 127 , 1000 , 1);
    readkey();
    adjust_sample( spl,127, 127 , 2000 , 1);//途中から2倍速に
    readkey();
    再生中の変更
    adjust_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop);
    この関数を使えば、再生中のサンプルのパラメータを調節することができる。
    パラメータの並び方は 先ほどの play_sample関数と同じなので上のを説明を参照する。

    例えば、ループフラグ (int loop )の設定を有効/無効にしたり、サンプリング 周波数 ( int freq )を変更すると 曲の途中で再生スピードを変えたりも出来る。 音量( int vol )を フェードしたりなど。もしサンプルが再生されていない場合は、何も変更されない。

    再生の停止
    void stop_sample(const SAMPLE *spl);
    サンプル再生を停止する(リジュームは効かない)。音楽を二重に再生していた場合は
    同一のSAMPLEストラクチャに由来するものをすべて停止する。

    コードの例:
    SAMPLE *spl,*spl3;
    spl= load_sample("loop02.wav");
    spl3= load_sample("loop03.wav");

    play_sample( spl,127, 127 , 4000 , 1);
    readkey();
    adjust_sample( spl,127, 127 , 1000 , 1);
    readkey();
    play_sample( spl3,127, 127 , 500 , 1);
    readkey();
    stop_sample(spl);
    readkey();

    mixer サウンドミキシング

    ミキシングは 音を 混ぜたり加工したりして バランスよく聞こえるようにする作業のこと。

    ただしAllegro の場合はこれらの関数は、主にMixer の状態や情報を取得するために使われるようだ。 実際のミキシング処理は Digital sample 関連の関数が受け持っている。

    リサンプリングの品質を設定する
    void set_mixer_quality(int quality);
    mixerのリサンプリングの品質を設定する。この関数は allegro_init() の前に呼び出すこともできる。

    int quality の値
    0 - 16bit のバッファへ 8bit データを入れる 高速なミキシング
    1 - 本来の16bitミキシング。(16bitステレオサウンドカードが必要)
    2 - 補完された16bitミキシング 
    外部設定ファイルを使った設定方法でも同じような設定が可能らしい。 (マニュアルのConfiguration routinesの Standard config variables にある Sound`quality' config を参照。)


    リサンプリングの品質設定を取得する
    int get_mixer_quality(void);
    Configuration routines の Sound`quality' config 設定 または、set_mixer_quality() 関数 によって設定された現在の ミキシング設定を取得する。

    返値:
    0 - 16bit のバッファへ 8bit データを入れる 高速なミキシング
    1 - 本来の16bitミキシング。(16bitステレオサウンドカードが必要)
    2 - 補完された16bitミキシング 


    サンプリング周波数を取得
    int get_mixer_frequency(void);
    mixer の サンプリング周波数を返す (単位はHz)


    ビット深度を取得
    int get_mixer_bits(void);
    mixerの ビット深度、 8bit または 16 bit を返す。
    ビット深度とは、サンプリングレート1回毎に記録するデータ量を規定するものである。


    出力チャンネル数の取得
    int get_mixer_channels(void);
    mixer が出力するチャンネルの数を返す。
    返値:
    0 - mixerが有効になっていない
    1 - モノラル
    2 - ステレオ


    音声データの数を得る
    int get_mixer_voices(void);
    mixer が 割り当てた 音声データの数を返す。


    チャンネルごとのサンプル数を得る
    int get_mixer_buffer_length(void);
    mixerバッファの チャンネル毎のサンプルの数を返す。

    Digital sample - Voice control サウンド関連 音データのコントロール

    もっと高度なサウンド処理を行いたい場合。Voice control にサンプル(音)データを渡して再生やエフェクトをかける。 play_sample() 関数よりも柔軟な再生が可能。これらの関数は Audio stream 関数による再生にも対応している

    サンプル ストラクチャの概要
    typedef struct SAMPLE

    int bits; - 8 or 16
    int stereo; - sample type flag
    int freq; - sample frequency
    int priority; - 0-255 */
    unsigned long len; - length (in samples)
    unsigned long loop_start; - loop start position
    unsigned long loop_end; - loop finish position

    使用されるSAMPLEストラクチャの定数:
    int priority;
    Ranging 0-255 (default 128) ,割り振られる音の数?
     
    unsigned long loop_start;
    unsigned long loop_end;
    ループ地点とループの終了地点
    サンプルデータを 渡す
    int allocate_voice(const SAMPLE *spl);
    Voice control のために サンプルを 読み込む。
    voice number,が返れば成功 、-1を返す場合はvoice データが存在しないことを意味する。
    使い終わったあとは、 deallocate_voice() あるいは release_voice() でメモリを解放しなければならない。


    メモリを解放する
    void deallocate_voice(int voice);
    使い終わったらメモリを解放する。


    再生データの切り替え
    void reallocate_voice(int voice, const SAMPLE *spl);
    新たに他のサンプルデータに読み替えするにはこの関数を使う。
    この関数を実行する事は
    deallocate_voice(voice); voice = allocate_voice(sample); 
    したことと同じ意味になる。

    再生終了
    void release_voice(int voice);
    メモリは解放されるが音楽は流れ続ける。
    deallocate_voice()と同じような機能を持つが微妙に違う。

    再生データの情報を取得
    SAMPLE *voice_check(int voice);
    現在、Voice control されている サンプルデータをチェックする。
    NULLが返ってきた場合は サンプルデータが有効になっていない事を示す。

    再生する
    void voice_start(int voice);
    Voice control を有効にする。

    一時停止する
    void voice_stop(int voice);
    voice_start が再び呼ばれるまで 再生を一時停止する。(リジューム)

    再生位置の指定
    void voice_set_position(int voice, int position);
    サンプルの再生位置をセットする。

    再生モードを指定する
    void voice_set_playmode(int voice, int playmode);
    PLAYMODE_PLAY 一度だけ再生する。(ループフラグなしの場合はデフォルト)
    PLAYMODE_LOOP ループ再生する。 終わりに達すると、最初の位置に戻って再生する。
    PLAYMODE_FORWARD :終わりから逆再生する( もし backwardフラグがない場合はデフォルト)
    PLAYMODE_BACKWARD: 逆再生ループが可能。
                ループフラグとの併用時も開始位置を気にせずにループ可能?
    PLAYMODE_BIDIR :ループフラグと併用すると一方のループ地点に達したら再生方向を変更する。
    音量を調節する
    int voice_get_volume(int voice);
    音量を 0-255.の範囲で取得

    void voice_set_volume(int voice, int volume);
    音量を 0-255.の範囲でセット

    音データに対しエフェクトをかける
    void voice_ramp_volume(int voice, int time, int endvol);
    volume ramp処理の実行:クレッシェンド (だんだん強く) あるいは デミニュエンド(だんだん弱く)の効果を得る。 指定された時間(ミリ秒)の間に 現時点の音量から int endvol に音量を変動させる。音量のフェードを行う。

    void voice_stop_volumeramp(int voice);
    volume ramp処理の実行を中止する

    int voice_get_frequency(int voice);
    再生されている音のピッチを Hz 単位で得る。

    void voice_sweep_frequency(int voice, int time, int endfreq);
    frequency sweep処理:指定された時間(ミリ秒)の間に 現時点の周波数からint endfreq に周波数を変動させる グリッサンド効果を得る。

    void voice_stop_frequency_sweep(int voice);
    frequency sweep処理の実行を中止する。


    int voice_get_pan(int voice);
    パン:音の発せられる位置を取得する。
    0 (左から聞こえる)  127(中央から)  255 (右から聞こえる).

    void voice_set_pan(int voice, int pan);
    パン:音の発せられる位置を指定する。
    0 (左から聞こえる)  127(中央から)  255 (右から聞こえる).


    void voice_sweep_pan(int voice, int time, int endpan);
    pan sweep 処理:パン位置を変動する。

    void voice_stop_pan_sweep(int voice);
    pan sweep 処理の実行を停止する。


    void voice_set_echo(int voice, int strength, int delay);
    エコーに関する パラメータを設定する。

    void voice_set_tremolo(int voice, int rate, int depth);
    トレモロに関する パラメータを設定する。

    void voice_set_vibrato(int voice, int rate, int depth);
    ビブラートに関する パラメータを設定する。

    MIDI routines MIDIによる演奏

    (仮): MIDIファイルの演奏に関する機能を提供する。


    MIDIファイルを読み込む
    MIDI *load_midi(const char *filename);
    MIDIファイルを読み込む(SMF format 0 と format1 (MTR) 形式 に対応)
    const char *filename には ファイル名を指定する。

    返値:
    MIDI ストラクチャの ポインタを渡す。:読み込み成功 ( 以降 このMIDIストラクチャを利用する )
    NULL :失敗


    MIDIデータの開放
    void destroy_midi(MIDI *midi);
    使い終わったらMIDI ストラクチャのメモリを開放する。これはメモリリークを防ぐためにある。


    メモリをロックする(DOS のみ)
    void lock_midi(MIDI *midi);
    これは DOS のための関数。 MIDIファイルが使っているすべてのメモリをロックする。
    通常は load_midi() から呼ばれるので、これを直接呼ぶ必要はない。


    MIDIデータの演奏
    int play_midi(MIDI *midi, int loop);
    指定したMIDIストラクチャの演奏を開始する。この時、既に他に演奏されているものがあればその演奏を中止する。

    int loop パラメータ
    NULL :通常演奏

    返値:
    0 = 成功
    非0 = エラーが発生した( 要求されたデータを picth caching ドライバがロードできなかったり... 少なくとも他のだれかがもっといい picth caching ドライバを書いてくれるかもしれない...だって!?)


    ループ演奏(A→B 区間 )
    int play_looped_midi(MIDI *midi, int loop_start, int loop_end);
    ユーザーが定義した ループポイント を指定して MIDIファイルを演奏する。 演奏が loop_end に達するか、ファイルの終わり(loop_end = -1)に達した場合に、 loop_start 地点に巻き戻される。 int loop_start, int loop_end は両方とも midi_pos 変数 の形式で指定する。


    MIDIデータの演奏中止
    void stop_midi();
    この関数を呼べば MIDI演奏中であればいつでも演奏を停止する。
    calling play_midi(NULL, FALSE); と同じこと。


    MIDIデータ の演奏を一時停止
    void midi_pause();
    MIDIデータ の演奏を一時停止する。


    MIDI データの演奏を再開
    void midi_resume();
    MIDI データの演奏を再開する。


    演奏位置を検索
    int midi_seek(int target);
    現在のMIDIファイル上に 指定した演奏位置を検索する。ターゲット地点が midi_pos より前に位置すれば
    ファイルの初めから検索が開始される。そうでなければ現在の位置から検索を始める。

    返値:
    0 = 指定された 演奏位置を探し当てる事に成功。
    1 = 演奏は停止されていて。位置が negative length に セットされている。 (MIDIファイルの長さを決めたいときに利用できる。)


    曲の長さを取得
    int get_midi_length(MIDI *midi);
    MIDI 演奏の開始から終了までの長さを取得する。この関数を呼び出した後には midi_pos には negative number の beats が入り、
    midi_time には 長さを秒数 で表したデータが入る。

    この関数が呼ばれると、現在演奏されているMIDi は停止されることに注意すること。
    通常 MIDI 演奏データの長さを得る前には、 このように play_midi を呼ばなければならない。

    length = get_midi_length(my_midi);
    play_midi(my_midi);
    do {
    pos = midi_time;
    textprintf_ex(screen, font, 0, 0, c, -1, "%d:%02d / %d:%02d\n",
    pos / 60, pos % 60, length / 60, length % 60);
    rest(100);
    } while(pos < = length);
     

    MIDI出力
    void midi_out(unsigned char *data, int length);
    リアルタイムにMIDIプレイヤに、MIDIコマンドのブロック を 流す。 トリガーノート や ジングル 等 MIDIファイルに存在しているものはなんでも送信する。


    MIDIパッチのロード
    int load_midi_patches();
    強制的にMIDIドライバに 使用するためのパッチ (各MIDIチャンネルが演奏する音色番号/名称のこと)をロードする。 この関数は通常あなたは呼ぶ事はないと思われる。 なぜならAllegro は MIDIファイルが要求された時はいつでも自動的にパッチをロードするからである。 しかし、あなたは midi_out()関数を経由してプログラムチェンジメッセージを送信し、音色を変更しなければならない

    返値
    0 = 読み込みに成功した
    非0 = エラーが発生した。


    現在の演奏位置(拍)を得る
    extern volatile long midi_pos;
    定数。 MIDIファイルの現在の演奏位置(beat number)が格納されている。 そうでなければ 現在演奏が行われていないことを意味する「負の数」 が格納されている。 音楽とアニメーションを同期させたり、 MIDIファイルが演奏を終了したかどうか調べるのに有用である。

    MIDI の 音の長さの単位は
    bar number (小節) - beat number (拍) - tick number (最小単位)
    1拍 = 480 tick らしい。


    現在の演奏位置(秒数)を得る
    extern volatile long midi_time;
    定数。現在演奏されているMIDI の 位置を秒数で 表したものが格納されている。これは もしあなたが 現在の演奏位置を beat number ではなく 秒数で表示したい時に役立つ。

    ループ位置の取得
    extern long midi_loop_start;
    extern long midi_loop_end;

    定数。play_looped_midi() 関数によってセットされる ループの開始位置と終了位置を指す。
    しかし それらの位置は 常に (start < end) の関係になければならない。
    そのため、値を同時に変更したなら、それらの値をチェックする必要がある。
    ちなみに値が -1 の場合は、ファイルの終端を指定したことを意味する。


    MIDI イベントの割り込み
    extern void (*midi_msg_callback)(int msg, int byte1, int byte2);
    extern void (*midi_meta_callback)(int type, const unsigned char *data, int length);
    extern void (*midi_sysex_callback)(const unsigned char *data, int length);

    MIDI プレイヤイベントの割り込みを有効にする hook 関数。もし パラメータに NULL 以外をセットした場合、割り込みハンドラによってこの関数が呼ばれたときに、 これらの関数はそれぞれ MIDI のメタ-イベント, システム エクスクルーシブデータ等の データ ブロック を 実行する。このときすべてのデータはロックされるべきなので OS の機能を呼んではいけない。 一般的には、 これらの関数を使う時は、メインコードから 割り込みを監視するためにフラグを立てるなどして使う。



    IBKパッチの適用 (DOS のみ)
    int load_ibk(char *filename, int drums);
    Adlib によって使われる IBK パッチ定義ファイルを読み込む。 一方、General MIDI instruments の代替として打楽器などのドラムセットが設定されれば、それを読み込むことができる。 この関数を呼ぶ前後に サウンド関係の初期化を行ったり、 単純に ibk_file や ibk_drum_file をコンフィグ設定から読み込む
    ということもできるかもしれない。

    注意:Adlib や IBK パッチは DOS 用なので気をつける。この関数は、 Adlib 以外のどんなドライバにも影響を及ぼさない。
    返値:
    0 = 読み込みに成功した
    非0 = エラーが発生した

    Audio stream routines サウンド関連 ストリーム再生

    (仮):Audio stream関数は 一般的なSAMPLE ストラクチャでは収まらないような大きなサウンドデータを再生したり、 巨大な音声ファイルからデータを部分的にロードしたり、波形データを生成してなにかしたい場合に使われる。

    オーディオストリームの再生
    AUDIOSTREAM *play_audio_stream(int len, bits, stereo, freq, vol, pan);
    この関数は、新規にaudio stream とその再生を行う。 int len にはサンプルから構成されるフレーム(byte数ではない)毎に変換するデータの長さを指定する。 サンプルフレームは 1つ のモノラルデータ あるいは 2つの組から成るステレオデータである。

    この長さは通常 (そうなるとは限らないが) 約1k のサイズで 2の累乗となる?。 バッファサイズが大きいと、わずかな更新で大きな効果を得られるが、実際にはデータを再生する間に遅延が発生してしまう結果となる。

    bits パラメータは 8 または 16を指定しなければならない。
    freq パラメータは 周波数のサンプリングレートを指定する。
    vol と pan パラメータはそれぞれ 0-255の範囲で 設定する。
    stereo パラメータは ステレオなら1を、それ以外なら0を指定する。

    もしあなたが 再生中にピッチや音量、パンを調整したいなら stream->voice をパラメータとして voice_*() 関数 を利用することができる。
    サンプルデータは、通常、 unsigned format.(0 -255)が使われる。

    バッファサイズを求めるための公式は次のようになる。
    bytes = len * (bits / 8) * (stereo ? 2 : 1);
    メモリの解放
    void stop_audio_stream(AUDIOSTREAM *stream);
    audio stream に使ったメモリを解放する。

    再生中の監視
    void *get_audio_stream_buffer(AUDIOSTREAM *stream);
    あなたはこの関数を audio stream 再生している間に一定の間隔で呼ばなければならない。
    次のサンプリングデータが格納されたバッファを提供するために(もしストリーミングのためのバッファが小さければ、頻繁に呼ばれるべきである。)

    もしこの関数が NULL を返すなら、ストリームはまだ多くのデータを再生しているので、あなたは何もしなくてもよい。 そして関数が 次に再生されるバッファ位置 といった数値を返すならば あなたは適切な数のサンプル(あなたが作成した数の)をアドレスにロードすべきである。

    例えば、fread()関数を使用して次のデータをバッファに満たした後に 新しいデータが有効であるということを明確にするために free_audio_stream_buffer() 関数を呼び出しなさい。
    注意:この関数は一定の間隔で呼び出す必要があるが、タイマーハンドラから 呼び出してはいけない。

    再生位置をプログラムに告知
    void free_audio_stream_buffer(AUDIOSTREAM *stream);
    get_audio_stream_buffer() 関数がNULL 以外のアドレスを返したあとに、
    その位置に新しいサンプルデータをロードされ再生される準備ができていることを示すためにはこの関数を呼びなさい。

    Recording routines オーディオ入力による録音

    (仮): これらの関数は 音声データを録音するために用いられる。入力源は、 マイク入力, LINE入力, CD入力 の中から選択できる。 サウンド関係のツールを開発したり、音の入力を利用したりできるかもしれない。

    いくつかのサウンドカードでは、 playback mode と recording mode を切り替える時に クリック音かポッという雑音が発生する現象が確認されている。


    オーディオ入力の初期化
    int install_sound_input(int digi, int midi);
    オーディオ入力を実現するサウンド録音モジュールを初期化する。 あなたは このサブルーチンを呼ぶ前に install_sound()関数と同じ 2つのカードパラメータ DIGI_NONE や MIDI_NONE を指定するか または 推奨ハードウェアを自動的に検出する設定どして DIGI_AUTODETECT や MIDI_AUTODETECT を使わなければならない。
    int digi
    DIGI_NONE :サウンド機能を使用しない
    DIGI_AUTODETECT :サウンドデバイスを 自動的に検出

    int midi
    MIDI_NONE :MIDIを使用しない
    MIDI_AUTODETECT :MIDIデバイスを 自動的に検出
    返値:
     0が返れば初期化に成功。


    オーディオ入力の終了・開放
    void remove_sound_input();
    オーディオ入力モジュールを終了した後にメモリを解放する。 通常あなたはこの関数を呼ぶ必要はない。なぜなら remove_sound()関数や allegro_exit()関数 が実行される時にも自動的にサウンド入力関連のメモリ解放が行なわれるためです。


    サンプリング設定のチェック
    int get_sound_input_cap_bits();
    現在のオーディオ入力ドライバーが、サポートしているサンプリング形式かどうかチェックする。ビット領域の値を返す。
    返値:
    0 = オーディオ入力はサポートされていない。
    8 = 8bit オーディオ入力がサポートされている。
    16 = 16bit オーディオ入力がサポートされている。
    24 = 8bit ,16bit 両方の オーディオ入力がサポートされている。


    ステレオ対応チェック
    int get_sound_input_cap_stereo();
    現在のオーディオ入力ドライバがステレオ録音に対応しているかどうかをチェックする。


    サンプリング可能な周波数をチェック
    int get_sound_input_cap_rate(int bits, int stereo);
    指定したフォーマットの録音するための可能なサンプリング周波数の最大値を返す。 もし0が返った場合はサポートされないことを示す。


    サンプリング設定かどうかチェック
    int get_sound_input_cap_parm(int rate, int bits, int stereo);
    指定した 録音周波数,bit数, ステレオ/モノラル の組み合わせのサンプリング設定 が利用可能かどうか チェックする。

    返値:
    0 = この形式の組み合わせでは 録音は不可能である。
    1 = 録音は可能ですが、オーディオ出力は中断されるでしょう。
    2 = 他のサウンドを再生しながら同時に 録音が可能である。
    -n = 未サポートのサンプリングレートです。代替として n レートのサンプリングは動作する。


    サウンド入力源の選択
    int set_sound_input_source(int source);
    オーディオ入力方式をセットする。 マイク入力, LINE入力, CD入力 から選択することができる。

    返値:
    0 = 成功した。
    -1 = 選択したハードウェアからの入力は提供されていない。

    int source に入るパラメータは...
    SOUND_INPUT_MIC マイク
    SOUND_INPUT_LINE ライン入力
    SOUND_INPUT_CD  CD音源


    録音の開始
    int start_sound_input(int rate, int bits, int stereo);
    必要に応じて(これは現在のドライバと共にいつも起こる)オーディオ再生を中断させて、指定された形式で録音を開始する。
    返値:
    バイト数で表現されるバッファサイズ = 録音成功 ( read_sound_input も参照 )
    0 = 録音失敗


    録音の停止
    void stop_sound_input();
    オーディオ録音を停止する。 normal playback modeに 切り替える。


    オーディオバッファの取得
    int read_sound_input(void *buffer);
    最も新規に記録されたオーディオバッファを検索します。
    返値:
    0 = オーディオバッファはまだ利用可能な状態にないか、空っぽである。
    非0 = オーディオバッファにデータが貯まっている場合。
    (バッファサイズのサイズを知りたければ start_sound_input()関数の返値を参照すること)

    あなたは 録音を行なっている間、一定の間隔でこのread_sound_input関数を呼ぶ必要がある。 (1秒につき100回くらい)さもなければいくつかのデータを取りこぼすかもしれない。もし充分に呼び出すことができない場合は、 digi_recorder() 関数の callback を使って 自前のより大きなバッファに波形データを貯蔵する方法がある。

    メモ:いくつかのサウンドカードでは、 playback mode と recording mode を切り替える時に クリック音かポッという雑音が発生することが確認されている。 波形データは、左右 のサンプルから構成されるステレオデータが unsigned format で格納されている。


    サンプリングデータが利用可能な事を知らせる(DOSのみ)
    extern void (*digi_recorder)();
    この関数をセットすると、 read_sound_input()関数を呼び出した時にはいつでもサウンドドライバによって  新しいサンプリングバッファが利用できることを知らせる。 永続的なバッファにデータがコピーされる。この関数は割り込みコンテキストによって実行されるので非常に高速で、 アクセスされる すべてのメモリとコードはロックされるため ディスクファイルやシステム処理をすることができない。 この関数は、現在 DOS 上でしか動作しない。


    MIDIデータが利用可能な事を知らせる(WIN,DOSのみ)
    extern void (*midi_recorder)(unsigned char data);
    もしこの関数をセットすると、 MIDI入力ドライバによって新しいMIDIデータが利用できることを知らせる。 この関数は割り込みコンテキストで実行されるため 高速である。またその間 コードとデータはロックされる。 この関数は、現在 DOS とWindows 上でしか動作しない。


    File and compression routines ファイル操作と圧縮

    (仮)
    Allegroのファイル操作関数は大きく 3つに分類できます。PackFile と DATAFILE はAllegro固有ものです。

  • ディレクトリパス 操作系( 各OSのシステムに対応。主にパス置換、情報取得、検索機能。※)
  • PackFile形式の出入力(LZH圧縮)
  • DATAFILE形式のアーカイブファイルの出入力。DATファイル関連

    ※今の所 Allegroでは、プレーンテキストを読込むための汎用的なAPIは用意されていません。必要な人は自作して下さい。(一応テキストファイル読み込みとして、 コンフィグファイルの読み込みはサポートされてはいます。)

    MacOSXでは、バンドル形式とそうでない場合で、ファイルの置き位置が違ってくることがあります。注意して下さい。


    この章では、ディレクトリパス 操作系 と、PackFile形式の出入力の関数を紹介します。

    ディレクトリパス 操作系

    実行プログラムのあるディレクトリ名を取得する
    void get_executable_name(char *buf, int size);
    現在実行中のAllegro実行アプリケーション本体のある場所をフルパスで取得します。
    「絶対パス名+実行ファイル名」 が char *buf に入ります。size は割り当てるメモリの量。
    //パス名を格納
    char name[200];

    get_executable_name(name, sizeof(name));
    allegro_message("Running `%s'\n", name);

    結果:
    c://usrname/project/program.exe
    user/project/build/program.app

    ファイル名を差し替える
    char *replace_filename(char *dest, const char *path, const char *filename, int size);
    「絶対パス名+ファイル名」のファイル名の部分を差し替えます。 size バイトぶんが dest にコピーされます。
    どんな使い方をするかは次の例を見てください。
    //パス名を格納する変数
    char name[200];
    ...
    get_executable_name(name, sizeof(name));// 実行ファイルのある場所を フルパスで取得
    replace_filename(name, name, "sound.dat", sizeof(name));// sound.dat に差し替え
    相対パス指定ではファイルを読み込まない場合もあります。replace_filename関数と get_executable_name関数を使って絶対パス指定でファイルを読み込ませることができます。
    注意:この方法を使った場合、日本語が混じったファイルパスに置くと ダメみたいです。この問題が改善されるまでは気を付けてください。
    char name[200];
    get_executable_name(name, sizeof(name)); //例えば、 user/desktop/tetris/program.app が name に代入されます。
    allegro_message("Running `%s'\n", name);

    // ファイル読込み( MapLoad と TextLoad 関数はユーザが用意した関数で、
    // C標準ライブラリの fopen 関数を使ってテキストファイルを読み込むというものです。
    // 関数を fp= fopen( name , "r" ); というように使っています。 )


    // ファイル名を差し替える replace_filename(name, name,"map.txt", sizeof(name)); MapLoad(name);// name に格納されている絶対パス名 user/desktop/tetris/map.txt で読み込みます

    replace_filename(name, name,"story.txt", sizeof(name));
    TextLoad(name);// name に格納されている絶対パス名 user/desktop/tetris/story.txt で読み込みます。
    その他のファイルパス操作系関数

    ファイルが存在するか調べる
    int file_exists(const char *filename, int attrib, int *aret);
    与えられたファイル名と属性(この章の最初を見ること)が一致するファイルが存在するかどうかを調べます。
    また、int *aret が NULL以外が指定された場合には、一致したファイルにその属性を付加します。
    例:
    /* ファイルが存在するか調べる */
    if (file_exists("franken.dat", 0, NULL))
    allegro_message("It is alive!\n");
    返値:
    0以外 なら ファイルが存在することを表します。
    0 なら、ファイルが見つからないか、指定した属性が一致しないかです。

    ファイルが存在するか調べる(短縮形)
    int exists(const char *filename);
    file_exists()関数の短縮バージョン。アーカイブや読み取り専用のビットがセットされていても、普通のファイルとしてチェックします。 しかし、ディレクトリやシステムファイル等は隠されません。
    返値:
    0以外 - ファイルが存在する
    0 - ファイルが存在しない

    ファイルサイズを byte数で返す。
    long file_size(const char *filename);
    指定した名前のファイルの容量を byte数で返します。もし、ファイルが存在しない場合は 返値には0が返り、Allegroシステムのエラー変数errnoに エラーコードが記録されます。

    ファイルの変更日時 を返す。
    time_t file_time(const char *filename);
      ファイルの変更日時を、1970年1月1日の00:00:00 世界標準時刻 からカウントされた秒数で返します。 ファイルが存在しなかったりエラーが発生した場合 0を返し、Allegroのエラー変数に エラーコードを記録します。

    末尾の拡張子を置き換えて、「ファイル名+拡張子」 形式の名前にする。
    char *replace_extension(char *dest, const char *filename, const char *ext, int size);
      新しい拡張子を末尾に追加して、指定された「ファイル名+拡張子」 形式の名前に置き換えます。char *dest バッファに、最大int size byte 記録します。 もし、ファイルに拡張子が付いていない場合は char *ext に指定された拡張子名が補完されます。 この関数ではAllegroの内部処理のおかげで 、入力 と 結果 を同じ変数で済ませる事ができます。
    例:
    replace_extension(buf, "C:\\game\\prog.exe", "dat", sizeof(buf));

    パスからファイル名の部分を返す。
    char *get_filename(const char *path);
      指定したファイルパスから、ファイル名の部分を返します。DOSやWindows環境下では `\(バックスラッシュ)' と `/(スラッシュ)' がディレクトリの区切りとして認識されます。 ただし、`/(スラッシュ)'は、他のプラットフォームでも区切りとして確認されることがあります。
    例:
    get_executable_name(name, sizeof(name));
    allegro_message("Running `%s'\n", get_filename(name));
    注意:Allegroは、検証中にはどんな出入力操作も行いません。なぜなら、ファイル名が含まれないディレクトリパス「/a/path/like/this/」であれば関数はNULL文字を返しますが。 しかし「/a/path/like/this」というディレクトリパスの場合、これがディレクトリとして正しいものであっても、ポインタとして「this」が返されるからです。
    返値:
    ディレクトリパスのファイル名の開始位置部分へのポインタ 、あるいは、有効なファイルが見つからない場合はディレクトリパスの開始位置へのポインタ(例えばUnix環境下でバックスラッシュを用いている場合)

    # find_allegro_resource — ファイルを複数の場所で検索する機能を提供する
    # append_filename — ファイル名とパスを連結する
    # canonicalize_filename — どんなファイル名も 文字上の正規化された形式(canonical form)に変更する。
    # fix_filename_case —ファイル名を大文字に変更 (DOSのみ)
    # fix_filename_slashes — すべてのディレクトリ区切りを変更する。 (DOSのみ)

    # is_relative_filename — ファイル名が相対パスなら TRUE を返す。  
    # get_extension — ファイル名の拡張子 を返す。  
    # put_backslash — パスの最後に、セパレータ(バックスラッシュ)を追加する。
    # set_allegro_resource_path — Allegroリソースを検索する特殊パスを設定する。
    # make_absolute_filename — 相対パスから絶対パス表記へ変換する。
    # make_relative_filename — 絶対パスやファイル名から相対パス表記へ変換を試みる。

    # al_findclose — 既にal_findfirst()関数によって検索されたものを閉じる。 
    # al_findfirst — ファイル検索のためのローレベル(細かい指定ができる)関数。
    # al_findnext — al_findfirst()関数による検索で次のファイルを検索する。
    # delete_file — ディスクからファイルを取り除く。
    # for_each_file_ex — 互いのファイルがワイルドカードにマッチした場合に callback()関数を実行する。  


    圧縮ファイル:AllegroのPackfile出入力について

    AllegroのPackfileルーティンは奥村晴彦氏による LZSS compressorアルゴリズムに基づいていて、高速バッファ I/Oシステムを実行して圧縮ファイルの読み書きを行う。これはZIPやLHAのような圧縮専門プログラムの圧縮率には劣るが解凍速度は非常に早く、また必要なメモリが少なくて済む。

    圧縮ファイルは常に、32bitの変数F_PACK_MAGICから始まり、F_NOPACK_MAGIC のファイルを自動検出する。 次に述べるFA _ * フラグ、 FA_RDONLY 、FA_HIDDEN 、FA_SYSTEM 、FA_LABEL 、FA_DIREC 、FA_ARCH が機能することが保証される。しかし、FA_SYSTEM, FA_LABEL, FA_ARCH といったフラグは DOS/Windowsだけの変数なのでこれらのフラグを使えば他のプラットホームでコンパイルすることはできなくなる。

    ' attrib ' パラメータ一覧
    ( パラメータに指定するフラグは '|' ( OR 演算子)で繋げることによっていくつも併用できる。)
    FA_RDONLY :DOS系の「読み取り専用」 やUnix系システムの 「書き込み不可」のようなフラグをディレクトリ・エントリに対して行う。
    FA_HIDDEN :DOS系の「.(ドット)」(Unix系の「.」,「..」を除く)で始まるファイル名を隠すフラグである。
    FA_DIREC : ディレクトリの代用となるフラグ。
    0xFF : すべて
    ' attrib ' パラメータが関数に渡されたとき、マッチしたファイルがそこに含まれているとフラグが立つ。すなわち一致するべきファイルの属性は、指定したフラグを含むかもしれないが、しかし明記していないフラグを含んではいけない。従って、' FA_DIREC | FA_RDONLY ' を渡したら、正常なファイルと、ディレクトリが「読み取り専用」でなければならない。しかし、隠しファイルではないファイルとディレクトリである。 もし、'FA_ARCH'フラグを渡した場合は、アーカイブ化されたファイルとされていないファイルが同時に含まれることになる。
    ' attrib ' パラメータを使用する関数の一例:
    int file_exists(const char *filename, int attrib, int *aret);
    int for_each_file_ex(const char *name, int in_attrib, int out_attrib, int (*callback)(const char *filename, int attrib, void *param), void *param);
    int al_findfirst(const char *pattern, struct al_ffblk *info, int attrib);

    なお、これらの関数を使わずに、C標準ライブラリのファイル出入力関数を使って、
    ファイルを読み込むことも可能。

    関連:
    * Datafile routines
    サンプルコード: expackf.c

    PackFile ファイル出入力

    主にPACKFILE ストラクチャが対象
  • pack_fopen — 各モードによるファイル読込み.
  • pack_fopen_chunk —ファイルを sub-chunkとして開く。
  • pack_fopen_vtable — ファイル構造を標準関数ではなくvtableの関数を使って開く。

  • pack_fclose — pack_fopen()関数で開いたファイルを閉じる
  • pack_fclose_chunk — 開いたsub-chunk を閉じる

    ファイル読み込み
    PACKFILE *pack_fopen(const char *filename, const char *mode);

    指定したモードに従ってファイルを読み込む。
    ファイル出入力フラグ:
    'r' - ファイル読込みモード
    'w' - ファイル書込みモード、存在するデータを上書きする。
    'p' - 「Packed Mode」でファイルを読込む。データを書き込む時はそれが 圧縮され、自動的にファイルが開いている間は解凍されている。
    このモードで 作成されたファイルは、このモードで読込まれない場合はゴミデータが生成される。
    '!' - 通常モード(非圧縮モード)で書き込みを行なう。しかし ファイルの先頭に value F_NOPACK_MAGIC を追加した場合、
    圧縮モードで書き込んで Allegroはそのデータが解凍する必要はないか自動的に検出作業を行う。
    これらの代わりに、
    F_READ
    F_WRITE
    F_READ_PACKED
    F_WRITE_PACKED
    F_WRITE_NOPACK
    を指定することもできる。

    返値:
    PACKFILEストラクチャへのポインタ- 成功
    NULL - 失敗

    魔法のファイルネームについて。
    "#" - #マーカーを使って「ファイル名.dat#パスまたはオブジェクトネーム」という形式のファイルパスを渡すと
    exdat 関数によって保存されたDAT形式の任意のデータを読み出す事ができる。DATファイルの階層指定にも対応している。
    ' filename.dat#object_name '
    ' filename.dat#graphics/level1/mapdata '
    また、もしそれから独立したオブジェクトを読み込もうと考えているなら、
    オブジェクトごとに圧縮されるか、無圧縮のDAT形式のDatafileで保存しておきなさい。

    (さもなければ、それが読み込まれた時に余分なデータを探すことになり?)
    最終的に、特殊なAllegro-object types がDATからインポートしたファイルと同じ形式ではないと分かる。


    Grabber から サンプリング音源 や ビットマップ関数のようなデータをインポートした時、それらは特殊なAllegro-object 形式に変換される。しかし「#」マーカー
    ファイル構文が含まれていると、バイナリデータとしてオブジェクトを読み込む。これは 例えば、あなたがDatafileから画像を読み込む時に load_pcx関数を使いたいと思ったなら、BITMAPオブジェクトよりもバイナリブロックとしてインポートすべきであることを意味する。


    vtableによるファイル読込み
    PACKFILE *pack_fopen_vtable(const PACKFILE_VTABLE *vtable, void *userdata);
    標準関数の代わりに、vtable で指定された機能を利用する新しい PACKFILE ストラクチャを作成する。 vtable と usedata は、PACKFILEが存在する限りは残さなければならない。 この時、pack_fopen_chunk()関数 を利用して、packfileの先頭に戻ってデータの塊(chunk)を開くことはできない。 また、pack_fopen_vtable()関数を使って開いたpackfileにpackfile_password()関数を適用して効果をもたらさない。

    返値:
    PACKFILEストラクチャへのポインタ- 成功
    0 - 失敗


    ファイルを閉じる
    int pack_fclose(PACKFILE *f);
    既に pack_fopen()関数によって読み込まれた PACKFILE *f ストリームを閉じる。これによりファイルが閉じたれたあとに、ファイル関連の操作をするとエラー(クラッシュ等)が発生したりするので注意する。

    返値:
    0 - 成功
    errno. - 失敗した場合はエラー番号として内容が返る
    この関数は、ファイル書き込み時のみ、failを返すことができる。(ファイル読み込み時には必ず0が返るため)


    ファイル内検索
    int pack_fseek(PACKFILE *f, int offset);
    PACKFILE *f のファイル出入力位置を移動させる。 C標準のfseek()関数とは異なり、この関数は現在位置より前方しか対応しないので、オフセット int offset に負の値を指定することはできない。

    返値:
    0 - 成功
    マイナス - エラー

    PackFile データ出入力

    PACKFILE ストラクチャ、
    LZSS_PACK_DATA , LZSS_UNPACK_DATA ストラクチャが対象。
  • int lzss_read
  • int lzss_write

    LZSS を使用してデータを読む
    int lzss_read(PACKFILE *file, LZSS_UNPACK_DATA *dat, int s, unsigned char *buf);
    データを dat から bufへ解凍します。ファイルの s バイトぶんまたは EOFまで達したデータが解凍されます。
    返値:
    バッファ buf へ追加されるbyte数を返します。

    LZSS を使用してデータを書き込む
    int lzss_write(PACKFILE *file, LZSS_PACK_DATA *dat, int size, unsigned char *buf, int last);
    buf から、データを size byteぶん圧縮します。圧縮情報は dat に含まれます。圧縮されたバイトデータは、 file に保存されます。
    返値:
    0 - 成功
    EOF - エラーが発生した

    Pack File ストラクチャ

    圧縮、解凍データに関するストラクチャ。

    LZSS_PACK_DATA
  • create_lzss_pack_data — 作成
  • free_lzss_pack_data — 解放

    LZSS_UNPACK_DATA
  • create_lzss_unpack_data —作成
  • free_lzss_unpack_data — 解放

    圧縮のためのLZSS_PACK_DATAストラクチャを作成する。
    LZSS_PACK_DATA *create_lzss_pack_data(void);
    圧縮のためのLZSS_PACK_DATAストラクチャを作成する。これは、Packfile で LZSS圧縮に使うためのものです。
    返値:
    ストラクチャへのポインタ - ストラクチャが正常に作成された
    NULL - 失敗した。
     
    作成されたLZSS_PACK_DATAストラクチャを解放する。
    void free_lzss_pack_data(LZSS_PACK_DATA *dat);
    create_lzss_pack_data()関数によって作成されたLZSS_PACK_DATAストラクチャを解放します。


    解凍のためのLZSS_UNPACK_DATAストラクチャを作成する。
    LZSS_UNPACK_DATA *create_lzss_unpack_data(void);
    解凍のためのLZSS_UNPACK_DATAストラクチャを作成する。これは、Packfile で LZSS解凍に使うためのものです。
    返値:
    ストラクチャへのポインタ - ストラクチャが正常に作成された
    NULL - 失敗した。
     
    作成されたLZSS_UNPACK_DATAトラクチャを解放する。
    void free_lzss_unpack_data(LZSS_UNPACK_DATA *dat);
    create_lzss_unpack_data()関数によって作成されたLZSS_UNPACK_DATAストラクチャを解放します。



    # pack_feof — 非0が返った場合、ファイルの終端(eof)に達した事を意味する。
    # pack_ferror — ファイルに対する出入力を行う時に発生したエラーをユーザに教える。 


    # pack_fgets — ファイルに対する出入力(行単位で読む)
    # pack_fputs — ファイルに対する出入力(文字列を書込む)
    # pack_fread — ファイルに対する出入力( n bytes 読込む)
    # pack_fseek — ファイルに対する出入力(ファイル位置を探し出す)
    # pack_fwrite —ファイルに対する出入力( n bytes 書込む)

    # pack_getc — ファイルに対する出入力(次の文字を得る)
    # pack_putc — ファイルに対する出入力( 文字を書き込む)
    # pack_igetl — pack_getc()関数のように, 32-bit Intel byte 形式の words データを得る
    # pack_igetw — pack_getc()関数のように, 16-bit Intel byte 形式の words データを得る
    # pack_iputl — pack_putc()関数のように, 32-bit Intel byte 形式の words データを書込む
    # pack_iputw — pack_putc()関数のように, 16-bit Intel byte 形式の words データを書込む
    # pack_mgetl — pack_getc()関数のように, 32-bit Motorola byte 形式の words データを得る
    # pack_mgetw — pack_getc()関数のように, 16-bit Motorola byte 形式の words データを得る
    # pack_mputl — pack_putc()関数のように, 32-bit Motorola byte 形式の words データを書き込む
    # pack_mputw — pack_putc()関数のように, 16-bit Motorola byte 形式の words データを書き込む.

    # packfile_password — packfileに暗号化されたパスワードを設定する。 

  • Grabber& DAT tools Grabber と DAT

    Allegro には、複数のファイルを1つのファイルにまとめて アーカイブする機能があります。(Packfile とは別の機能です。)

    このAllegroのアーカイブ形式 Datafile を作成、編集するために GUIインターフェースを持つ Grabber 、そしてCUIインターフェースを持つ DAT という ツールが用意されています。

    これらのツールは Allegro を解凍したディレクトリ内の tool というディレクトリを探せば見つかる。

    Grabberはダブルクリックするか、コマンドラインで実行するとフルスクリーンモードで立ち上がります。 それに対して、DAT は、コマンドラインから、引数を渡して実行します。
    以下は、CUIインターフェースを持つ DATツール についてのメモです。

    DAT ツールは '-a' オプションを加える事で、アーカイブ機能を利用することができる。
    この アーカイブモード を利用して、複数のリソースをひとつの .dat ファイルに固めることができる。
    dat myfile.dat -a alien.pcx scream.wav
    とコマンドを打てば、
    alien.pcx と scream.wav が myfile.dat というアーカイブに追加される

    dat ファイルにアーカイブされるデータには オブジェクトのタイプと、オブジェクト名、 プロパティ、データ自身 の情報が格納される。 このうち、引数に使われた ファイル名と 拡張子 によって オブジェクトのタイプとオブジェクト名が自動的に反映される。

    最初の例では alien.pcx というファイルは オブジェクトのタイプ .pcx →「bitmap」、 オブジェクト名は 「alien」 というデータとしてアーカイブ内に格納される。

    しかし 拡張子によっては、ビットマップあるいはスプライト 等様々な用途に用いられるものも存在する。 その場合は、'-t' フラグを使って そのデータが属するオプジェクトのタイプを 指定してやるとよい。

    特定のオブジェクト のタイプを指定するには、'-t' フラグを使う。
    dat myfile.dat -a alien.pcx -t RLE
    pcx ファイルですが、 オプジェクト のタイプは RLE スプライトとして格納される。

    ほかのオプションの説明。
    '-c0' -無圧縮
    '-c1' - ファイル個別に圧縮
    '-c2' - アーカイブ全体を圧縮
    '-d ' アーカイブの中から 指定したオブジェクト名のデータを削除する。
    '-e ' アーカイブの中から指定したオブジェクト名のデータを取り出す。
    名前にはワイルドカードが使える。-o オプションと一緒に使えば、
    データを、ディレクトリやファイルに名前をつけて出力することができる。
    '-h outputfile.h' アーカイブの中に格納されているデータの索引をヘッダファイルとして、出力する。
    このファイルは データファイルを読み込む際に include することもできるらしい。

    '-007 password' パスワードをセットする。

    ' PROP=value' プロパティ と値の組み合わせで、アーカイブ内のプロパティの値を変更できる。
    my_object というオブジェクトの名前を what_a_silly_name という名前に変更する場合は
    dat myfile.dat my_object NAME=what_a_silly_name
    となる。

    DATAFILE データファイル・アーカイブ

    Allegro には、複数のファイルを1つのファイルにまとめて アーカイブする機能があります。(Packfile とは別の機能です。) このアーカイブは、DATAFILE形式と呼ばれ拡張子は.dat と定められています。 このアーカイブ は、Grabber や DAT と呼ばれるツール(Allegro解凍ディレクトリ内に用意されています。)を使って作成します。

    dat ファイルは オブジェクトのタイプと、名前、と プロパティと、データそのもの に分かれていて、 作成したアーカイブ内のデータへは、Allegro プログラムからAPI を通じてアクセスすることができます。

    DATAFILEの読み込み
    DATAFILE *load_datafile(const char *filename);
    データファイルの読み込み
    DATAFILE *load_datafile_callback(const char *filename, void (*callback)(DATAFILE *d));
    コールバック(ある関数が呼ばれた場合にそれを実行する仕組み)を使った読み込み。

    メモリの解放
    void unload_datafile(DATAFILE *dat);
    メモリリークを回避する為に、使い終わったらメモリを解放する。
    *dat に関連する すべてのデータが解放される。

    アーカイブからデータをロード
    DATAFILE *load_datafile_object(const char *filename, const char *objectname);
    DATAFILEアーカイブから、特定のオブジェクト名をもつデータをロードする。
    注意すべき点は、アーカイブファイル全体を圧縮していた場合は、読み込み処理は遅くなること。

    読み込んだ特定のデータのメモリを解放
    void unload_datafile_object(DATAFILE *dat);
    データファイルから読み込んだ、特定のオブジェクト名のデータのメモリを解放する。

    アーカイブ内を検索
    DATAFILE *find_datafile_object(const DATAFILE *dat, const char *objectname);
    すでに読み込んだデータファイルから、特定のオブジェクト名のものをポインタで返す。もしNULLを返した場合は、見つからなかったことを意味する。
    この関数は、 '/' と '#' で区切られた データファイルパスの入れ子を認識する。


    オブジェクトのプロパティを取得
    const char *get_datafile_property(const DATAFILE *dat, int type);
    データファイルから、指定したタイプのデータのプロパティを取得する。
    int type は DAT_ID macro によって作成されたものを用いる。

    オブジェクトのタイプを取得
    Macro DAT_ID(a, b, c, d);
     4文字で指定されたデータファイル内のオブジェクトのタイプを返す。
    例えば、下のように使う。
    get_datafile_property(datob, DAT_ID('N','A','M','E'));

    データファイルの使い方
    Grabber によってアーカイブするか、あるいはコマンドラインからDAT を使って
    dat myfile.dat -a COOL_PICTURE.bmp
    のように アーカイブを作成した場合にAllegro からそれを利用する場合。
    DATAFILE *dat;
    BITMAP *bmp;

    dat = load_datafile("myfile.dat");//アーカイブを読む
    if (!dat) { return;}//エラー

    // *dat の中に格納されている「 BITMAP」タイプの
    // 「COOL_PICTURE」というオブジェクト名 の データを読む。
    bmp = (BITMAP *)dat[COOL_PICTURE].dat;

    項目がネストされている場合は、親ノード名の DATAFILEオブジェクトを
    作って、そこから同じように指定するらしい。
    DATAFILE *dat = load_datafile("whatever.dat");//
    DATAFILE *nested = (DATAFILE *)dat[内包ファイル名].dat;
    FONT *thefont = (FONT *)nested[NESTED_FILE_A_FONT].dat;

    fixed math 固定小数点数

    Allegroはまた、固定小数点 を持つ 型 の 数を扱う関数を提供する。 これらは、小数点切り上げや、他の型変数との変換、四則演算、三角関数 等の機能を提供する。

    固定小数点数とは、小数点位置を固定し、「整数部」と「小数部」と、内部データが2つに分かれているものを指す。 (「fixed」type は 符号付き 32-bit 整数 として、整数部小数部を、それぞれword型(16bit)として格納されている。 整数部は上位word , 小数部分は下位word の順に格納されている)

    この型 表現できる数は -32768 から 32767 の範囲で、小数位は下4〜5桁までの精度 の 数を表現することができるとのこと。 固定小数点数は、計算の精度よりも、高速な計算 が得意という特徴を持っている。


    参考文献:
  • 固定小数点数について
  • 浮動小数点数について
  • 端数処理について(四捨五入, 丸め 等)


  • 整数→固定小数点数
    fixed itofix(int x);
    整数( int )型の変数 を 固定小数点( fixed )型に 変換する。
    これは、x <<16 したのと同じことを意味する。

    数値だけ並べた場合に手っ取り早く 固定小数点型の数に変換する場合に
    は、左に16ビットシフトした x <<16 という形で用いられることがある。

      整数部    小数部
    | 16ビット | 16ビット |
                  32
         32←←←←←←←←← 左16ビットシフト
    例えばこのように書かれていた場合
    /* 立方体の頂点座標。 行列関連の関数は 固定小数点型の値を扱う */
    { -32 << 16, -32 << 16, -32 << 16 },
    { -32 << 16, 32 << 16, -32 << 16 },
    { 32 << 16, 32 << 16, -32 << 16 },
    は、次のようなことをしているのと同じ。
    { fixed itofix(-32) , fixed itofix(-32) , fixed itofix(-32 ) },
    { fixed itofix( -32) , fixed itofix( 32) , fixed itofix(-32) },
    { fixed itofix( 32 ), fixed itofix(32) , fixed itofix(-32) },
    int型の数値だとこのようになる
    { -32 , -32 , -32 },
    { -32 , 32 , -32 },
    { 32 , 32 , -32 },
    固定小数点数→整数
    int fixtoi(fixed x);
    固定小数点(fixed )型の変数 を 整数( int )型に変換する。
    丸め が要求される。


    床関数
    int fixfloor(fixed x);
    fixed x の値 未満で、最大の整数(int)値を返す。

    xが、正の数の場合、小数点以下の切り捨てが行われる。
    例: fixfloor( 1. 3 ); の結果は 、 1 となる。


    天井関数
    int fixceil(fixed x);
    fixed x の値 以上で、最小の整数(int)値を返す。

    xが、正の数の場合、小数点以下が 0 以外の場合、小数点 切り上げが行われる。
    fixfloor( 1. 3 ); の結果は 、 2 となる。


    浮動小数点→ 固定小数点
    fixed ftofix(double x);
    浮動小数点( idouble )型の変数 を 固定小数点( fixed )型に 変換する。


    固定小数点→ 浮動小数点
    double fixtof(fixed x);
    固定小数点( fixed )型の変数 を浮動小数点( idouble )型に 変換する。


    演算について

    通常 整数は + -/ * 演算子を使って加算、減算、乗算や除算を行うことができる。ただし固定小数点数の場合には問題がでてくる。 例えば、32768 までしか入らない型 の変数に、演算結果として上限を超える 17764680 という数字が入ってしまうと、桁があふれて正確な 計算ができなくなってしまう。 このように、型が格納できる桁数を越えた値をとることを「オーバーフロー(桁あふれ)」という。

    Allegro では オーバーフローから プログラムを保護するための監視機能がついた 四則演算関数が用意されていて オーバーフローが発生した場合には エラーNo.を報告し、格納できる値の最大値がセットされるとのこと。 もし、あなたがオーバーフローが起きたか知りたい場合は これらの関数を呼ぶ前にエラー変数を初期化 「 errno = 0 」 すること。

    これらの関数は、演算子を使った計算に比べて処理速度が劣るが、オーバーフロー対策の手間を考えると効率が良い。

    固定小数点数同士の乗算
    fixed fixmul(fixed x, fixed y);

    固定小数点数同士の除算
    fixed fixdiv(fixed x, fixed y);

    固定小数点数同士の加算
    fixed fixadd(fixed x, fixed y);

    固定小数点数同士の減算
    fixed fixsub(fixed x, fixed y);


    Fixed point trig

      平方根, sin , cos,tan , inverse sin , inverse cos 関数 は テーブル参照によって値が求まるので高速である。そのため値の精度はそれなりのものしか期待できない。 一方 inverse tan は tan テーブルを参照しているため、他の関数より処理が遅いとのこと。

    ラジアン(Radian) と 度数(Digree)。
    角度を表現する方法には、主に二つの単位系が知られている。 ラジアンは、 180° = π と定めて扱う角度を定義する。 360° ならラジアンは 2π, 90°なら ラジアンは 1/2π となる。


    参考文献:
  • ラジアン
  • 三角関数
  • 度数法とラジアン法の関係


  • 単位変換

    角度単位の変換 digree → radian
    extern const fixed fixtorad_r;
    この定数は、度 から、ラジアン形式に変換する。
    fixtorad_r = π/180

    y が 角度を表す 度数法の 角度 の場合。 y を この定数で乗算するとラジアンに変換できる。
    x = fixmul(y, fixtorad_r); により
    x 値 には ラジアン値として表される角度が返ってくる。


    角度単位の変換 radian → digree
    extern const fixed radtofix_r;
    この定数は、ラジアン形式 から 度 に変換する。
    radtofix_r = 180/π

    xが 角度を表すラジアン値の場合。 x を この定数で乗算すると 度に 変換できる。
    y = fixmul(x, radtofix_r); により
    y値 には 固定小数点値として表される角度が返ってくる。


    三角関数

    三角関数: 角度(ラジアン)→ 二辺の比率 を求める
    fixed fixsin(fixed r);
    サイン (sin) … 正弦 テーブルを参照する。

    fixed fixcos(fixed r);
    コサイン(cos) … 余弦 テーブルを参照する。

    fixed fixtan(fixed r);
    タンジェント(tan) … 正接 テーブルを参照する。


    逆三角関数:二辺の比率 →角度(ラジアン) を求める。
    fixed fixasin(fixed x);
    アークサイン (asin) … 逆正弦 テーブルを参照する。

    fixed fixacos(fixed x);
    アークコサイン(acos) … 逆余弦 テーブルを参照する。

    fixed fixatan(fixed x);
    アークタンジェント(atan) … 逆正接 テーブルを参照する。

    fixed fixatan2(fixed y, fixed x);
    アークタンジェント … 逆正接 を求める。libc の atan2() 関数と同じ処理。


    平方根
    fixed fixsqrt(fixed x);
    ルート … 平方根を求める。


    斜辺を求める
    fixed fixhypot(fixed x, fixed y);
    直角三角形の斜辺( hypotenuse )の長さを求める。 この関数は、三平方の定理に基づき √ (x^2 + y^2) で計算された結果を返す。

    1^2 = sin^2θ + cos^2 θ


    FIX Class !?
    C++ を利用する場合の注意点。
    あなたは、 fix class と fixed typedef を併用してはいけない。 x が class fix のオブジェクトである場合、fixsqrt(x) を呼ぶのは間違いで、 オーバーロードされた sqrt(x) または x.sqrt() のように呼ばなければならない。 らしい。

    3D math routines ベクトル・行列

    Allegro は 3次元空間を表現するための便利な ベクトル、行列 や 補助関数を提供する。 関連
    * Fixed point math
    * 3D math routines
    * Quaternion math
    * Polygon rendering

    3D空間を表わす例:(実際にはもっと設定が必要)
       /* はじめに 3Dオブジェクトを投影する ビューポート を設定する。 */
       set_projection_viewport (0, 0, SCREEN_W, SCREEN_H);
      
    	/*  次に、視点位置と方向を決めて。カメラ行列*mを作る。 
    	* Allegro は右手座標系である。この例では、奥行はz軸に負の向きに
    	 *  上方向は y軸方向に正の向きを指している。 
    	*/ 
    	 
       get_camera_matrix_f (
           &m,  /*  カメラの行列 */
          0, 0, 0,  /*  視点の位置 この例では ( 0, 0,0 )に位置している . */
          0, 0, -1, /* 視点の奥行方向を決めるベクトル、z軸に負の向き*/
          0, 1, 0,  /* 上方向を決めるベクトル。 */
          32,       /* 視野角を256度形式で指定、これは 360度形式では 45° */
          (float)SCREEN_W / (float)SCREEN_H)); /* アスペクト比*/
      
    	/* カメラ行列に対して、変換行列を適用する。 
    	*   x, y,z パラメータそれぞれ、 100, 200,-300 を適用する。
    	*  点に対し、相対的に回転処理を行うことを意味する。
    	*   この 変換は、アスペクト比や倍率に従ってカメラに投影される、
    	* また、ビューポートへ投影されるための画面の更新の準備がなされる。
    	*/
       apply_matrix_f (&m, 100, 200, -300, &x, &y, &z);
      
       /* 最後に、 点は、カメラによって、スクリーンに投影される。*/
       persp_project_f (cx, cy, cz, &sx, &sy);
      


    カメラ(視点)を設置
    void get_camera_matrix(MATRIX *m, fixed x, y, z, xfront, yfront, zfront, fixed xup, yup, zup, fov, aspect);
    void get_camera_matrix_f(MATRIX_f *m, float x, y, z, xfront, yfront, zfront, float xup, yup, zup, fov, aspect);
    透視投影変換によって、 3D空間のオブジェクトを投影するカメラを構築する。 x,y,z パラメータ にはカメラの位置、 xfront, yfront, zfrontは、前方向を指定するベクトル、そして、 xup, yup, zup は上方向を決定すすベクトルを指定する(これらは単位ベクトルでなくてもよい)。 fov パラメータには視野角、( in binary, 256 degrees to the circle format. ) 32-48 が適当である。視野角に 64 (90°) を入れると倍率が適用されない。 aspect にはアスペクト比(画面の比率....4/3)。アスペクト比の求め方は、 (float)w/(float)h という式を使う。


    ビユーポートの設定
    void set_projection_viewport(int x, int y, int w, int h);
    persp_project() 関数によって投影される画面の比率を ビユーポートをセットする。 スクリーンエリアの寸法は好きなように指定できるが、 通常は 0, 0, SCREEN_W, and SCREEN_H と指定する。 また、get_camera_matrix の後で、アスペクト比を後で設定しておくことを忘れてはいけない。あなたが指定したビューポートが3D空間上でどのような大きさにあるべきかを高さを幅を指定する。 距離は 1.0ならばスクリーンを完全に覆い尽くす。
    (すなわち get_camera_matrix 関数は、 視界角(FOV)とアスペクト比を通して倍率を適用するのでこれは厳密には正確ではない...。
    パラメータとして、-1/-1/2/2 を渡せば 余分なスケーリングは投影されない。


    投影法の設定
    void persp_project(fixed x, fixed y, fixed z, fixed *xout, fixed *yout);
    void persp_project_f(float x, float y, float z, float *xout, float *yout);
    3D空間上の点(x,y,z)を 2D平面 に投影する。 結果は (*xout, *yout)に出力される。 なお投影倍率は、calling set_projection_viewport()によって設定されたものが利用される。 この関数は、 x軸(左-右) y軸(上-下) z軸(手前-奥の深度) から成る視体積 を正規化したものが投影される。 カメラの視野角は90°である、つまり x=z と -x=z は スクリーンの端に位置する、そして、 y=z and -y=z は スクリーンの上下端に位置する。 もしあなたがカメラの視点位置を違うものにしたければ、すべての3Dオブジェクトを 適切な行列によって変換させなければならない。 例えば左に10°カメラをパンするなら、あなたはすべてのオブジェクトを右に10°回転させなければならない。


    角度について
    Allegro の一部の関数(get_z_rotate_matrix関数等)は、角度指定に、the specified angle (given in binary, 256 degrees to a circle format).という単位が使われている。 これは 円を256段階に分けた表記法で、360°= 256 Degree となる。例えば 90°= 64 , 45°=32


    行列

    参考文献:
    CAD・CGのための基礎数学5.2
    Future's Laboratory

    Allegro では、 3D 数学関数はすべて固定小数点数演算 と、浮動小数点 を使用する方法が使える。


    通常 3次元空間 に関する 線形変換は、 4X4からなる行列を、x,y,z 成分と、w=1 の同次ベクトルを操作することで、あらゆる変形が可能となる。
    ( a, b, c, d )
    ( e, f, g, h )
    ( i , j, k, l )
    ( m, n, o, p)

    Allegro の行列について
      Allegroでは  回転スケーリング&平行移動は 4x3行列 を用い、スクリーンに投影する関数を実行する段階で 4x4 行列へ変換する仕組みになっているらしい? そのため行列の最下段の列を扱う必要がなくなる。Allegro は 最下段が ( m, n, o, p )= (0,0,0,1) であると仮定して 、最適な行列操作を行う。 Allegro では任意の点を表すのに (x,y,z,w)の同時ベクトルを用いなくてもよく、行列変換関数はアフィン変換 のみサポートする。 DirectX は (m, n , o ) ? なお、 C++でプログラムする場合は、 fix class を使う必要があるとのこと。


    Allegro の行列オブジェクトについて

    Allegro では、 3D 数学関数はすべて固定小数点数演算 と、浮動小数点 を使用した方法が使える。 これらを使った構文は同一であるが、 浮動小数点を使うときは 関数の名前に '_f' を付けた名前の関数使うことになっている。 例えば固定小数点用の cross_product() 関数を、浮動小数点で使う場合は cross_product_f() を使わなければならない。

    固定小数点数 を使う場合は、MATRIX、 浮動小数点数を使う場合は、MATRIX_f 型のオブジェクトを用いる。
    typedef struct MATRIX -- 固定小数点用
    fixed v[3][3]; - 3x3 スケーリング(拡大縮小)& 回転 成分
    fixed t[3]; - x/y/z 平行移動 成分
    typedef struct MATRIX_f -- 浮動小数点用
    float v[3][3]; - 3x3 スケーリング(拡大縮小)& 回転 成分
    float t[3]; - x/y/z 平行移動 成分



    任意の点に行列を適用する
    void apply_matrix(const MATRIX *m, fixed x, y, z, *xout, *yout, *zout);
    void apply_matrix_f(const MATRIX_f *m, float x, y, z, *xout, *yout, *zout);
    任意の点(x,y,z)に 行列 *m を掛けて適用する。 変換結果後の座標は (*xout, *yout, *zout).に出力される。
    適用する前には、次にあげる関数を利用して行列*m を得ておく。

    単位行列
    extern MATRIX identity_matrix;
    extern MATRIX_f identity_matrix_f;
    単位行列、これは「何も変化しない」行列で、行列の初期化などに使われる。

    平行移動行列を得る
    void get_translation_matrix(MATRIX *m, fixed x, fixed y, fixed z);
    void get_translation_matrix_f(MATRIX_f *m, float x, float y, float z);
    この関数によって得られた行列を、任意の 点(px, py, pz) に適用した場合、点の 位置はそれぞれ (px+x, py+y, pz+z)へ変換される。 すなわち、これは、3Dオブジェクトが平行移動することを意味する。


    スケーリング行列を得る
    void get_scaling_matrix(MATRIX *m, fixed x, fixed y, fixed z);
    void get_scaling_matrix_f(MATRIX_f *m, float x, float y, float z);
    この関数によって得られた行列を、任意の点(px, py, pz) に適用した場合、点の 位置はそれぞれx倍,y倍,z倍された (px*x, py*y, pz*z)に変換 される。これは、3Dオブジェクトを拡大縮小させることを意味する。


    X軸回転行列を得る
    void get_x_rotate_matrix(MATRIX *m, fixed r);
    void get_x_rotate_matrix_f(MATRIX_f *m, float r);
    スタック行列 *m に対して、X軸のまわりを角度 r だけ回転させる行列を得る。 (given in binary, 256 degrees to a circle format).


    Y軸回転行列を得る
    void get_y_rotate_matrix(MATRIX *m, fixed r);
    void get_y_rotate_matrix_f(MATRIX_f *m, float r);
    スタック行列 *m に対して、Y軸のまわりを角度 r だけ回転させる行列を得る。 (given in binary, 256 degrees to a circle format).


    Z軸回転行列を得る
    void get_z_rotate_matrix(MATRIX *m, fixed r);
    void get_z_rotate_matrix_f(MATRIX_f *m, float r);
    スタック行列 *m に対して、Z軸のまわりを角度 r だけ回転させる行列を得る。 (given in binary, 256 degrees to a circle format).


    回転行列を得る(任意のベクトル軸)
    void get_align_matrix(MATRIX *m, fixed xfront, yfront, zfront, fixed xup, fixed yup, fixed zup);
    void get_align_matrix_f(MATRIX *m, float xfront, yfront, zfront, float xup, yup, zup);
    指定 等位のベクトルに沿って一直線に並ぶように行列を回転させる行列を得る(上と奥行の外積から右→)。 (これらは、正規化 または 垂直である必要はないが、上と前方向のベクトルは同じであってはいけない ) 前方向のベクトルが、0,0,-1 で 上方向のベクトルが 0,1,0 であれば、単位行列を返す。

    回転行列を得る(角度)
    void get_vector_rotation_matrix(MATRIX *m, fixed x, y, z, fixed a);
    void get_vector_rotation_matrix_f(MATRIX_f *m, float x, y, z, float a);
    任意のベクトル(x , y , z) の周りを 指定した角度 a だけ回転させる行列を得る。回転方向は時計回り。 (角度の単位は、given in binary, 256 degrees to a circle format).

    スケーリング回転行列を得る?
    void get_transformation_matrix(MATRIX *m, fixed scale, fixed xrot, yrot, zrot, x, y, z);
    void get_transformation_matrix_f(MATRIX_f *m, float scale, float xrot, yrot, zrot, x, y, z);
    任意の点が 3つの軸のすべての周りを角度r 回転するような拡大縮小回転行列を得る。(よくわかない)


    シンプルな行列操作(さらに加算)
    void qtranslate_matrix(MATRIX *m, fixed x, fixed y, fixed z);
    void qtranslate_matrix_f(MATRIX_f *m, float x, float y, float z);
    既存の行列に対して 単純にオフセットを加算し平行移動させる。 この関数は、乗算するのに2つの作業用の行列を一時的に利用する必要がない、


    シンプルな行列操作(さらに乗算)
    void qscale_matrix(MATRIX *m, fixed scale);
    void qscale_matrix_f(MATRIX_f *m, float scale);
    既存の行列に対して単純に倍率(拡大縮小) 要素を乗算させる。 この関数は、乗算するのに2つの作業用の行列を一時的に利用する必要がない、


    2つの行列同士の乗算
    void matrix_mul(const MATRIX *m1, const MATRIX *m2, MATRIX *out);
    void matrix_mul_f(const MATRIX_f *m1, const MATRIX_f *m2, MATRIX_f *out);
    2つの行列同士の乗算を行い、MATRIX *out に出力する。 ( この関数は、入力する側の行列をあらかじめバックアップをとっておかなければいけない。しかしこの関数は、入力と出力の行列が全く違っていた場合には処理が速くなる) (p * out) = ((p * m1) * m2) このようにして 2つの行列 *m1 と *m2 を合成する。 メモ:行列の乗算する順番によっては結果が違う事に注目( 例えば、matrix_mul(m1, m2) と matrix_mul(m2, m1) の結果は違うものになる)


    ベクトル

    ベクトルの長さを求める
    fixed vector_length(fixed x, fixed y, fixed z);
    float vector_length_f(float x, float y, float z);
    ピタゴラスの定理を使って、三次元空間上のベクトル(x,y,z) の 長さを求める。


    ベクトルの正規化
    void normalize_vector(fixed *x, fixed *y, fixed *z);
    void normalize_vector_f(float *x, float *y, float *z);
    ベクトルを正規化。ベクトル(*x, *y, *z) を 単位ベクトルに変換する。 特筆すべき点は、単位ベクトルとはオリジナルのベクトルと同じ方向で、長さが1のものを指す。


    ベクトルの内積
    fixed dot_product(fixed x1, y1, z1, x2, y2, z2);
    float dot_product_f(float x1, y1, z1, x2, y2, z2);
    ベクトル (x1, y1, z1) . (x2, y2, z2) が成す ベクトルの内積 ( dot product )を計算する。

    ベクトルの外積
    void cross_product(fixed x1, y1, z1, x2, y2, z2, *xout, *yout, *zout);
    void cross_product_f(float x1, y1, z1, x2, y2, z2, *xout, *yout, *zout);
    2つの入力 ベクトル (x1, y1, z1) . (x2, y2, z2) が成す ベクトルの外積 ( cross product )を計算する。 計算 結果は、 ベクトル(*xout, *yout, *zout) に出力される。 ベクトルの外積は、構成されるベクトルに対して垂直という性質をもっていて、ポリゴン面を正規化する時など用いられる。


    カリング
    fixed polygon_z_normal(const V3D *v1, const V3D *v2, const V3D *v3);
    float polygon_z_normal_f(const V3D_f *v1, const V3D_f *v2, const V3D_f *v3);
    ポリゴンを形成する3つの z 方向の単位ベクトル を探し出す。 この機能は 背面除去(back-face culling)の為に利用される。 なぜ除去しなければいけないかというと、閉じたポリゴンの裏面等、画面から見えないデータを削除することで、処理データを減らして高速化がはかれる。 この関数は、 ポリゴンを半分の割合で選り抜いて除去することができる。ただし、この隠面除去はいったん persp_project()関数(または、正投影等 )によってスクリーン投影 された後しか使う事ができない。

    メモ:3D空間上にある3つの頂点が 同じ直線上にある場合にはこの機能は失敗する。
    返値:
    -1 = ポリゴンは安全に選り抜くことができる。
    0 = そのポリゴンはスクリーンに対して垂直である。

    Quaternion クオータニオン

    Quaternion(クオータニオン) を使って、3D空間上で回転を表現するのに、ベクトルを用いて任意の回転軸 を中心に、始点 (a)から 終点(b)の方向へ、何度回転させるかを指定する。なお、回転軸のベクトルは、始点 (a)と終点(b)の ベクトルの外積にあたり、(a)と(b)を含む回転面に垂直となる。クオータニオンには xyz回転量を指定する方法にみられる欠点はなく複雑な回転(ひねり回転など)制御もなんなくこなすことができる。


    Allegro の デモプログラム exquat は xyz の回転量を指定する 「Euler Angle(オイラー角)」 と、我らが「Quaternion(クォータニオン)」 による3次元空間上の回転をわかりやすく比較するという内容。



    OpenGLと併用する場合、AllegroGL を使う事になりますが、OpenGLはクオータニオン関係の関数が用意されていないので AllegroGLが OpenGL行列 とAllegro の行列を変換する関数を用意している。

    Allegroの クォ−タニオンオブジェクト
    typedef struct QUAT
    float w, x, y, z;
    クオータニオンは4つの部分からなる四元数とも呼ばれ、3つの虚数単位 i, j, kをもっていて、複素数の親戚にあたる。

    単位クオータニオン
    extern QUAT identity_quat;
    このグローバル変数は、 行列における単位行列のように、何も変化のない「単位クオータニオン」を意味する。単位クオータニオン絶対値が 1 という性質を持っている。とりあえずクオータニオンを設定する場合はこれで初期化する!?

    各軸で回転
    void get_x_rotate_quat(QUAT *q, float r);
    void get_y_rotate_quat(QUAT *q, float r);
    void get_z_rotate_quat(QUAT *q, float r);
    それぞれの軸に r 度回転する。(given in binary, 256 degrees to a circle format).

    任意の軸で回転
    void get_rotation_quat(QUAT *q, float x, float y, float z);
    クオータニオンオブジェクトを構成する3つの軸の量(given in binary, 256 degrees to a circle format) を指定してポイントを回転させる。

    任意の軸と角度で回転
    void get_vector_rotation_quat(QUAT *q, float x, y, z, float a);
    クオータニオンオブジェクトを構成するx,y,z ベクトルと角度a (given in binary, 256 degrees to a circle format) を指定してポイントを回転させる。

    クオータニオン→回転行列
    void quat_to_matrix(const QUAT *q, MATRIX_f *m);
    クオータニオン→回転行列へ変換する。


    回転行列 →クオータニオン
    void matrix_to_quat(const MATRIX_f *m, QUAT *q);
    回転行列 →クオータニオンへ変換する。


    クオータニオンの2つの回転を乗算し、回転を合成する
    void quat_mul(const QUAT *p, const QUAT *q, QUAT *out);


    クオータニオンの適用
    void apply_quat(const QUAT *q, float x, y, z, *xout, *yout, *zout);
    任意の点 (x, y, z) に対してクオ−タニオン q を適用して、ポイント(*xout, *yout, *zout).として出力する。これは行列による apply_matrix_f()関数より少し処理が遅い。 そのため、もし多くの点に適用する場合はまず quat_to_matrix() を呼び、 apply_matrix_f()を呼ぶとよい。

    ( 内部処理では、逆クオータニオンを生成している、 quat_inverse(q, &i); quat_mul(&i, &v, &t); quat_mul(&t, q, &v); )


    クオータニオン回転の補間
    void quat_interpolate(const QUAT *from, const QUAT *to, float t, QUAT *out);
    クオータニオン*from と*to を構築する。 t は 0(*from 方向)〜1(*to 方向)の値をとる。t = 0.5 の場合はちょうどまんなかになる。 結果は クオータニオン *out に反映される。 この関数は、*from と*to の角度は short rotation ( 180°より小さい角度の回転) を形成する。


    回転角領域が指定可能な補間
    void quat_slerp(const QUAT *from, const QUAT *to, float t, QUAT *out, int how);
    一見 quat_interpolate()関数と同じにみえて、回転の方向をコントロールすることができる。slerp = 球面線形補間 int how パラメータによって回転の種類をコントロールできる。その内容は以下の通り。
    QUAT_SHORT - quat_interpolate()のように、球面線形補間による最短距離を通って回転する
    QUAT_LONG - 180°より大きな角度の回転。
    QUAT_CW - 上から見て時計回りの方向に回転する。
    QUAT_CCW - 上から見て反時計回りの方向に回転する。
    QUAT_USER - クオータニオンは、指定したように補間できる

    GUI routines Allegro GUI

    (仮)
    AllegroのGUI は、大きく2つの分野、ダイアログストラクチャとメニューストラクチャを扱う。
  • ダイアログストラクチャ - ボタンやテキスト、スライドバーなどのGUIエレメント
  • メニューストラクチャ - プルダウンメニュー(Macのメニューバー形式)

  • ※現時点 (v4.2.0 RC2)では 日本語文字が含まれるファイル名やファイルパスは未対応(その部分が文字化けする)。
    v4.2.0 正式版 で 日本語文字が含まれるファイル名やファイルパスの表示できるようになりました。

    デザインは、Allegro独自のもので、デフォルトはグレーがかったインターフェイス。多少のカスタマイズはできますが、 もっと凝ったデザインを求めるなら、Allegro対応の 拡張GUI ライブラリを使用する選択肢もある。

    概要

    Allegroはオブジェクト指向のダイアログマネージャを含んでいる。これはAtariの GEMシステム (form_do(), objc_draw(), 等が起源になっている) テストプログラム のような小さなものから Grabberのような実用性の高いプログラムまで、インターフェースを叩くのに使う事ができる。さもなければ あなたはより複雑なOSの仕組みを使わなければならないかもしれない。

    Allegro は新しいダイアログ プロシージャ(ダイアログが動作する手順)を書く事でユーザー自身のオブジェクトタイプを定義することができる。従ってマウス、キーボード、ジョイスティック等からの入力はAllegroに任せる事で、ユーザーインターフェイスやGUI 制御を完全にコントロールすることができる。


    参考文献:
    The Allegro GUI Clinic AllegroGUI のチュートリアル (英語)

    想像図:
    GUIの仕組み, 構造体

    ダイアログストラクチャ(構造体)について

    GUIダイアログは、 DIALOGストラクチャの配列として格納されており、 ("Structures and types defined by Allegro" のメンバ変数を参照)配列は 0が置かれるポインタがあるオブジェクトが最後になっていなければならない。各オブジェクトに は次のビットフラグの組み合わせを含む flags field というデータが含まれることもある。
    typedef struct DIALOG
    int (*proc)(int, DIALOG *, int); - ダイアログプロシージャへのポインタ
    (メッセージヘッダ)
    int x, y, w, h; - オブジェクトの位置(x,y)とサイズ(w×h)。
    int fg, bg; - fg=前傾色 と bg=背景色
    int key; - 割り当てたキーボードショートカット
    int flags; - オブジェクトのステータスフラグ
    int d1, d2; - あなたが使いたいと思ったものはなんでも。
    void *dp, *dp2, *dp3; - オブジェクト固有のデータへのポインタ


     int flags; - オブジェクトのステータスフラグ  
    D_EXIT - このオブジェクトは クリックするとダイアログが閉じる。
    D_SELECTED - このオブジェクトは選択されている。this object is selected
    D_GOTFOCUS - このオブジェクトは入力フォーカスされている。
    D_GOTMOUSE - マウスは現在オブジェクトの上にある。
    D_HIDDEN - このオブジェクトは 隠れていて非アクティブである。
    D_DISABLED - このオブジェクトは、グレー表示で非アクティブである。
    D_DIRTY - このオブジェクトは 再描画の必要がある。t
    D_INTERNAL - ライブラリ内部用なのでこれを使っていはいけない、
    D_USER - ユーザーが自由に使える。
    int d1, d2; - あなたが使いたいと思ったものはなんでも。
    void *dp, *dp2, *dp3; - オブジェクト固有のデータへのポインタ等に使う。
    これには、コールバック関数へのポインタを指定したり、とにかく何でも指定できる。


    サンプル、exgui.c から DIALOG ストラクチャの具体的な設定方法の例
    the_dialog[] = というふうに 配列指定すると、いくつもオブジェクトを定義する事ができる。
    DIALOG the_dialog[] =
    {
    /* (dialog proc) (x) (y) (w) (h) (fg)(bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */

    /* GUIにキャプションを付ける場合はこのようになる */
    { d_text_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "d_menu_proc->", NULL, NULL },
    { d_text_proc, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, "d_button_proc->", NULL, NULL },

    /*GUI エレメント:ボタンやチェックボックス等、 ショートカットもある */
    { d_button_proc, 160, 40, 160, 20, 0, 0, 't', 0, 0, 0, "&Toggle Me!", NULL, NULL },
    { d_check_proc, 160, 70, 160, 20, 0, 0, 'c', 0, 0, 0, "&Check Me!", NULL, NULL },
    { d_edit_proc, 160, 130, 160, 8, 0, 0, 0, 0, LEN, 0, the_string, NULL, NULL },
    { d_list_proc, 160, 150, 160, 44, 0, 0, 0, 0, 0, 0, (void *)listbox_getter, sel, NULL },

    /* ステータスフラグに D_EXIT フラグ を含むもの */
    { my_button_proc, 0, 450, 160, 20, 0, 0, 'q', D_EXIT, 0, 0, "Quit", NULL, (void *)quit },
    { my_button_proc, 400, 150, 160, 20, 0, 0, 'i', D_EXIT, 0, 0, "Info", NULL, (void *)info1 },
    { my_button_proc, 400, 200, 160, 20, 0, 0, 'n', D_EXIT, 0, 0, "Info", NULL, (void *)info2 },

    /* サンプル exrgbhsv.c に見られるコールバック例: pdate_color_valueという関数名に注目*/
    /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */
    { my_slider_proc, 32, 16, 256, 16, 0, 255, 0, 0, 255, 0, NULL, (void *)update_color_value, &colors[S_R] },
    { my_slider_proc, 32, 64, 256, 16, 0, 255, 0, 0, 255, 0, NULL, (void *)update_color_value, &colors[S_G] },

    /* DIALOGストラクチャ配列の最後は 必ず次のような NULL データを置かなければならない */
    { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
    };
    例えば、ボタンをクリックすると、それに関連するダイアログストラクチャの配列の に記述してあるポインタ(*dp, *dp2, *dp3)に従って、コールバック関数が呼ばれ処理が行われるという仕組みらしい。
    コールバック関数については次のように関数を作成されるが、返値を適切に設定する必要がある。
    /* *dp ポインタに 指定する コールバック関数*/
    int update_color_value(void *dp3, int val){
    /* 処理*/

    /* D_O_K をダイアログ ストラクチャに返す*/
    return D_O_K;
    }
    ダイアログ マネージャへ返す変数。:
    D_O_K - 通常ステータスを返す。
    D_CLOSE - ダイアログは、ダイアログを閉じるように ダイアログマネージャに伝える。
    D_REDRAW - ダイアログ全体を描き直すようにダイアログマネージャに伝える。
    D_REDRAWME - 現在のオブジェクトを描き直すようにダイアログマネージャに伝える。
    D_WANTFOCUS - 入力フォーカスをオブジェクトに与えるという要求
    D_USED_CHAR - もしこれらがキーを使ったなら、MSG_CHAR または MSG_XCHARを返す。


    メニューストラクチャ(構造体)について

    typedef struct MENU
    char *text; - メニューアイテムの為に表示されるテキスト

    int (*proc)(void); - アイテムがクリックされる時に呼ばれる コールバック関数を指定
    struct MENU *child; - ネストされた子メニュー
    int flags; - 項目がチェックされた/使用可能か の状態
    void *dp; - あなたが必要とするデータへのポインタ

    MENU submenu[] =
    {
    { "Submenu", NULL, NULL, D_DISABLED, NULL },
    { "", NULL, NULL, 0, NULL },
    { "Checked", check_callback, NULL, D_SELECTED, NULL },
    { "Disabled", NULL, NULL, D_DISABLED, NULL },
    { NULL, NULL, NULL, 0, NULL }
    }

    MENU main[] ={
    { "&Test", menu_callback, NULL, 0, NULL },
    { "&Submenu", NULL, submenu, 0, NULL },
    { NULL, NULL, NULL, 0, NULL }
    {
    MENUストラクチャ配列の最後も 必ず NULL データを置かなければならない。

    ダイアログプロシージャを扱う関数

    各オブジェクトはダイアログプロシージャのポインタに格納された情報によってコントロールされる。 オブジェクトに関するアクションが必要な時はいつでもダイアログプロシージャが呼ばれる。 さもなければ、object_message() 関数を使って直接呼び出すことができる。

    ダイアログプロシージャを扱う関数のパラメータは次のようになっている。
    int proc(int msg, DIALOG *d, int c);
    /* int (*proc)(void) に指定する コールバック関数*/
    /* メニュー項目がクリックされたら それぞれに対応した関数が呼ばれる*/
    int check_callback(){

    /* 何か処理をする */

    /* D_O_K をダイアログ ストラクチャに返す*/
    return D_O_K;
    }
    ↑のようなコールバック関数を機能ごとに用意する。

    typedef struct DIALOG_PLAYER
    typedef struct MENU_PLAYER
    この2つの構造体については、init_dialog() ,init_menu() 関数の説明をみる。

    実行

    /* the_dialog[] の ダイアログを実行する */
    ret = do_dialog(the_dialog, -1);
    詳細については、do_dialog() ,do_menu() 関数への説明を参照。


    関数

    # do_dialog —  ダイアログマネージャの基本関数。  
    # do_menu — ポップアップメニューをアニメーション表示。
    # popup_dialog — ポップアップ ダイアログのために do_dialog() を使う。
    # position_dialog — 指定した位置にダイアログオブジェクトの配列 を移動する。

    # init_dialog — Low level (細かい指定ができる)のダイアログ初期化関数
    # init_menu — Low level (細かい指定ができる)のメニュー初期化関数
    # update_dialog — Low level (細かい指定ができる) のdialog player更新関数。
    # update_menu — Low level (細かい指定ができる) のmenu player更新関数。
    # object_message — オブジェクトにメッセージを送り反応を返す。
    # shutdown_dialog — init_dialog()関数によって 返された dialog playerを破棄する。
    # shutdown_menu — init_menu()関数によって 返された menu player を破棄する。

    # active_dialog — 最後にアクティブになった、ダイアログを指すグローバルポインタ  
    # active_menu —最後にアクティブになった、メニューを指すグローバルポインタ  
    # alert — アラートボックスをポップアップ表示する。 
    # alert3 — alert()関数と似ているが、こちらは3つのボタンがある。

    # broadcast_dialog_message — アクティブダイアログのすべてのオブジェクトにメッセージを投げる。
    # dialog_message — 配列のすべてのオブジェクトにメッセージを送る。
    # centre_dialog — ダイアログオブジェクトの配列を集中させる。

    ダイアログ プロシージャ

    # d_bitmap_proc — ダイアログ プロシージャを、ビットマップに描画する。
    # d_box_proc — ダイアログ プロシージャをスクリーン上のボックスに描画する。
    # d_button_proc — ダイアログ プロシージャをボタンオブジェクトに実装する。
    # d_check_proc — ダイアログ プロシージャをチェックボックスオブジェクトに実装する。
    # d_clear_proc — スクリーンを消去する為のダイアログ プロシージャ。
    # d_ctext_proc — ダイアログ プロシージャ をテキストとしてスクリーンに描画する。
    # d_edit_proc — ダイアログ プロシージャを編集可能なテキストエリアオブジェクトに実装する。
    # d_icon_proc — ダイアログ プロシージャをビットマップ画像付きボタンに実装する。
    # d_keyboard_proc — キーボードショートカットのための不可視 ダイアログ プロシージャ 。
    # d_list_proc — ダイアログ プロシージャ をリストボックスオブジェクトに実装する。
    # d_menu_proc — ダイアログ プロシージャ をメニューバーに実装する。
    # d_radio_proc — ダイアログ プロシージャ をラジオボタンに実装する。
    # d_rtext_proc — 複数のダイアログ プロシージャ を スクリーン上にテキストとして実装する。
    # d_shadow_box_proc — ダイアログ プロシージャをスクリーン上にボックスとして描画する 。
    # d_slider_proc — ダイアログ プロシージャ を素ライターバー として実装する。
    # d_text_list_proc — ダイアログ プロシージャ を タイプ別のリストボックスとして実装する。
    # d_text_proc — 複数のダイアログ プロシージャ を スクリーン上のテキストとして描画する。
    # d_textbox_proc — ダイアログ プロシージャをテキストボックスオブジェクトとして実装する。  
    # d_yield_proc — CPU切り替えを得る?、タイプ不可視のダイアログ プロシージャ

    その他

    # gui_textout_ex — キーボードショートカット アンダーバーを使いテキストを画面に描画する
    # file_select_ex — Allegroファイルセレクタをキャプション付きで表示。 
    # find_dialog_focus — インプットフォーカスされたオブジェクトをダイアログから検索する。
    # gfx_mode_select — Allegroグラフィックモードを選択するダイアログを表示(画面解像度や色深度など)。
    # gfx_mode_select_ex — Allegroグラフィックモード選択ダイアログ拡張版。
    # gfx_mode_select_filter — さらに拡張版。

    # gui_bg_color — 標準的なダイアログのための前景及び背景色
    # gui_fg_color — 標準的なダイアログのための前景及び背景色。
    # set_dialog_color — ダイアログオブジェクト 配列の色を設定する。
    # gui_mg_color — greyed outダイアログオブジェクトのために用いられる色

    # gui_button_proc —Allegroダイアログの外観をカスタマイズする
    # gui_ctext_proc —Allegroダイアログの外観をカスタマイズする
    # gui_edit_proc —Allegroダイアログの外観をカスタマイズする
    # gui_list_proc — Allegroダイアログの外観をカスタマイズする
    # gui_text_list_proc — Allegroダイアログの外観をカスタマイズする
    # gui_shadow_box_proc — Allegroダイアログの外観をカスタマイズする

    # gui_font_baseline — キーボードショートカットのアンダースコアの高さを調節する。
    # gui_get_screen — GUIルーティンを描画する為に ビットマップ画面を返す。
    # gui_set_screen — GUIルーティンを描画する為に ビットマップ画面をセットする。

    # gui_menu_draw_menu — メニューのアピアランスを変更するための Hooks
    # gui_menu_draw_menu_item — メニューのアピアランスを変更するための Hooks

    # offer_focus — 入力フォーカスを特定のオブジェクトに提供する。
    # gui_mouse_focus — マウスポインタがフォーカスした場合に知らせる。
    # gui_mouse_b — マウスの状態によってGUI ルーティンにアクセスし Hook 関数を使う。
    # gui_mouse_x — マウスの状態によってGUI ルーティンにアクセスし Hook 関数を使う。
    # gui_mouse_y —マウスの状態によってGUI ルーティンにアクセスし Hook 関数を使う。
    # gui_mouse_z — マウスの状態によってGUI ルーティンにアクセスし Hook 関数を使う。

    # gui_strlen — 文字列の長さ(pixel)を返す。



    ここから先は ダイアログプロシージャを自作する場合の情報。

    ダイアログプロシージャを使って機能強化する

    ユーザーが自分でダイアログプロシージャを作ってGUIの機能を拡張することもできる。

    各オブジェクトはダイアログプロシージャのポインタに格納された情報によってコントロールされる。 オブジェクトに関するアクションが必要な時はいつでもダイアログプロシージャが呼ばれる。 その他には、object_message() 関数を使って直接呼び出すこともできる。

    ダイアログプロシージャ関数として機能するための、パラメータは次のように決められている。
    int my_proc(int msg, DIALOG *d, int c);

    実際の使用例は、サンプルの exrbghsv.c が参考になる。
    > int my_slider_proc(int msg, DIALOG *d, int c)
    また、d_button_proc のような既存のダイアログプロシージャ関数の処理内容を覗いて調べるのも参考になるかもしれない。

    ダイアログプロシージャの挙動を決める 「メッセージフラグ」

    int msg に渡されるフラグは ダイアログのポインタ d であらわされるオブジェクトがどんなふるまいを行なうかを示す。 そして、 msg (メッセージ)フラグが MSG_CHAR あるいは MSG_XCHAR であれば c で示されたキーが押されたことになる。 メモ: d はダイアログ全体ではなく、 特定のオブジェクトを示すポインタであることに注意する。

    ダイアログプロシージャは次のいづれか から呼ばれる可能性がある:
    int my_func_name(int msg, DIALOG *d, int c)
    MSG_START:
    オブジェクト自身を初期化するようにオブジェクトにメッセージを伝える。 ダイアログマネージャはそれがダイアログに表示する直前にオブジェクトに送る。


    MSG_END:
    オブジェクトが片付けられるものはなんでもダイアログが閉じる時にすべてのオブジェクトにメッセージを伝える。


    MSG_DRAW:
    オブジェクト自身をスクリーンに描画するように伝える。このメッセージを送る時にはマウス・ポインタをオフにするので描画コードはそれを心配する必要がない。


    MSG_CLICK:
    オブジェクトの上にマウスが乗っている間にボタンがクリックされたという情報。 通常オブジェクトはマウスボタンが押されている限りマウスの挙動を維持する。 そして、ボタンが離された時だけメッセージハンドラからメッセージが返される。 もし、このメッセージを処理するなら、gui_mouse_*() 関数を使用してマウスの状態を取得してください。

    MSG_DCLICK:
    ユーザーがオブジェクトをダブルクリックした時に送られる。 最初にボタンが押された時にはMSG_CLICKが送られさらに短期間で再び押された場合にMSG_DCLICKが送られる。 もし、このメッセージを処理するなら、gui_mouse_*() 関数を使用してマウスの状態を取得してください。


    MSG_KEY:
    オブジェクトが押されたというキーボードショートカットが発生した時、または 入力フォーカスがある間に enter, spaceキーやジョイスティックのボタンが押された時にこのメッセージが送られる。


    MSG_CHAR:
    キーが押されたとき、このメッセージを入力フォーカスを持っているオブジェクトに送ります。 c パラメータとして、readkey()形式のキャラクターコード をオブジェクトに送ります。 オブジェクトがkeypressに対応している場合はD_USED_CHARを返さなければならない。そうでなければ デフォルトキーボードインターフェースが操作するのを許可する D_O_Kフラグを返さなければならない。文字入力がユニコードに対応する必要があるなら、MSG_CHARの代わりにMSG_UCHARを使用するべきです。


    MSG_UCHAR:
    オブジェクトがMSG_CHAR入力を無視した場合、このメッセージが代わりに送られる。完全なユニコードの値が c パラメータに渡される。 これは、アドレスが255以上のキャラクターコードの読み込みを可能にしますが、scancodeに関しては何も伝えない。 もしそれを知る必要があるなら、代わりにMSG_CHARを使ってください。そうでなければ、もし入力/D_O_Kフラグを処理した場合は_D USED_CHARを返すでしょう。


    MSG_XCHAR:
    キーが押されたとき、Allegroは入力フォーカスのあるオブジェクトにMSG_CHAR と MSG_UCHAR メッセージを送る。
    もしオブジェクトが そのキーを処理しない場合(D USED_CHARよりむしろD_O_Kを返す場合)、オブジェクトマネージャは、データのキーフィールドから適合するショートカットが存在するオブジェクトを探して MSG_KEYをそれに送るでしょう。 この処理が失敗した場合は、ダイアログのすべてのオブジェクトにMSG_XCHARを投げる。 オブジェクトにフォーカスが当たっていない時でさえ 特殊なキー入力に応じるのを許可して(D USED_CHARよりむしろリターンD_O_K)を無視する場合 矢印キーに対応してフォーカスを移動させ、ESCキーが押されたらダイアログを閉じるといった デフォルト動作をAllegroが実行する。


    MSG_WANTFOCUS:
    オブジェクトが入力フォーカスを許可するか否かに関係なくクエリーを送る。 もしそれが実行されたら、D_WANTFOCUSを返し、それがユーザー入力に関係しない場合は D_O_K を返す。


    MSG_GOTFOCUS:
    MSG_LOSTFOCUS:
    オブジェクトがフォーカスを得たり失ったりするときはいつでもこれらのメッセージを発信する。 これらのメッセージは いつもMSG_DRAWに従って フォーカスの当たったかどうかのオブジェクトの表示を 切り替える。もし、 あなたがMSG_LOSTFOCUSイベントに対してD_WANTFOCUSを返すと、これは マウスがスクリーンの背景に移ったりして、オブジェクトのフォーカスが失われるのを防ぐので、 ある他のオブジェクトが焦点を持って行く準備ができている(このトリックはd_edit_proc()オブジェクトによって使用されます)ときだけ入力フォーカスが失われるでしょう。


    MSG_GOTMOUSE:
    MSG_LOSTMOUSE:
    オブジェクトの上からマウスが移動したり離れた時に送られる。 これらはMSG_DRAWによって続かないので、 マウスが上にある時にオブジェクトを違うふうに表示するなら このメッセージの挙動に応じてオブジェクト自身を描き直す義務があります。


    MSG_IDLE:
    ダイアログマネージャが何もすることがない時はいつでもこのメッセージを発信する。

    MSG_RADIO:
    クリックした際に同じグループにある他のボタンが解除された時に ラジオボタンオブジェクトによって発信される。
    グループ番号は c メッセージパラメータによって渡される。


    MSG_WHEEL:
    マウスホイールが回転するときはいつでも フォーカスされたオブジェクトに発信される。cメッセージパラメータはクリックした数が含まれる。


    MSG_LPRESS, MSG_MPRESS, MSG_RPRESS:
    対応するマウスボタンが押されるときに、発信される。


    MSG_LRELEASE, MSG_MRELEASE, MSG_RRELEASE:
    対応するマウスボタンが離されたときに、発信される。

    MSG_USER:
    汎用メッセージ変数。 (MSG_USER、MSG_USER+1、MSG_USER+2、…MSG_USER+n) と名付けられた どんな番号も好きな時に使うことができる。

    Allegroはいくつかの標準ダイアログ プロシージャを提供する。それらは簡単なユーザーインターフェイスオブジェクト、あるいはユーザー定義のダイアログプロシージャ を呼ぶことができる。これらは一種のオブジェクト指向プログラミングでいう継承をもたらす。

    例えばあなたがボタン描くためには d_button_proc関数を呼んで作成することができる。しかし それとは機能は違うけれども、 クリックメッセージを処理するボタンや 画面全体を描画する d_button_procを呼び出すボタンも同じように作る事ができる。

    Allegro デフォルトのGUI を実行するためのメモ。

    日本語フォント(TrueType)を使う場合は、set_uformat(U_UTF8); し、 GlyphKeeper を導入すること。
    日本語を含むUTF8ファイルパス表示は改善されましたが、d_edit_proc への日本語の入力は、なにか工夫が必要。
    
    /* unicode用の最大byte数*/
    #define MAX_BYTES_PER_CHAR 6      
    
     /*  d_edit_proc オブジェクトのための定義 */
    #define LEN 32          
    
    /* 書かれている文字 */
    char the_string[(LEN + 1) * MAX_BYTES_PER_CHAR] = " テキスト abc" ;
    
    // ダイアログ ストラクチャ
    // はじめに d_clear_proc を置かないとうまくGUIが配置されない。また、構造体の最後には、NULLだけのデータを置かなければいけない。
    //  DIALOG *obj を引数とする関数で, d_edit_proc の欄に入力されている  文字列 は char *text = obj->dp のように取得することができる。
    DIALOG the_dialog[] =
    {
       /* (dialog proc)     (x)   (y)   (w)   (h) (fg)(bg) (key) (flags)     (d1) (d2)    (dp)                   (dp2) (dp3) */
    { d_clear_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { d_text_proc, 0, 130, 0, 0, 0, 0, 0, 0, 0, 0, "表示する文:", NULL, NULL }, { d_edit_proc, 160, 130, 160, 8, 0, 0, 0, 0, LEN, 0, the_string, NULL, NULL }, { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; /* メインルーチンの内 */ main(){ /* ユニコードの設定や、Allegro、 GlyphKeeperの初期化を行っておく。*/ set_uformat(U_UTF8); allegro_init(); gui_fg_color = makecol(0, 0, 0); gui_mg_color = makecol(128, 128, 128); gui_bg_color = makecol(200, 240, 200); set_dialog_color (the_dialog, gui_fg_color, gui_bg_color); the_dialog[0].bg = makecol(255, 155, 255); //the_dialogストラクチャの 0番目のGUI部品 (d_clear_proc )の背景色を白くする。 the_dialog[1].bg = makecol(200, 0, 0); //the_dialogストラクチャの 1番目のGUI部品(d_text_proc)の背景色を赤くする。 position_dialog (the_dialog, 2, 2); // 配置 do_dialog(the_dialog, -1); // GUI を実行する。 return 0; } END_OF_MAIN();
    参考:
    d_edit_proc を パスワード入力欄「*****」風にする:
    Password field with d_edit_proc ?

    メモ:
    ダイアログプロシージャに日本語変換処理を割り込めば、日本語も入力できるかもしれない、しかし入力のタイミングをどうするかが問題です。

     
    2005.07.28 Packfile Matrix , Joystick , Polygon を追加
    2005.07.09 MIDI , Recordeing , Graphic Mode を追加
    2005.05.15 Allegro の バージョンは 4.1.18〜4.2.0β4
    2005.04.27

    Tsukubado