dim3では、スクリプトはそれぞれ、
- あるモデル(Object)に対応するスクリプト
- ある武器(Weapon)に対応するスクリプト
- ある弾(Projectile)に対応するスクリプト
- あるマップ(Course)に対応するコーススクリプト
が存在し、Data/Scripts/以下、種類別にフォルダに入っています。
つまり、プレイヤーにさせたいことは、プレイヤーに対応する Player.js スクリプトに書きます。
敵キャラにさせたいことは、敵キャラに対応する Joefoe.js に書く、といった案配です。
■ オブジェクトについて - dim3の仕組み
dim3のすべてのもの(ボタンや画像、3Dモデル、色、カメラ等)は、
オブジェクト(対象)という概念で管理されています。
オブジェクトには大きく分けて2種類あります。
weap , proj , obj , course から始まるものは「Specific script Object」 と呼ばれ、特定(自身)のスクリプトからしか使えません。
Map , Camera , Sound , iface から始まるものは 「Global Object」 と呼ばれ、どのスクリプトからも使うことができます。
書式に従って対象のありかを指定すれば、その対象に関するあらゆる特徴を自由に操作する事が出来ます。
公式のマニュアルのスクリプトリファレンスには、オブジェクトとメソッドの一覧が載っています。
■ イベント発生について - dim3はどのように動いているのか?
dim3エンジンは、キーが押された、プレイヤーが行動した、MAPが読込まれた、モデルが構築された、ぶつかった、ダメージを受けた、といった状況の変化に対して、「イベント定数」というものを発行します。
イベント定数は、「DIM3_EVENT_」 で始まる定数で、メインイベントとサブイベント(さらに分類されたもの)を持っています。
DIM3_EVENT_CONSTRUCT
DIM3_EVENT_MAP_OPEN
DIM3_EVENT_JUMP
DIM3_EVENT_CLICK
DIM3_EVENT_DAMAGE
DIM3_EVENT_COLLIDE
公式のマニュアルのスクリプトリファレンスには、イベント、サブイベント一覧が載っています。
■ イベント・ループについて
一方、各スクリプトは、それがいつ起きるか、いつも監視しています。実際に Data/Setting/以下のスクリプトには必ず、event 関数による、 次のようなコードが含まれています。
スクリプトは実行されると、このevent 関数の中をえんえんと廻り続けることになります、何かイベントが発生すると swith &case 文で捕捉され 各処理にまわされます。
各処理にまわされる関数には、通常引数はobj , サブイベントがある場合はsubEventも渡します。
//メインループ
function event(obj,mainEvent,subEvent,id,tick)
{
switch (mainEvent) {
case DIM3_EVENT_CONSTRUCT: // データ構築時に呼ばれます(一番最初)
joeFoeConstruct(obj);
return;
case DIM3_EVENT_SPAWN: // MAP上に生成された時
joeFoeSpawn(obj);
return;
case DIM3_EVENT_DIE: 死んだ
joeFoeDie(obj);
return;
case DIM3_EVENT_DAMAGE: //ダメージを受けた
joeFoeDamageStart(obj,tick);
return;
case DIM3_EVENT_WATCH: //索敵中
joeFoeWatch(obj,subEvent);
return;
case DIM3_EVENT_WAIT://攻撃など、一定時間後に行なうべき行動 は DIM3_EVENT_WAIT が発生した時に行ないます。
joeFoeWait(obj,id,tick);
return;
case DIM3_EVENT_TIMER ://一定期間毎に起こしたい行動は DIM3_EVENT_TIMER が発生した時に行ないます。
joeFoeTimer(obj,id,tick);
return;
}
}
ここで、制作者が行なう事は、 発行されたイベントに対して、どんな処理をするのかをスクリプトに書くことです。例えば「イベント定数」に対するアニメーションや条件判断、フラグの取捨選択などが挙げられます。
dim3付属のデモについてるスクリプトには、様々な関数やメソッドの使用例があるので、参考にして下さい。
■ウエイト・タイマーの使い方
これは、その処理の一例です。
ウェイトやタイマーを使うには、スクリプトの最初で用途ごとにIDという定数を定義しておきます。
これはタイマーとウェイトのサブイベント定数にあたるもので、ユーザーが自由に作れます。ただし値は重複してはいけません。
そして、メインループのswitch〜case文でタイマー/ウェイトイベントを絞り、そこから更にIDごとに各関数へ振り分ける処理を書いておきます。
後は呼び出したい部分にウェイト/タイマーを発行する関数(startTimerやstartWait)を書いておけば、実行時にイベントが発行された時にメインループでそれを捕捉してくれます。
時間単位は「tick」。
タイマー : 一定時間毎にタイマーイベントとIDを発行する。
ウェイト : 一定時間後にウェイトイベントとIDを発行する。
これらを定義するメソッド:
startTimer(frequency_ticks,id);
startWait(wait_ticks,id);
startWaitRandom(wait_low_ticks,wait_high_ticks,id);
例えば、上で説明した Event ループで考えてみます。
スクリプトの最初で、ユーザーIDをいくつか作っておきます。
//ユーザーID :
var ID_ENEMY_ATTACK = 1;//攻撃する
var ID_ENEMY_WALK = 2; //歩く
var
ID_ENEMY_JUMP = 3; //ジャンプする
この時
- 1:起こすタイミング: joeFoeSpawn(obj);関数内で、タイマーイベントの発生を定義します startTimer(500 , ID_ENEMY_JUMP ); と書いておきます。
- 2: 実際にさせたい処理: joeFoeTimer(obj,id,tick); 関数内にかきます、
このとき、 タイマーイベント捕捉だけでは不十分なので、 joeFoeTimer 関数内で、さらに IDが ID_ENEMY_JUMPかどうかを調べ、分岐させます。
そこに、ジャンプさせるために obj.motionVector.jump(); を書きます。
実行時には、キャラクターがマップ出現後に
500tick 時間毎にタイマーイベントが発生し DIM3_EVENT_TIMER と共に
ID_ENEMY_JUMPが発行されます。それがメインループで捕捉され、 ID_ENEMY_JUMPの時に、実際のジャンプ obj.motionVector.jump(); が実行されます。
(なお、 obj.motionVector.go();で移動開始、 obj.motionVector.stop();で止まります)、
結果:
※joeFoeSpawn(obj);関数 はDIM3_EVENT_SPAWNイベントによって、マップ上に出現した時に呼び出されます。
※joeFoeTimer(obj,id,tick);関数 は タイマーイベントが発生した時に呼び出されます。
※このキャラクターはマップ上に出現されるや否や、600tick 毎にジャンプし続けることになります。