■top■
Allegro API (一部)システム* 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仕様が変更される可能性も考えられます。 ここに書かれたメモや仕様の正確性は保証しません。もし利用する場合は自己責任でお願いします。 APITransparency 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; 時間を取得する 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>struct tm 構造体の使い方 hogehoge->tm_hour 構造体(ストラクチャ)
各項目を参照。
もし、自作の関数にAllegro の bitmap ストラクチャを渡さなければいけないときは、引数にストラクチャの型名も記述する。 ストラクチャは、ポインタとして渡されたり、メンバ変数にアクセスできたりする。 void my_function( BITMAP *bitmap ){ メンバ変数にアクセスする場合 構造体ポインタの場合 は アロー演算子を使う。 int width = bitmap->w; そうではない場合は。ドット演算子を使う。 int width = bitmap.w; ユニコード関連
プログラム中で扱う文字コードを指定する
void set_uformat(int type); int type には 次のいずれかのエンコーディングモード を指定します。 ●Allegroに初めから用意されているエンコーディングモード日本語文字列を扱うには、U_UNICODE か U_UTF8 を指定すると良いです。 たとえば、 set_uformat( U_UTF8 ); と書く事で、プログラム中でUTF8文字列を使うことができます。 重要:この関数はAllegroの初期化 allegro_init(); よりも 先に 呼び出す必要があります。 現在設定されている文字コードの種類を取得する int get_uformat(void); 文字コード別に処理を振り分ける時に使う。 switch(get_uformat()) {返値:現在使用している 文字コートの種類を返す。 拡張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()関数で指定可能なエンコーディングモードを追加します。 ただし、実際のエンコード処理や文字列処理関数は自前で用意しなければいけません。 登録された 各関数はフック関数として呼び出されます。例えば EUC_JP エンコーディングで何かしたい場合は、次のようになるそうです。 文字コードのデータ形式に関するの知識が必要です。 // まず、 ugetc, ugetx, usetc, uwidth, ucwidth, uisok 関数に相当する日本語文字コード処理関数を書いて下さい。この項目を書くにあたって、register_uformat()? のトピックを参考にしました: 文字からユニコードを得る(文字列の一番最初の文字だけ) int ugetc(const char *s); Unicode テキストデータを読むための 低レベル機能サポート関数です。 int first_unicode_letter = ugetc(text_string);返値: 現在のエンコーディングモードの形式で、文字あるいは、文字列の一番最初の文字のコードが返ります。 文字からユニコードを得る int ugetx(char **s); int ugetxc(const char **s); Unicode テキストデータを読むための 低レベル機能サポート関数です。ugetc()関数 と違い、文字列を構成する すべての文字のコードデータを扱うことができます。この関数は、const がついた文字変数でも使えます。 char *p = string;返値: 現在のエンコーディングモードの形式で、数値が返ります。この関数は、同じポインタに対して 使用するたびに、前回指し示すポインタのアドレスから、さらに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];注意:空文字列を指定する場合でも、バッファに終端文字列を考慮したサイズを与えなければいけない。 さもなければ、デバッグ版の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 );ustrsize との違い set_uformat( U_UTF8 );なお、文字列をスクリーンに描画した時の幅(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);返値: コードそのものを返す 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 に含まれているかどうかを調べる。返値: 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) {返値: 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]; 文字列のコピー 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;返値: トークン(字句)へのポインタがもし見つからなければ NULLを返す。 あなたは NULLが返ってきた場合にメモリを解放することができる。 文字列の検索(複数マッチ対応) char *ustrtok_r(char *s, const char *set, char **last); 該当する 文字列 を検索する(文字列中に複数見つかってもOK)。 最後のパラメータは、char ポインタのポインタ last です。 char *word, *last;返値: トークンへのポインタor もし見つからなければ NULLを返す。 あなたは NULLが返ってきた場合にメモリを解放することができる。 Configure コンフィグコンフィグファイルはWindows95以前に使われていた初期設定ファイルで、アプリケーション毎にその設定を記録したものです。Allegroでは、Allegroアプリケーションのためのコンフィグファイル(拡張子.ini)を扱います。 このコンフィグファイルのデータ形式は「セクション」ごとに、それぞれ「キー」と「値」 のデータの組み合わせがあります。たとえば、ジョイスティックのキーコンフィグや、色深度、画面モードなどの設定がセクションそして設定する事ができます。 Allegroのコンフィグ関数を使えばWindowsと同じように、LinuxやMacOSXでも共通の初期設定を扱う事ができます。 .INIファイル # セクション 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);と同じ 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,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 if (key[KEY_W]) {たとえば、capslockキーで、カタカナひらがな入力の切り替えを行う例。 capslockキーが押されている間は カタカナを入力するという場合。 if ( key_shifts & KB_CAPSLOCK_FLAG ) { 何かキーが押されたか判断する int keypressed(); 返値:TRUE なら、何かキーが押されたことを示す readkey(); は入力待ちのためプログラムの進行がストップしてしまう。それを回避するには keypressed(); を使って判断し、 キーが押されたときだけキー入力を拾うようにするとよいです。 キー入力を拾う int readkey(); キーで入力された文字を得る。 int val;バッファが空の間は、キー入力までプログラムの進行を待機させるので ユーザーの入力に対して次の場面に進ませるという使い方もできる。 textout(screen, font, 30, 20, 0 , -1," -PUSH ANY KEY - なにかキーを押してネ" );キー入力を拾う(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; UTF8では、"ん"= E38293 なので "\xE3\x82\x93" のように書いても"ん" と表示できます。 (※ 「¥」は実際には、バックスラッシュ) キー入力のシミュレート void simulate_keypress(int key); キーを押さなくても、 キーバッファにキー入力情報を渡すことで、ユーザーがキーを押したようにみせかける。 キーバッファの内容は、それぞれreadkey();、 ureadkey(); を使って判別する。 simulate_keypress(KEY_SPACE << 8); キー入力のシミュレート(Unicode版) void simulate_ukeypress(int keyy, int scancode ); simulate_ukeypress(0x00DF, 0);使っている キーボードの種類によってキーが存在しなくても 、この関数によってフォローすることができる。 また、 キーボード以外の ソフトウェアキーボードやストロークを利用して文字入力する場合にも使えるかもしれない。 キー入力設定 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;メモリ保護の詳細については install_int_ex() の説明を見ること。 Joystick routines ジョイスティック
(仮)
Allegroはマウスやキーボードでもないハードウェア、ジョイスティック入力を実装する。 しかし、ほとんどのプラットホームがジョイスティックの割り込みに対応していないので、 正しいジョイスティックの入力を得るには、プログラム中で、すくなくとも1フレームにつき1回は 入力を監視(ポーリング)されなければならない。 ジョイスティックの初期化 int install_joystick(int type); ジョイスティックの初期化と、中心位置を調節する。 ジョイスティック関連の関数を呼び出す前に必ず初期化を行う。 通常パラメータ int type は JOY_TYPE_AUTODETECT を指定する。 textout_centre_ex(screen, font,返値: 0 成功 ジョイスティックの使用を終了 void remove_joystick(); ジョイスティックの使用を終了する。これは allegro_exit()が自動的に行うので、呼び出す必要はない。 ジョイスティックのポーリング int poll_joystick(); ジョイスティックには割り込み機能が備わっていない。 そのため、ジョイスティックからの入力を調べるにはこの関数をそのつど呼び出さなければいけない。 コードの例:返値: 0 成功 マイナス 失敗 接続しているジョイスティックの数 extern int num_joysticks; グローバル変数。 有効なジョイスティックの番号が格納されている。 現在サポートされているドライバーは4つまで認識する。 ジョイスティックの情報 extern JOYSTICK_INFO joy[n]; ジョイスティックの情報が格納されているグローバル配列 この内容は、poll_joystick() 関数が呼ばれるたびに更新される。 はじめは、num_joysticks と同じ値しか入っていない。 typedef struct JOYSTICK_INFOint flags;が返す値 JOYFLAG_DIGITAL - 現在提供されているコントローラはデジタル入力モードである。 ボタン情報。 typedef struct JOYSTICK_BUTTON_INFO機能がどのボタンに割り当てられるか表示したければ、これらの情報が利用できる。 各ジョイスティックに備わっている、1つまたは複数のスティック入力の変化や、指定位置にあるかコントロールする事ができる。 スティック入力に関するストラクチャはこのようになっている。 typedef struct JOYSTICK_STICK_INFOひとつのジョイスティックは、複数の違ったスティック入力が提供されるかもしれないが、 安心してスティックの初期配列をメインのコントローラの方向性に委ねることができる。 スティックの初期位置やボタン割り当てがストラクチャに格納されている。 typedef struct JOYSTICK_AXIS_INFOint 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;返値: 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:返値: 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); リフレッシュレートの参照(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; 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; システム描画領域の作成 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 の場合は。 /* マスクカラーを他の色に変更するサンプル. */ メモリの解放 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 専用の関数もある。 /* どんな色深度モード でもこれは緑色に見える */返値: 色深度と指定したパラメータに対応した 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;//画像 COMPILED_SPRITECOMPILED_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" のように書いても"ん" と表示できます。 システムフォント・オブジェクト 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ポリゴン 関数となっている。 メリット デメリット 参考: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 typedef struct 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[] 頂点ストラクチャの配列
三角形のポリゴン 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 — アフィン変換テクスチャ ポリゴン Zバッファについてサンプルコード:exzbuf.cZバッファは通常 POLYTYPE_* モードで動作するように設計されている。 int type OR集合「|」によって複数のモードを併用することが可能。 polygon3d(bmp, POLYTYPE_ATEX | POLYTYPE_ZBUF, tex, vc, vtx);サンプルコード exzbuf.c を参考にする。 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.c3Dシーンのためのメモリを割り当てる。 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返値: 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);このようにすると、同じ音楽が二重に再生され輪唱のようになる。 もし、再生途中で何かを変化させたいならadjust_sampleを利用する。 play_sample( spl,127, 127 , 1000 , 1);再生中の変更 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; mixer サウンドミキシング
ミキシングは 音を 混ぜたり加工したりして バランスよく聞こえるようにする作業のこと。
ただしAllegro の場合はこれらの関数は、主にMixer の状態や情報を取得するために使われるようだ。 実際のミキシング処理は Digital sample 関連の関数が受け持っている。 リサンプリングの品質を設定する void set_mixer_quality(int quality); mixerのリサンプリングの品質を設定する。この関数は allegro_init() の前に呼び出すこともできる。 int quality の値 0 - 16bit のバッファへ 8bit データを入れる 高速なミキシング外部設定ファイルを使った設定方法でも同じような設定が可能らしい。 (マニュアルのConfiguration routinesの Standard config variables にある Sound`quality' config を参照。) リサンプリングの品質設定を取得する int get_mixer_quality(void); Configuration routines の Sound`quality' config 設定 または、set_mixer_quality() 関数 によって設定された現在の ミキシング設定を取得する。 返値: 0 - 16bit のバッファへ 8bit データを入れる 高速なミキシング サンプリング周波数を取得 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が有効になっていない 音声データの数を得る 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 使用されるSAMPLEストラクチャの定数: int priority;サンプルデータを 渡す 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 一度だけ再生する。(ループフラグなしの場合はデフォルト)音量を調節する 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); 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 の 音の長さの単位は 現在の演奏位置(秒数)を得る 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返値: 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 に入るパラメータは... 録音の開始 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固有ものです。 ※今の所 Allegroでは、プレーンテキストを読込むための汎用的なAPIは用意されていません。必要な人は自作して下さい。(一応テキストファイル読み込みとして、 コンフィグファイルの読み込みはサポートされてはいます。) MacOSXでは、バンドル形式とそうでない場合で、ファイルの置き位置が違ってくることがあります。注意して下さい。 この章では、ディレクトリパス 操作系 と、PackFile形式の出入力の関数を紹介します。 ディレクトリパス 操作系実行プログラムのあるディレクトリ名を取得するvoid get_executable_name(char *buf, int size); 現在実行中のAllegro実行アプリケーション本体のある場所をフルパスで取得します。 「絶対パス名+実行ファイル名」 が char *buf に入ります。size は割り当てるメモリの量。 //パス名を格納 ファイル名を差し替える char *replace_filename(char *dest, const char *path, const char *filename, int size); 「絶対パス名+ファイル名」のファイル名の部分を差し替えます。 size バイトぶんが dest にコピーされます。 どんな使い方をするかは次の例を見てください。 //パス名を格納する変数相対パス指定ではファイルを読み込まない場合もあります。replace_filename関数と get_executable_name関数を使って絶対パス指定でファイルを読み込ませることができます。 注意:この方法を使った場合、日本語が混じったファイルパスに置くと ダメみたいです。この問題が改善されるまでは気を付けてください。 char name[200];その他のファイルパス操作系関数 ファイルが存在するか調べる int file_exists(const char *filename, int attrib, int *aret); 与えられたファイル名と属性(この章の最初を見ること)が一致するファイルが存在するかどうかを調べます。 また、int *aret が NULL以外が指定された場合には、一致したファイルにその属性を付加します。 例:返値: 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の内部処理のおかげで 、入力 と 結果 を同じ変数で済ませる事ができます。 例: パスからファイル名の部分を返す。 char *get_filename(const char *path); 指定したファイルパスから、ファイル名の部分を返します。DOSやWindows環境下では `\(バックスラッシュ)' と `/(スラッシュ)' がディレクトリの区切りとして認識されます。 ただし、`/(スラッシュ)'は、他のプラットフォームでも区切りとして確認されることがあります。 例:注意: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系システムの 「書き込み不可」のようなフラグをディレクトリ・エントリに対して行う。' attrib ' パラメータが関数に渡されたとき、マッチしたファイルがそこに含まれているとフラグが立つ。すなわち一致するべきファイルの属性は、指定したフラグを含むかもしれないが、しかし明記していないフラグを含んではいけない。従って、' FA_DIREC | FA_RDONLY ' を渡したら、正常なファイルと、ディレクトリが「読み取り専用」でなければならない。しかし、隠しファイルではないファイルとディレクトリである。 もし、'FA_ARCH'フラグを渡した場合は、アーカイブ化されたファイルとされていないファイルが同時に含まれることになる。 ' attrib ' パラメータを使用する関数の一例: なお、これらの関数を使わずに、C標準ライブラリのファイル出入力関数を使って、 ファイルを読み込むことも可能。 関連: * Datafile routines サンプルコード: expackf.c PackFile ファイル出入力主にPACKFILE ストラクチャが対象ファイル読み込み PACKFILE *pack_fopen(const char *filename, const char *mode); 指定したモードに従ってファイルを読み込む。 ファイル出入力フラグ:これらの代わりに、 F_READを指定することもできる。 返値: PACKFILEストラクチャへのポインタ- 成功 NULL - 失敗 魔法のファイルネームについて。 "#" - #マーカーを使って「ファイル名.dat#パスまたはオブジェクトネーム」という形式のファイルパスを渡すと exdat 関数によって保存されたDAT形式の任意のデータを読み出す事ができる。DATファイルの階層指定にも対応している。 ' filename.dat#object_name 'また、もしそれから独立したオブジェクトを読み込もうと考えているなら、 オブジェクトごとに圧縮されるか、無圧縮の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 ストラクチャが対象。 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 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 RLEpcx ファイルですが、 オプジェクト のタイプは 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オブジェクトを 作って、そこから同じように指定するらしい。
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 という形で用いられることがある。 整数部 小数部例えばこのように書かれていた場合 /* 立方体の頂点座標。 行列関連の関数は 固定小数点型の値を扱う */は、次のようなことをしているのと同じ。 { fixed itofix(-32) , fixed itofix(-32) , fixed itofix(-32 ) },int型の数値だとこのようになる { -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 → radianextern 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 ) 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 -- 固定小数点用 typedef struct MATRIX_f -- 浮動小数点用 任意の点に行列を適用する 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クオータニオンは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()のように、球面線形補間による最短距離を通って回転する GUI routines Allegro GUI
(仮)
AllegroのGUI は、大きく2つの分野、ダイアログストラクチャとメニューストラクチャを扱う。 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 flags; - オブジェクトのステータスフラグ D_EXIT - このオブジェクトは クリックするとダイアログが閉じる。 int d1, d2; - あなたが使いたいと思ったものはなんでも。これには、コールバック関数へのポインタを指定したり、とにかく何でも指定できる。 サンプル、exgui.c から DIALOG ストラクチャの具体的な設定方法の例 the_dialog[] = というふうに 配列指定すると、いくつもオブジェクトを定義する事ができる。 DIALOG the_dialog[] =例えば、ボタンをクリックすると、それに関連するダイアログストラクチャの配列の に記述してあるポインタ(*dp, *dp2, *dp3)に従って、コールバック関数が呼ばれ処理が行われるという仕組みらしい。 コールバック関数については次のように関数を作成されるが、返値を適切に設定する必要がある。 /* *dp ポインタに 指定する コールバック関数*/ダイアログ マネージャへ返す変数。: D_O_K - 通常ステータスを返す。 メニューストラクチャ(構造体)についてtypedef struct MENU MENU submenu[] =MENUストラクチャ配列の最後も 必ず NULL データを置かなければならない。 ダイアログプロシージャを扱う関数各オブジェクトはダイアログプロシージャのポインタに格納された情報によってコントロールされる。 オブジェクトに関するアクションが必要な時はいつでもダイアログプロシージャが呼ばれる。 さもなければ、object_message() 関数を使って直接呼び出すことができる。ダイアログプロシージャを扱う関数のパラメータは次のようになっている。 int proc(int msg, DIALOG *d, int c); /* int (*proc)(void) に指定する コールバック関数*/↑のようなコールバック関数を機能ごとに用意する。 typedef struct DIALOG_PLAYERこの2つの構造体については、init_dialog() ,init_menu() 関数の説明をみる。 実行/* the_dialog[] の ダイアログを実行する */詳細については、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: 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_edit_proc を パスワード入力欄「*****」風にする: Password field with d_edit_proc ? メモ: ダイアログプロシージャに日本語変換処理を割り込めば、日本語も入力できるかもしれない、しかし入力のタイミングをどうするかが問題です。 |