ponpoko実験室
2.ステータス表示のレイアウトを変更してみる
今回は余り深いところまで掘り下げずに画面レイアウトのスクリプト中心に延べようと思います。
●プレイヤーのステータス情報
まずプレイヤーのステータスについて簡単な説明をします。プレイヤーのステータス(体力、選択中の武器、及び弾薬等)は以下の配列に格納されています(entはプレイヤーのentityであるedict_t型構造体)。
ent->client->ps.stats[n]
そして上記のnに以下の値が対応しています。
// player_state->stats[] indexes
#define STAT_HEALTH_ICON 0 //体力アイコンのimage index番号
#define STAT_HEALTH 1 //体力値
#define STAT_AMMO_ICON 2 //弾薬アイコンのimage index番号
#define STAT_AMMO 3 //弾薬数
#define STAT_ARMOR_ICON 4 //アーマーアイコンのimage index番号
#define STAT_ARMOR 5 //アーマーの値
#define STAT_SELECTED_ICON 6 //アイテム選択アイコンのimage index番号
#define STAT_PICKUP_ICON 7 //拾得アイテムアイコンのimage index番号
#define STAT_PICKUP_STRING 8 //拾得アイテムの名前(文字列)
#define STAT_TIMER_ICON 9 //タイマーアイコン(Quadその他時間限定アイテム)のimage index番号
#define STAT_TIMER 10 //タイマーの値
#define STAT_HELPICON 11 //ヘルプアイコンのimage index番号
#define STAT_SELECTED_ITEM 12 //選択中のアイテム
#define STAT_LAYOUTS 13 //下位2ビットのオンオフで2枚のレイアウト画面の表示選択
#define STAT_FRAGS 14 //デスマッチで獲得したFRAGの数
#define STAT_FLASHES 15 //毎frameごとに更新されており、下位第1ビットで体力ダメージ、
//下位第2ビットでアーマーダメージ、それぞれのバックグラウンド
//フラッシュ処理指定
元のソースではステータスの最大数は32個になっています。まだまだ余ってますね。それに最大数というのも変更してしまって良いような...これはまた別の機会にしたいと思います。
で、今必要なのは0〜nの配列番号に対応する各役割(ステータスindex"n"と呼ぶことにします)であってどのような経緯で各配列へ値が代入されるのか等ということは考える必要は無し。
●レイアウト用スクリプトの記述
次に実際に画面のレイアウト変更について。画面のレイアウト設定はレイアウト用のスクリプトを記述することで実現することが分かりました。
そのスクリプトが記述されている場所はg_spawn.cファイル中でsingle_statusbarへ文字列が代入されている部分です(シングルプレイ用画面レイアウト)。
以下に一行ずつ説明をコメント文へ記述してあるので一通り見たらどのような意味があるのか詳細を見てください。
char *single_statusbar =
"yb -24 " //画面下から上へ24ドットにy座標を指定
// health
"xv 0 " //320*240モードで画面の左端にあたる部分へx座標を指定
"hnum " //体力値を表すレイアウト変数hnumの値を表示(注)
"xv 50 " //320*240モードで画面の左端にあたる部分から右へ50ドットにx座標を指定
"pic 0 " //体力アイコンを表示
// ammo
"if 2 " //ステータスindex2の内容が0以外の時
" xv 100 " //320*240モードで画面の左端にあたる部分から右へ100ドットにx座標を指定
" anum " //弾薬数を表すレイアウト変数anumの値を表示(注)
" xv 150 " //320*240モードで画面の左端にあたる部分から右へ150ドットにx座標を指定
" pic 2 " //弾薬アイコンを表示
"endif " //条件処理ここまで
// armor
"if 4 " //ステータスindex4の内容が0以外の時
" xv 200 " //320*240モードで画面の左端にあたる部分から右へ200ドットにx座標を指定
" rnum " //アーマー値を表すレイアウト変数rnumの値を表示(注)
" xv 250 " //320*240モードで画面の左端にあたる部分から右へ250ドットにx座標を指定
" pic 4 " //アーマーアイコンを表示
"endif " //条件処理ここまで
// selected item
"if 6 " //ステータスindex6の内容が0以外の時
" xv 296 " //320*240モードで画面の左端にあたる部分から右へ296ドットにx座標を指定
" pic 6 " //アイテム選択アイコンを表示
"endif " //条件処理ここまで
"yb -50 " //画面下から上へ50ドット地点にy座標を指定
// picked up item
"if 7 " //ステータスindex7の内容が0以外の時
" xv 0 " //320*240モードで画面の左端にあたる部分へx座標を指定
" pic 7 " //拾得アイテムアイコンを表示
" xv 26 " //320*240モードで画面の左端にあたる部分から右へ26ドットにx座標を指定
" yb -42 " //画面下から上へ42ドット地点にy座標を指定
" stat_string 8 " //ステータスindex8から拾得アイテム名(文字列)を表示
" yb -50 " //画面下から上へ50ドット地点にy座標を指定
"endif " //条件処理ここまで
// timer
"if 9 " //ステータスindex9の内容が0以外の時
" xv 262 " //320*240モードで画面の左端にあたる部分から右へ262ドットにx座標を指定
" num 2 10 " //2桁幅でタイマー値(ステータスindex10)を表示
" xv 296 " //320*240モードで画面の左端にあたる部分から右へ296ドットにx座標を指定
" pic 9 " //タイマーアイコンを表示
"endif " //条件処理ここまで
// help / weapon icon
"if 11 " //ステータスindex11の内容が0以外の時
" xv 148 " //320*240モードで画面の左端にあたる部分から右へ148ドットにx座標を指定
" pic 11 " //ヘルプアイコンの表示
"endif " //条件処理ここまで
;
スクリプトの詳細
上では読みやすいようにスクリプトは1処理ごとに行を区切っていますが、処理と処理の間にスペースさえ入って入ればよいので
char *single_statusbar = "yb -24 xv 0 hnum xv 50......
と書いても何ら問題はありません。以下にスクリプトの詳細を示します。
各パラメータの意味
< stat > ステータスindexの番号
< name > レイアウト変数名
< value > 数値を意味します
< string > 文字列を意味します
< fieldwidth > 桁の幅(数値)
< picname > イメージ名、picsディレクトリ内のファイルを拡張子無しで示す
カーソル位置の指定
座標値はx座標は右方向が正、y座標は下方向が正とします。
xl < value > 画面左端を基準としたx座標を指定
xr < value > 画面右端を基準としたx座標を指定
yb < value > 画面下端を基準としたy座標を指定
yt < value > 画面上端を基準としたy座標を指定
xv < value > 320*240モードでの画面左端を基準としたx座標を指定
yv < value > 320*240モードでの画面上端を基準としたy座標を指定
描画
statpic < name > 指定されたレイアウト変数の内容を表示
num < fieldwidth > < stat > ステータスindex< stat >の値を指定された桁数で表示
pic < stat > ステータスindex< stat >に指定されているアイコン(イメージ)を表示する
picn < picname > < picname >で指定したアイコン(イメージ)を表示
string < string > < string >で記した文字列を表示
cstring < string > < string >で記した文字列を水平位置の中心へ表示
string2 < string > < string >で記した文字列を緑色で(チャットメッセージのフォント色)表示
cstring2 < string > < string >で記した文字列を水平位置の中心へ表示
stat_string < stat > ステータスindex< stat >に割り当てられた文字列を表示
条件式
if < stat > ステータスindex< stat >の値が0以外ならばendifまでの処理を行う
ifeq < stat > < value > ステータスindex< stat >の持つ値と< value >の値が等しければendifまでの処理を行う
ifbit < stat > < value > ビット判定?詳細は不明
endif 条件処理の終端
string系命令では文字列の両端をダブルクォーテーションで囲むことでスペースの混在する文字列も表示することができます。
例えばNIKUMAN TABETAI Death!と表示させたいならスクリプト中へ
"string \"NIKUMAN TABETAI Death!\" "
と記述し、sprintfを使って\に続く特殊文字の記述を実際のコードへ置き換えればよいのです。
sprintf(single_statusbar,single_statusbar);
この方法を使えば改行\nも可能でした。
さっき示したsingle_statusbarへの代入文中、コメント文の(注)で示した部分に気づいた人もいると思います。特殊な存在である「レイアウト変数」はスクリプト中へそのまま書き入れればステータスindexの値を表示するということは理解できるのですが、存在理由が今一つはっきりしません。num命令で同様の処理ができるからです(桁数を指定しなければならない部分のみ異なる)。
まあ、レイアウト変数名が分かっているステータスindexについてはレイアウト変数を使って不明な物はnum命令を使ってれば今のところ問題ないでしょう。
g_spawn.cファイル中でsingle_statusbarの代入部分の後方にdm_statusbarの代入文(デスマッチ用画面レイアウト)もあるのでいじってみてください。
このスクリプトがconfigstringでステータスバーのindexへ渡されてうんたらかんたらという話はまだどうでもいいです。今はとにかくいじれ!
e-mail:ponpoko@axcx.com