|
|
|
|
|
これまで三回に渡って、主にプログラムの高速化技術について話してきました。それは非力なマシンでもできるだけユーザに快適にプレイしてもらうためでした。ご存じの通り、コンピュータ関連技術は驚くべき速度で発展を遂げ、アマランスII発売の頃にはV30-CPU搭載機よりもi80286-CPU搭載機の方が主流となっていました。これらの機種で前作アマランスをノーウエイトモードでプレイすると、ゲームに支障をきたすほど高速になります。 |
|
このような背景もあり、アマランスIIではさらなるの表現力の向上を目指し、16色対応・80286-CPU搭載機推奨という形で作り始めたのです。ちなみに前作アマランスが16色対応ではなく8色モードだったかというと、PC-9801VM/VFが16色ボードオプションだったからです。VX以降の機種で標準搭載となりました。また、V30-CPU搭載機を対象外としたかというとそうではありません。快適とはいえませんが、十分にプレイ可能な速度になるよう配慮しながら高速化しています。 |
|
|
|
多機能8方向スクロール |
|
|
|
同時発色数が16色と倍になったことで、前作に比べても表現力がグッと向上しています。また、フィールド上にNPC以外にも、敵キャラクタやパーティーメンバーなども表示されるようになったため、賑やかな雰囲気になっています。横に流れる川はもちろんアニメーションしています。 |
スクロールに関しては前作と決定的に異なる部分があります。それは「フリップ」を使用している点です。フリップに関しては前回説明したとおり、2枚のV-RAMを垂直帰線期間に入るタイミングで切り替えることによってちらつきを一切出さない手法です。余談ですが、この手法を採るとマップフィールドをデザインするグラフィッカが気をつけなければならないことがあります。それは「同じPCGをひとつおきに配置すると高速化する」ということです。前作やビートバイスでは同一のPCGをスクロール方向に並べると書き換えが不要になり高速化しましたが、フリップを使うと二枚のV-RAMがかわりばんこに書き換えられることになるため、「ひとつおき」になるのです。
また、16色対応になったことで変化した点もあります。それは同時に表示できるPCGの個数です。前作では256個使えましたが、アマランスIIでは204個に制限されています。これは16色になったことでデータサイズが大きくなったことによるものです。当然、キャラクタのデータサイズも大きくなるので、こちらも数の制約がキツくなっています。このあたりはグラフィッカの努力によって補われています。 |
|
ちなみに、PC-9801シリーズでフリップを使うということは、常に描画は裏V-RAMに対して行われることになります。V-RAMのアクセスが低速であることは前回書きました。ここで気になるのは、「裏V-RAMは画面に表示されていないメモリ」であるという点です。V-RAMが低速な主な理由は、画面に表示するためにグラフィックコントローラからもアクセスされるからでした。では、少なくともアクセスする時点で表示されていない裏V-RAMのメモリアクセス速度はどうなるのでしょう?実は表V-RAMよりもずっと高速なのです。ただし、メインメモリに比べるとやはり低速ですが。これにより、フリップは意外と高速動作させることができるのです。 |
|
さて、フリップを使うことで速度的には若干低下しましたが、その分だけプログラムをすっきりと簡略化することができ、機能面が向上しています。二重スクロールのスクロールステップを任意に設定できたり、奥のスクロールプレーンもアニメーションさせられたりといった部分です。
それ以外にもノウハウの蓄積が、より高機能・高効率なスクロールを実現する助けになっています。以下はアマランスIIのスクロールシステム用マップデータの属性ビットを示しています。
0〜7・PCG番号(0〜203)
8・透過指定(背景が透ける)
9・アニメーション指定(アニメーションする)
10・下半身非表示指定(下半身が表示されない)
11・完全非通過指定(絶対に通過できない)
12・非通過指定(キャラクタが通過できない)
13・マスク指定(合成されるキャラクタにマスクがかけられる)
14・全体マスクPCG指定(1PCG全体がマスクON状態である)
15・イベント発生指定(この場所でイベントが発生する)
|
|
二重スクロールによる奥行き感の強調。小高い丘の上から海を臨む状態。さらに遠くに見える海面がアニメーションしている。16ドット単位のスクロールでも十分に雰囲気が伝わる。 |
8は二重スクロール時に奥のプレーンが透過する部分に立てます。10は浅瀬や草むらに入ったとき、キャラクタの身体が沈んだように見せるときに立てます。11と12は障害物指定ですが、壁抜け呪術が存在する関係上、2ビット必要になります。14は合成処理が不要であることを明示しており、速度向上に寄与します。15はその場所で何らかのイベントが発生することを示し、このビットが立っているPCGに主人公キャラクタが重なった場合のみ、イベントのチェックを行います。これもスクロール速度向上のために設けられているビットです。
これらのビットの組み合わせで、アマランスIIのスクロールシステムは高い表現力と高速性の両方を実現しています。
|
|
これは余談になりますが、アマランスIIのスクロールシステムは当初8ドット単位のスクロールにも対応していました。しかし、よりスムースなスクロールを実現できますが、80286搭載マシンでも十分な速度とはいえず、8ドット単位で動くのは戦闘モードの各キャラクタのみということになっています。実際にやってみて感じたのですが、スクロールはスムースであればあるほど良いというわけではないようです。フィールドの広さやイベントの密度との兼ね合いもあり、プレイヤーが「快適」と感じるスクロールステップと速度があるように感じました。人は二本の足で歩く生物ですから、一歩踏み出すごとにカクッカクッとスクロールしても違和感を覚えにくいのかもしれません。コンシューマ機用のスクロール型ARPGソフトのように、ドット単位でスムースにスクロールするフィールドでキャラクタがテクテクとアニメーションすると、地面を滑っているように見えたりします。慣れもあるのでしょうが、私などはこちらのほうが違和感を感じるから不思議なものです。(もちろん歩くアニメーションのコマ数が多ければ違和感は感じませんが。) |
|
|
|
クリッピング |
|
クリッピングは3Dゲームの世界で非常に重要な処理です。プレイヤーの視界以外の部分をカットする処理のことをいいます。これは2Dの世界でも同様に重要な処理です。フィールドに大きなキャラクタが出現した場合、そのキャラクタの一部がフィールドエリアの外にはみ出すことがあります。何もしないとフィールド画面以外のステータス表示域や飾り枠などが上書きされて壊れてしまいますから、フィールド画面以外の部分でないかチェックしながら表示しなければなりません。これは使用頻度の高い重要な処理ですから、ゲームにおいては効率よく高速化する必要があります。 |
|
アマランスIIのクリッピング処理は非常に高速です。一般的なクリッピングアルゴリズムではなく、早い時期に場合分けを実行し、専用ルーチンで描画を行っています。ボスキャラをコマ落ちなく動かし、ザコキャラがわらわら出てきてもストレスを感じないようにと考えたのですが、今にして思えば、ここまでやることはなかったかな・・・・とも思います(^_^;)。 |
|
|
|
スクリプト制御 |
|
アクション型RPGのプログラムは多くの複雑な動作を要求されます。その全てをメインプログラムに組み込むとなると、プログラマの負担が大変大きくなってしまいます。デバッグも大変ですし、二人以上で作業を分担するときも問題が発生しやすくなります。 |
|
|
|
アマランスIIでも前作同様、テキスト画面を利用したアニメーション合成が随所で使われています。この朝日街道(ちょうじつかいどう)での激しい雨のフィールドシーンもその中のひとつ。他にも吹雪や砂嵐などがあります。 |
そこで考えられたのがスクリプトによる制御・実行です。スクリプトは「台本」とか「手書き」といった意味の言葉ですが、メインのプログラマはこの「台本」通りに振る舞う「役者」のみをプログラムするのです。台本の方は文法と決まりさえ憶えれば誰が書いてもよいわけですから、作業の分散が効率よく行えるようになります。また、デバッグも非常に簡単になります。テスト用の役者プログラムさえ用意すれば、台本を書いている各自が自由に簡単に動作チェックできます。これはアマランスIIに始まったことではななく、リボルティーIIの頃から使用されているテクニックです。 |
|
アマランスIIでは、イベントの実行/アニメーション(ビジュアル)シーンの実行/キャラクタの動きがスクリプトによって実現されています。下の2本のリストは実際のイベント・スクリプトです。Sample1は気候神ラウネンを騙った中ボスのキジャキとの戦闘に勝利した際に発動されるイベントを記述したもの、Sample2はゲハイムヴェーク(地下通路)で中ボスの光のラオトスの待ち伏せに突入するイベントを記述したもので、両方とも実際の製品に使用されたものです。 |
|
|
|
|
|
|
|
|
|
|
|
|
Sample1 |
|
|
|
|
|
001 |
;======================================== |
|
|
002 |
; 偽ラウネン(キジャキ)断末魔 |
|
|
003 |
;======================================== |
|
|
004 |
EVSTART EV130 |
|
; EV130開始ラベル |
|
|
|
|
|
|
|
|
|
005 |
|
NOFIGHT |
|
; 戦闘モードから抜ける |
|
|
006 |
|
DELAY |
500 |
; 5秒待ち |
|
|
007 |
|
SE |
18, 0, 1 |
; 効果音18を鳴らす |
|
|
008 |
|
BGMCHANGE |
21 |
; BGMを21に変更 |
|
|
009 |
|
REMAKE |
4, 0 |
; 奥の間への通路出現 |
|
|
010 |
|
SPEAK |
338 |
; 【おや?………これは………】 |
|
|
011 |
|
MESSAGE |
9, 16, 22 |
; 「クロームの鍵を手にいれた」 |
|
|
012 |
|
ITEMGET |
ITEM, 21 + 10 |
; 『クロームの鍵』入手 |
|
|
013 |
|
SPEAK |
339 |
; 【クリーデン、これが何か………】 |
|
|
014 |
|
SPEAK |
340 |
; 【いや、はじめて見る………】 |
|
|
015 |
|
FIN |
|
; イベント終了 |
|
|
|
|
|
|
|
|
|
016 |
EVEND EV130 |
|
; EV130終了ラベル |
|
|
|
|
|
|
|
|
|
Sample2 |
|
|
|
|
|
001 |
;======================================== |
|
|
002 |
; ラオトス出現 |
|
|
003 |
;======================================== |
|
|
004 |
EVSTART EV230 |
|
|
|
|
|
|
|
|
|
|
|
005 |
|
LDB@ |
SYSC |
; システムカウンタをバイト変数にロード |
|
|
006 |
|
IFB@NEI |
52, #END |
; バイト変数が52以外なら#ENDへ飛ぶ |
|
|
007 |
|
EQUIPCHK |
ITEM, 0 |
; アイテムNo.0(D−リヒト)の装備有無をバイト |
|
|
008 |
|
IFB@NEI |
-1, #PASS |
; 変数に入れ、無しなら#PASSへ飛ぶ |
|
|
009 |
|
ON |
101 |
; F101 =「Dリヒト非装備フラグ」= ON |
|
|
010 |
|
SPEAK |
1538 |
; 【行くぞ!二人とも………】 |
|
|
011 |
|
REMAKE |
55, 11 |
; <入り口閉鎖> |
|
|
012 |
|
GOTO |
#FIG |
; #FIGへ飛ぶ |
|
|
013 |
#PASS: |
|
|
|
|
014 |
|
SPEAK |
1533 |
; 【きゃっ!!】 |
|
|
015 |
|
MESSAGE |
10, 16, 149 |
; 「突然、ディンの服が引き裂かれた」 |
|
|
016 |
|
SPEAK |
1534 |
; 【くそっ! 見えない敵か?!】 |
|
|
017 |
|
MOVE |
2, 2 |
; パーティーを下にスクロールと共に一歩移動 |
|
|
018 |
#FIG: |
|
|
|
|
|
019 |
|
BGMCHANGE |
17 |
; BGMを17に変更 |
|
|
020 |
|
FIGHT |
15 |
; <戦闘No.15発生> |
|
|
021 |
#END: |
FIN |
|
; イベント終了 |
|
|
|
|
|
|
|
|
|
022 |
EVEND EV230 |
|
|
|
|
|
|
|
|
簡単にリストを解説していきます。Sample1を見てください。全体を見ておわかりのように、セミコロン以降がコメントで、一行に一命令を書くようになっています。
まず、イベントのラベル(識別子)はEVSTART と EVEND で本文スクリプトを挟んで記述します。ここでは"EV230"という名前になっています。NOFIGHTは戦闘画面からマップ移動画面に切り替えるコマンドです。006〜008行は特に説明は不要でしょう。その次の REMAKEはマップの一部を「貼り替える」コマンドです。次回のツールの話にも出てくるのですが、あらかじめ切り取っておいたマップのパーツを指定したマップに重ねて貼り付けるのです。パラメータは2つの整数ですが、ひとつが対象となるマップの番号で、もうひとつが貼り込むパーツの番号です。貼り付ける座標はパーツデータに入っています。これによって、あるイベント内で遠く離れた場所のマップを事前に変更することもできるわけです。
SPEAKコマンドは顔CG付き会話メッセージを表示します。顔CGやそれの位置、メッセージなどは別データとして定義しておき、その番号を指定するようになっています。次のMESSAGEコマンドは画面の任意の場所にメッセージを表示し、キー入力を待ちます。ITEMGETはその名の通り、指定したIDのアイテムをパーティーの所有物リストに加えます。そしてFINがイベントの実行の終了を伝えます。 |
|
|
|
このようなオーバーラップ・ビジュアルシーンも先のイベントスクリプトによるもの。でも、オープニングやエンディング、次回予告などの全画面モードのイベントは後述のアニメーションドライバによるものです。 |
Sample2はイベントの流れを制御している例です。右のコメントを見てもえらえるとだいたいわかると思います。LDB@はバイト型のローカル変数に式で示される値を代入する命令で、この例ではSYSCという名前のシステム変数の値を代入しています。SYSCはゲームのメイン進行カウンタで、ストーリーがどの辺りまで進んでいるかを表します。次のIFB@NEI命令でその値が52か否かを比較し、偽であれば#ENDへ飛びます。つまりここでは「システムカウンタが52以外であれば何もしない」となります。次のEQUIPCHKはIDが0であるアイテムを誰が装備しているかをバイト変数に入れる命令で、誰も装備していないと−1を返すようになっています。次行でそれをチェックし、誰かが装備していたら#PASSへ飛ぶようになっています。ここでイベントの内容を分岐させているわけです。誰も装備していないと次のONコマンド以降が実行され、フラグNo.101がONになり、戦闘前会話が行われ、後戻りができないようにマップの入り口がふさがり、戦闘シーンNo.15に突入します。#PASS以降では別の戦闘前会話が行われ、パーティーキャラクタがスクロールと共に一歩前に移動してから同じ戦闘シーンに入ります。ちなみにフラグNo.101は後述の戦闘スクリプトで参照されます。 |
|
このようにアマランスII専用の立派(?)なプログラム言語になっています。このスクリプトソースを変換してオブジェクト(中間コード)とし、これをメインプログラム中のイベントドライバが実行します。ちなみにアマランスIIでは変換にマクロアセンブラ(SLR社製OPTASM)を流用しており、上のコマンドはすべてアセンブラマクロとして定義されています。エルステディア以降になると専用のコンパイラを使うようになり、Windows版アマランスともなるとC言語ライクな高度な言語体系になっています。この詳細に関してはまた別の機会にお話しすることにしましょう。 |
|
|
|
さて、今度はキャラクタの制御に関するスクリプトです。下の2本のリストは実際のキャラクタ制御スクリプトです。Sample3は戦闘シーンのとあるザコキャラの制御スクリプト、Sample4は同じく戦闘シーンの中ボスの制御スクリプトの一部です。これらもイベントスクリプト同様、アセンブラのマクロ機能を利用して変換されてから、メインプログラムのキャラクタ制御ルーチンで解釈・実行されます。 |
|
|
|
|
|
|
|
|
|
|
|
|
Sample3 |
|
|
|
|
|
001 |
;======================================== |
|
|
002 |
; ザコ敵キャラクタ(ゴブリン) |
|
|
003 |
;======================================== |
|
|
004 |
SPEED |
= |
3 |
|
|
|
|
|
|
|
|
|
005 |
E5 |
PROC |
NEAR |
|
|
|
006 |
|
FCSET |
#S |
; 初期処理 |
|
|
007 |
|
IDSET |
2 |
; 敵のIDは0-127の間。128以上は町人を表す |
|
|
008 |
|
LVSET |
0 |
; 敵のレベル(Lv)設定 |
|
|
009 |
|
STSET |
200 |
; 体力(St)設定 |
|
|
010 |
|
APDPSET |
33, 10 |
; 攻撃力(Ap)/防御力(Dp)設定 |
|
|
011 |
|
SIZESET |
4, 4 |
; 当たり判定用のサイズ。始点は左上固定 |
|
|
012 |
|
FWSET |
2 |
; 足元の幅。当たり判定用。スライムなどはY幅と同じ値になる |
|
|
013 |
|
GELTSET |
8 |
; 所持金設定 |
|
|
014 |
|
POSSET |
34, 12 |
; 初期発生座標 |
|
|
015 |
|
DIRSET |
5 |
; 初期進行方向設定(キャラクタのパターン決定用) |
|
|
016 |
|
APS_D |
0, 1, 0, 2 |
; アニメーションパターンテーブル |
|
|
017 |
|
APS_R |
3, 4, 3, 5 |
; | |
|
|
018 |
|
APS_U |
6, 7, 6, 8 |
; | |
|
|
019 |
|
APS_L |
9, 10, 9, 11 |
; V |
|
|
020 |
|
CLET |
V0, SPEED |
; V0 = 歩行スピードカウンタ |
|
|
021 |
|
CLET |
V3, 0 |
; リアン追尾指定 |
|
|
022 |
#S: |
|
|
|
|
|
023 |
|
DEAD |
#E |
; 死亡判定 |
|
|
024 |
|
CSUB |
V0, 1 |
; 移動速度制御 |
|
|
025 |
|
FLAGNJ |
#E |
; V |
|
|
026 |
|
CLET |
V0, SPEED |
; V0再設定 |
|
|
|
|
|
|
|
|
|
027 |
|
FDISTCHK |
V3, 20 |
; 相対距離チェック |
|
|
028 |
|
FLAGJMP |
#N |
; 20以上ならば追尾しない |
|
|
029 |
|
CLET |
V2, 0 |
; リアン追尾 |
|
|
030 |
|
CHASE |
V2 |
; V |
|
|
031 |
#N: |
|
|
|
|
|
032 |
|
ADVANCE |
|
;1歩進む |
|
|
033 |
|
OBSCHK |
|
; 進行方向の障害物チェック |
|
|
034 |
|
FLAGNJ |
#P |
; V |
|
|
035 |
|
RAND |
V1, 8 |
; 進行方向乱数指定 |
|
|
036 |
|
CADD |
V1, 1 |
; | |
|
|
037 |
|
VLET |
V44, V1 |
; V |
|
|
038 |
#P: |
|
|
|
|
|
039 |
|
ANIME |
|
; キャラクタパターンをアニメーションTBLに従って変更 |
|
|
040 |
#E: |
|
|
|
|
|
041 |
|
STDISP |
|
; ;敵のスタミナ表示 |
|
|
042 |
|
CPUT |
|
; キャラクタのPUT |
|
|
043 |
|
CEND |
|
; 終了 |
|
|
|
|
|
|
|
|
|
044 |
E5 |
ENDP |
|
|
|
|
|
|
|
|
|
|
|
Sample4 |
|
|
|
|
|
|
;======================================== |
|
|
|
; 中ボス(キジャキ) |
|
|
|
;======================================== |
|
|
|
; V0 (B):動作速度制御カウンタ
; V2 (B):追尾IDカウンタ
; V3 (B):ミサイルID番号(ミサイルが参照する)
; V4 (B):追尾キャラクタID番号(ミサイルが参照する)
; V10(B):追尾キャラクタID番号
; V12(W):追尾IDのX座標
; V14(W):追尾IDのY座標
; V16(W):ミサイル発生X座標
; V18(W):ミサイル発生Y座標
; V20(B):ミサイルID番号
; V22(B):ミサイル進行方向フラグ
; V24(B):ミサイル進行方向フラグ(ミサイルが参照する)
; V26(W):テンポラリ |
|
|
|
;======================================== |
|
|
|
QUIJAKI |
START |
|
|
|
|
|
|
・
・
・
|
|
|
|
|
|
#LP: |
CMOD |
V2,4 |
;追尾対象ラップアラウンド防止 |
|
|
|
|
I3JMP |
V2,#DINCB,#LIANN,#CRIDEN ;追尾対象に従って分岐 |
|
|
|
#LIANN: |
VINC |
V2 |
;追尾対象更新 |
|
|
|
|
CLET |
V10,0 |
|
|
|
|
|
JUMP |
#GOGO |
|
|
|
|
#DINCB: |
CLET |
V10,1 |
;ディンの存在チェック |
|
|
|
|
JUMP |
#GO |
|
|
|
|
#CRIDEN: |
CLET |
V10,2 |
;クリーデンの存在チェック |
|
|
|
#GO: |
VINC |
V2 |
;追尾対象更新 |
|
|
|
|
BANCHK |
V10 |
;追尾対象存在チェック |
|
|
|
|
FLAGNJ |
#LP |
; 存在しない |
|
|
|
#GOGO: |
RAND |
V30,255 |
;RATE/255の確率でマジックミサイル発射 |
|
|
|
|
CCAJMP |
V30,RATE,#E |
|
|
|
|
|
CLET |
V20,MISSILE_BASE; マジックミサイルのDCTを探す |
|
|
|
#CHKLP: |
BANCHK |
V20 |
;DCTがあいているか? |
|
|
|
|
FLAGNJ |
#CHKEND |
; Yes! |
|
|
|
|
LOOPJMP |
V20,%MISSILE_BASE+MISSILENUM,#CHKLP |
|
|
|
|
JUMP |
#E |
;空きDCTがないのでマジックミサイルを発射しない |
|
|
|
|
|
|
|
|
|
|
#CHKEND: |
XWLD |
V10,V12,V56 |
;X座標取得 |
|
|
|
|
CWADD |
V12,2 |
; 目標位置補正(キャラクタ中心を目標とする) |
|
|
|
|
XWLD |
V10,V14,V58 |
;Y座標取得 |
|
|
|
|
CWADD |
V14,2 |
; 目標位置補正(キャラクタ中心を目標とする) |
|
|
|
|
VWLET |
V16,V12 |
;発生X座標設定 |
|
|
|
|
CWLET |
V18,0 |
;発生Y座標設定 |
|
|
|
|
CCAWJMP |
V12,%XWID-1,#LEFT ;左から発射 |
|
|
|
; 右半分からマジックミサイル発射 |
|
|
|
|
CLET |
V22,2 |
;左下に向かって進む |
|
|
|
|
VWADD |
V16,V14 |
|
|
|
|
|
CCBWJMP |
V16,%XWID*2,#SPAWN |
|
|
|
|
VWLET |
V18,V16 |
|
|
|
|
|
CWSUB |
V18,%XWID*2-1 |
|
|
|
|
CWLET |
V16,%XWID*2-1 |
|
|
|
|
JUMP |
#SPAWN |
|
|
|
|
; 左半分からマジックミサイル発射 |
|
|
|
#LEFT: |
CLET |
V22,1 |
;右下に向かって進む |
|
|
|
|
・
・
・
|
|
|
|
|
|
#E: |
STDISP |
|
;残り体力(ST)表示 |
|
|
|
#EE: |
CPUT |
|
;キャラクタのPUT |
|
|
|
|
CEND |
|
;終了 |
|
|
|
|
|
|
|
|
|
|
#EV: |
CPUT |
|
;キャラクタのPUT |
|
|
|
|
SE |
15 |
;中ボス死亡効果音発声 |
|
|
|
|
EVBORN |
130 |
;キジャキ断末魔イベント発生 |
|
|
|
|
GOTO |
#E |
|
|
|
|
|
|
|
|
|
|
|
QUIJAKI |
ENDP |
|
|
|
|
|
|
|
|
では、Sample3をごく簡単に説明していきましょう。まず、最初からラベル"#S:"までの間は全て初期設定です。行ごとのコメントを見てもらえれば、おおよその見当はつくと思います。6行目のFCSETという命令は、2回以上実行されたときに、パラメータのラベルに飛ぶという動作をします。これによって作業域の初期化などの処理を1回だけ実行するようにしています。パラメータ部に出てくるV0〜44という名前は、各キャラクタごとに使用できる変数を示しています。これらの変数は基本的に1バイトサイズですが、偶数値のものは1ワード(2バイト)サイズとしても使用できるようになっています。若い番号のものは意味が決まっていますが、そうでないものは自由に使用することができます。
このリストで制御される敵キャラクタは、プレイヤーキャラであるリアンが自分を中心に距離20以内にいると追いかけてくるという単純な動作をします(距離1は8×8ドットマス)。また、追尾中に障害物にぶつかったらランダムに進行方向を変えます。(コウモリなどの飛行キャラはこの処理が不要というわけです。) |
|
|
|
これは船上でのザコキャラ戦から撤退するところ。敵キャラはもちろん、実は味方キャラも同じスクリプトで制御されています。さらにはプレイヤーキャラも同じくスクリプト制御です。キー入力を変数に代入するコマンドを使います。 |
Sample4は非常に長いリストの一部を切り出したものです。複雑な攻撃を繰り出すボスキャラも、ザコキャラと同じスクリプトで制御します。パーティーのメンバーを識別したり、投擲攻撃をしたりしています。ちなみに、火の玉を投げたりビームを発射したりする攻撃はBORNという命令を使って、火の玉キャラやビームキャラを新しく発生させることで実現します。コメントに出てくる"DCT"とは、V0〜44までの変数を含む、キャラクタごとの設定/作業域を示すポインタテーブルを指します。当然ですが、仮にDCTが20あれば、同時に最大で20キャラクタ表示できることになります。そのためDCTに空きがあるか調べて、なければ新規発生処理を断念するようプログラムされています。
最後から3行目にEVBORNという命令があります。これは指定されたイベントを戦闘中に発生させる命令です。ここでは130番目のイベントを起動していますが、これは先のSample1のスクリプトで記述されたものです。 |
|
|
|
最後にアニメーション(ビジュアル)制御用スクリプトについても紹介しておきましょう。実はこのアニメーション制御スクリプトが最も歴史が古く、汎用性も高いものなのです。イベントやキャラクタ制御とは異なり、製品ごとに専用のものを作る必要がないからです。実際、このアニメーション実行に関しては、ソーススクリプトをコンパイルして出力されたオブジェクトを独立した専用の実行プログラム(AD.EXE)が読み込んで実行します。ビートバイスやアマランス1〜4などの店頭デモなどはすべてこのシステムで動いています。このアニメーション記述言語はFGAL(エフギャル)"Fuga General Animation Language"と呼ばれており、実行プログラムは「アニメーションドライバ」といいます。 |
|
では実際にFGALスクリプトがどのようなものかをお見せいたしましょう。下のリストSample5を見てください。これはアマランスのオープニングアニメーションを記述したスクリプトの一部です。アマランスIIのものがすぐに見つからなかったので前作のものを持ってきました。 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Sample5 |
|
|
|
|
|
|
|
|
|
|
|
|
001 |
;======================================== |
|
|
002 |
; Amaranth OPENING |
|
|
|
|
|
|
|
|
|
003 |
;======================================== |
|
|
004 |
; 初期設定 |
|
|
|
|
|
|
|
|
|
005 |
|
GRAPHOFF |
|
|
|
|
|
|
|
|
006 |
|
TEXTOFF |
|
|
|
|
|
|
|
|
007 |
|
SGCLR 0, 128 |
|
|
|
|
|
|
|
|
008 |
|
APALET[0,0,0,0] |
|
|
|
|
|
|
|
|
009 |
|
FADEOUT8 0 |
|
|
|
|
|
|
|
|
010 |
|
SCROLL 0 |
|
|
|
|
|
|
|
|
011 |
|
RESO 1 |
|
|
|
|
|
|
|
|
012 |
|
BANK 0,0 |
|
|
|
|
|
|
|
|
013 |
|
WIPE 0,0 |
|
|
|
|
|
|
|
|
014 |
; 使用変数 |
|
|
|
|
|
|
|
|
|
015 |
|
DEFINE CPU |
|
|
|
|
|
|
|
005 |
|
DEFINE A,D,F,G,N,T,W,X,Y,C1,C2,C3,C4,C5 |
|
|
006 |
; CPU チェック |
|
|
|
|
|
|
|
|
|
007 |
|
CPU = _506 |
|
|
|
|
|
|
|
|
008 |
; ここから開始 |
|
|
|
|
|
|
|
|
|
009 |
|
BANK 0,1 |
|
|
|
|
|
|
|
|
010 |
|
IF [_510 = 1] #HDLOAD00 |
|
|
|
|
|
|
011 |
|
EXPAND B:FT.CG 0 0 |
|
|
|
|
|
|
012 |
|
JUMP #CONT00 |
|
|
|
|
|
|
|
013 |
#HDLOAD00 |
|
|
|
|
|
|
|
|
|
014 |
|
EXPAND FT.CG 0 0 |
|
|
|
|
|
|
|
015 |
; JINGLE |
|
|
|
|
|
|
|
|
|
016 |
#CONT00 |
|
|
|
|
|
|
|
|
|
017 |
|
IF [_510 = 1] #HDLOAD0M |
|
|
|
|
|
018 |
|
MLOAD B:FGTTL.MD |
|
|
|
|
|
|
019 |
|
JUMP #CONT0M |
|
|
|
|
|
|
020 |
#HDLOAD0M |
|
|
|
|
|
|
|
|
021 |
|
MLOAD FGTTL.MD |
|
|
|
|
|
|
022 |
#CONT0M |
|
|
|
|
|
|
|
|
|
023 |
|
MUSIC 0,0 |
|
|
|
|
|
|
|
024 |
|
APALET [0,0,0,0][1,8,12,15] |
|
|
|
|
|
025 |
|
GET [0,0][80,80],C1,1 |
|
|
|
|
|
|
026 |
|
BANK 0,0 |
|
|
|
|
|
|
|
|
027 |
|
GRAPHON |
|
|
|
|
|
|
|
|
028 |
|
PUT [0,60],C1,1,$301,7 |
|
|
|
|
|
|
029 |
|
FREE C1 |
|
|
|
|
|
|
|
|
030 |
|
_509 = 0 |
|
|
|
|
|
|
|
|
031 |
#MUSWAIT0 |
|
|
|
|
|
|
|
|
|
032 |
|
WAIT 0 |
|
|
|
|
|
|
|
|
033 |
|
IF [_509 = 1] #SKIPDA |
|
|
|
|
|
|
034 |
|
IF [_508 <> 0] #MUSWAIT0 |
|
|
|
|
|
035 |
|
FADEOUT8 8 |
|
|
|
|
|
|
|
036 |
|
JUMP #START |
|
|
|
|
|
|
|
|
|
・
・
・
|
|
|
|
|
|
|
|
|
|
|
|
145 |
; 2秒で横線が上から下へ走る |
|
|
146 |
|
SWAIT 200 |
|
|
|
|
|
|
|
|
|
147 |
|
|
APALET [1,0,12,7] |
|
|
148 |
|
|
N = 0 |
|
|
|
|
|
|
|
|
149 |
|
|
LOOP 200 |
|
|
|
|
|
|
|
|
150 |
|
|
|
SWAIT 1 |
|
|
|
|
|
|
|
151 |
|
|
|
|
BOXF[0,N][639,N],1,0,0,0 |
|
|
152 |
|
|
|
|
BOXF[0,N-2][639,N-2],1,2,0,0 |
|
|
153 |
|
|
|
|
N = N+2 |
|
|
154 |
|
|
|
EWAIT 1 |
|
|
|
|
|
|
|
155 |
|
|
ENDLOOP |
|
|
|
|
|
|
|
|
156 |
|
|
BOXF[0,N-2][639,N-2],1,2,0,0 |
|
|
157 |
|
EWAIT 200 |
|
|
|
|
|
|
|
|
|
158 |
; 文字列,実際にスクロールインしてくる (表示含めて21秒) |
|
|
159 |
|
SWAIT 2100 |
|
|
|
|
|
|
|
|
|
160 |
|
|
N = 49536 |
|
|
|
|
|
|
|
161 |
|
|
SCROLL N |
|
|
|
|
|
|
|
162 |
|
|
Y = 0 |
|
|
|
|
|
|
|
163 |
|
|
IF [CPU = 1] #V30SCUP |
|
|
164 |
|
|
LOOP 400 |
|
|
|
|
|
|
|
|
165 |
|
|
|
SWAIT 4 |
|
|
|
|
|
|
|
166 |
|
|
|
|
BANK 0,1 |
|
|
|
|
167 |
|
|
|
|
GET[0,Y][80,1],C1,7 |
|
|
|
|
168 |
|
|
|
|
BANK 0,0 |
|
|
|
|
169 |
|
|
|
|
PUT[0,Y],C1,7,0,0 |
|
|
|
|
170 |
|
|
|
|
FREE C1 |
|
|
|
|
171 |
|
|
|
|
N = N+40 |
|
|
|
|
172 |
|
|
|
|
Y = Y+1 |
|
|
|
|
173 |
|
|
|
|
VSYNC |
|
|
|
|
174 |
|
|
|
|
SCROLL N |
|
|
|
|
175 |
|
|
|
EWAIT 4 |
|
|
|
|
|
|
|
176 |
|
|
ENDLOOP 400 |
|
|
|
|
|
|
|
177 |
|
|
JUMP #SCUPEND |
|
|
|
|
|
|
|
178 |
#V30SCUP |
|
|
|
|
|
|
|
|
|
|
|
|
|
・
・
・
|
|
|
|
|
|
|
|
|
|
|
|
1072 |
; ローゼをイン |
|
|
1073 |
|
BANK 1,0 |
|
|
|
|
|
|
|
|
|
1074 |
|
GRAPHON |
|
|
|
|
|
|
|
|
|
1075 |
|
FADEIN8 10[0,0,0][15,0,0][0,15,0][10,15,11][0,0,15][15,0,15][0,15,15][15,15,15] |
|
|
1076 |
|
BOXF[0,0][639,20],7,2,0,0 |
|
|
|
1077 |
|
PENV[0,0],6,4,400,80,0 |
|
|
|
1078 |
|
TEXT 不思議な男の人……まるで風の遣いのよう… |
|
|
|
1079 |
|
PRINTS |
|
|
|
1080 |
|
GET[0,0],[44,16],C1,6 |
|
|
|
1081 |
|
X = 2 |
|
|
|
|
|
・
・
・
|
|
|
|
|
|
|
|
|
|
|
|
1143 |
|
END |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ほとんどコメントが無いのでわかりにくいかもしれませんが、グラフィック関連の命令がずらりと並んでいます。基本的にはBASIC風の言語体系になっています。普段はプログラミングをしないグラフィック担当者らの腰が引けないように、直感的なプログラムができるように配慮(?)してあります。
アニメーション制作者はグラフィックパターンを準備し、それらを表示するスクリプトを記述します。テキストファイルとしてセーブしたスクリプトを専用のコンパイラ(FGALコンパイラ)にかけます。このコンパイラは1パスで処理するようになっており、非常に高速です。これもカット&トライ(試行錯誤)をしやすくするためです。あとはコンパイラの吐いたオブジェクトファイル名を引数に指定してアニメーションドライバを起動すれば、スクリプトに従ったアニメーションが画面に表示されます。 |
|
|
|
こちらはアマランスIIのオープニングの1シーン。文字がくるくるとアニメーションしながら表示されたりする部分もすべてアニメーション記述言語“FGAL”で記述されています。 |
では特徴的な部分を解説していきます。まず変数ですが、自由な名前を付けることができ、事前にDEFINE文で定義しておく必要があります。"_"(アンダスコア)に続いて3桁の数字が続いている名前を持つ変数はシステム変数です。また、配列は1次元1系統のみ使用でき、"@[式]"で記述されます。条件分岐は"IF"文により、"IF[条件式] #ラベル"という構文になります。リスト中のEXPAND文は、独自に可逆圧縮されたCGデータを展開表示するコマンドで非常に高速かつ省メモリです。
また、いろいろな性能のCPUに対応するため、SWAIT〜EWAIT文が用意されているのが大きな特徴です。これは「間に挟まれた処理を指定した時間をかけて実行する」というものです。低速なマシンに合わせて時間を設定すれば、どんな高速マシンでもタイミングが狂うことがありません。また、入れ子も8段まで可能です。他にもBGMとの同期をとるコマンドや各種セミグラフィックのコマンドなど、上のリストでは使われていない様々な便利な機能が用意されています。 |
|
このように文法の異なる(というかその用途に合わせた)スクリプト言語をいくつも創造し、より効率の良い開発ができるように日々頭を捻っていました。 |
|
|
|
MIDIインタフェース対応 |
|
アマランスIIから「標準化」したのがBGM演奏のためのMIDIインタフェース対応です。Roland社製のMPU-PC98/401インタフェース、およびその互換ボードへの対応がなされています。後にRS-232Cコネクタに接続するタイプのMIDIインタフェースも出回りましたが、それには対応していません。理由はいろいろありますが、とにかく風雅システムでは最後(Windowsに移行する)まで対応しませんでした。ちなみに某社の互換MIDIインタフェース「サウンド○レット」は、インテリジェントボードでありながら発声量が多くなるとテンポを維持できませんでした。つまり、それほどにアマランスIIのBGMのデータはもの凄かったわけです。RSインタフェース非対応の理由の一端です。 |
|
風雅システムのMIDIドライバは、もちろん自社開発のオリジナルです。アセンブラのみで組んであるので、常駐サイズ(メモリ占有量)も小さく、処理も軽快です。演奏データ形式は暗号化されたオリジナルのものですが、専用のコンバータにかけることで、一般的なフォーマットのデータであれば変換してそのまま演奏させることができました。お察しの通り、その演奏データも独自の方法で圧縮されていて、「メインメモリにやさしい」ものです。 |
|
最初からゲームのBGM演奏用に開発したので、演奏機能的にも特化されたものがいくつもあります。フェードイン・フェードアウトはもとより、テンポやキーの途中変更、インタフェースの使用割り込み番号の設定、EMS対応など様々です。
中でもちょっと面白いのが「効果音の発声」機能です。LA音源モジュールやGS音源モジュールがターゲットでしたから、使用できる音色の中にピストルの発射音やヘリコプターの音、爆発音など、上質の効果音があります。そこでゲームからそれらがいつでも使えるようにしてあるのです。通常はFM音源で効果音を鳴らしますが、ここぞというときには音源モジュールからリアルな効果音が出るというわけです。が、実際にやってみるとそれまで鳴っていたFM音源の効果音との差がありすぎて、完全に音が浮いてしまいました。そのようなわけで、残念ながらこの機能は製品では使用されていません。
それともうひとつ。「音痴演奏」機能。「指定した頻度で音程をはずしてくれる」というありがたい(?)機能です。ズッコケイベントなどで使おうと思って作った機能だったのですが、思った以上に間抜けで身体の力が抜けてしまうという現象が発生し、これも製品では使用していません。 |
|
アマランスIIでは当初Roland社製のMT-32系LA音源のみの対応でしたが、後にパワーアップキットでGS音源にも対応しました。当時、数万円もする高価な音源モジュールだったにもかかわらず、「アマランスIIのために買った!」というユーザが続出しました。開発陣は嬉しい反面、申し訳ないような複雑な心境だったものです。が、「投資の甲斐があった」というご意見がほとんどで、小さくガッツポーズをしたものです。 |
|
|
|
|