[前へ] [目次へ] [次へ]

調べると右に動くイベントを作ってみる

今回は調べると右に動くイベントを作ってみます。


●基本移動と移動予約
   イベントオブジェクトには行動を指定することができます。
   この行動の指定には二種類あり、
   サンプルで最初からいるイベントのように「何もしなくても勝手に行動する」設定と
   「スクリプト上で指定した時に指定された行動を一度だけ行う」設定があります。
   
   「何もしなくても勝手に行動する」設定を「基本移動」と呼び、
   ゲームでは歩き回る村人など、「特にイベントを起動していない時に行う行動」を設定します。
   対して「スクリプト上で指定した時に指定された行動を一度だけ行う」設定を「移動予約」と呼び、
   こちらはイベント処理内でのキャラクターの移動のように、「必要な時に単発で行う動作」を設定します。
   
   FGSのデフォルトではイベント処理中は「基本移動」は一時停止され、「移動予約」はそのまま実行されるようになっています。
   今まで気に留めていなかった人も多いかと思いますが、
   実は「放置すると歩き回るサンプルイベント」はメッセージ表示中移動していません。
   (ただし移動中だった場合、マスの途中でピタッと止まるわけではなく、マス単位で停止します)

   
●ムーブコマンド
   「ムーブコマンド」とは、基本移動や移動予約時に行う動作を指定するためのコマンドID群です。
   「ムーブコマンド」は整数値で、これ自体はかなりややこしいものになっています。
   (詳細は FGESCommonEventObject::ReserveLogicMove にあります)
   そこで、「ムーブコマンド」のリストについては専用のエディターが準備されており、
   それを使うことによってかなり分かりやすく記述することができます。
   
   「ムーブコマンド」の処理はイベントオブジェクトごとに行われます。
   また、「ムーブコマンド」は処理時に次の「ムーブコマンド」の処理を行うまでのフレーム数を指定し、
   このフレーム数の経過後に次の「ムーブコマンド」の処理が開始されます。
   このフレーム数は「ムーブコマンド」によって指定され、
   「ムーブコマンド」によるフレーム数の指定がない場合、「移動周期(基本移動間隔)」を使います。

   
   「ムーブコマンド」の処理が開始されると、以下の優先順位で一つだけ処理され、
   その「ムーブコマンド」が指定したフレーム数分、待機します。
   (この時待機フレーム数が0である場合、即座に次のムーブコマンドの処理が始まります)
      1(優先).移動予約されたムーブコマンド(予約順)
      2.基本移動に設定されたムーブコマンド
   ただし、基本移動ムーブコマンドの処理中に移動予約が行われた場合、
   基本移動ムーブコマンドの処理を中断して直ちに移動予約ムーブコマンドの処理が開始されます。
   移動予約ムーブコマンドの処理が完了した後、基本移動ムーブコマンドの処理は再開されます。


●論理移動と描画移動
   「ムーブコマンド」は基本的には移動処理を行うことを想定して定義されています。
   ここで問題になるのが「移動中のイベント」です。
   
   どういうことかというと、「ゆっくりと移動するイベント」の「当たり判定」についてです。
   基本的にイベントキャラクターは他のイベントキャラクターやプレイヤーと重ならないように、
   自分のいるマスに対して「障害判定」を発生させています。
   移動しようとするキャラクターは通常、移動先のマスの「障害判定」を確認して移動の可否を決めているわけです。
   
   イベントキャラクターが移動する場合、まず移動先のマスの「障害判定」を確認します。
   そして「移動可能」であった場合、自分のいる「論理座標」を移動先のマスに更新します。
   「論理座標」を更新したことで、「自分のいるマス」が移動し、自分が発生させる「障害判定」の位置も更新されます。

   しかし、これだけだとイベントキャラクターは「一瞬で」移動先のマスに移動してしまいます。
   忍者のような動きをしたいならそれでもいいかもしれませんが、
   村人が片っ端からそんな動きをしていたらシュールでしかありません。
   
   そこで、FGSでは「イベントキャラクターを画面上に表示する座標」は「実際に存在するマス」とは別に管理されています。
   ここで「実際に存在するマス」を示す座標を「論理座標」、
   「イベントキャラクターを画面上に表示する座標」を「描画座標」と呼び、
   「論理座標」を更新する処理を「論理移動処理」、「描画座標」を更新する処理を「描画移動処理」と呼んでいます。
   
   そして、前述の移動処理が「論理移動処理」にあたり、
   さらに「描画座標」を「描画移動時間」だけ掛けて後追いで更新(描画移動処理)するように設定されるのです。

   
   このような手順で移動が行われているため、
   「ゆっくりと移動するイベントを高速に移動するイベントが追いかける」ようなことをすると、
   「既に移動済みだが、画面上はまだいるように見える位置」に
   「高速に移動するイベントが素早く移動する」ことにより、一時的にイベント同士が重なったように見えます。
   この挙動は今のところ仕様であり、気になる場合は演出で回避したり、移動速度を合わせるなどしてください。


●調べられたら移動予約をする
   さて、ムーブコマンドの概要の説明が終わったところで本題の「調べると右に動くイベント」を作ってみます。
   まず、コマンドの挿入から「行動予約」を開きます。


   ムーブコマンドエディターが起動するので、移動する歩数を1にしたまま「右」ボタンを押します。


   「右に1歩移動」が追加されたことを確認して、OKを押します。


   すると次のスクリプトが挿入されます。
<  1>
<  2>
<  3>
<  4>

//論理移動の予約
EMC::Move(this,2,1,0);//右に1歩移動
 


●実行して確認する


   イベントを調べるとイベントが右に1マス動きます。



●問題点
   無事、調べると右に動くイベントが完成しました。
   しかし、まだこれでは困ったことが起きてしまうのです。
   
   以下の事例をご覧ください。


   これは左から右キーを押しながら調べた結果起きる現象です。
   「移動予約」は文字通り「予約」であるので、移動の完了を待つことなくイベントは完了します。
   プレイヤーは自由に動けるようになるので、すぐに移動中のツボを追いかけることが可能です。
   
   そして、「動きの遅いツボ」が移動している間に「動きの速いプレイヤー」が追いかけることによって、
   ツボとプレイヤーが重なってしまったわけです。(前述の通り、これは仕様です)
   これを特に問題ではないと片付けることもできます。
   しかし気になるようであれば、例えば「ツボが動ききるまでイベントを完了しない(プレイヤーの行動を認めない)」という対処が考えられます。
   
   コマンドの挿入から「行動完了の待機」を選択して、「 this の完了を待機する」と設定してください。




<  1>
<  2>
<  3>
<  4>
<  5>
<  6>
<  7>

//論理移動の予約
EMC::Move(this,2,1,0);//右に1歩移動

//行動完了を待機する (待機対象)
ECL::WaitMove(this);
 

   
   まだあります。
   今のままだとツボの移動が終わってからすぐにもう一度動かそうとしてもしばらく動きません。
   これは移動した時の待機フレーム数が残っていて次のムーブコマンドがすぐに実行されないためです。
   このように待機フレーム数が残ってしまうと都合が悪い場合は「周期を待たない」オプションを付けましょう。
   「周期を待たない」オプションには「成功時」と「失敗時」がありますが、
   これは「移動できたら成功」、「障害物や壁、他のイベントなどがあって移動できないと失敗」となります。
   今回は移動できたかどうかに関わらず周期を待ちたくないので、両方にチェックします。
   
   最初の移動予約の部分を削除して改めてコマンドの挿入をします。


   「移動周期を待たない」オプションを付けて入力すると (成功待無)(失敗待無)(待無) 等の表示が付き、
   このオプションを付けた条件では待機フレーム数が0になります。
   「成功時周期を待たない」場合に移動が成功すると移動が終わり次第、次のムーブコマンドが開始されます。
   「失敗時周期を待たない」場合に移動が失敗すると即座に次のムーブコマンドが開始されます。
   
<  1>
<  2>
<  3>
<  4>

//論理移動の予約
EMC::Move(this,2,1,EMC::NOWAIT);//右に1歩移動(待無)
 


   これで万全? いやいや、まだあります。
   先ほどのように「移動完了までウェイト」してしまうと関係ないのですが、
   動くツボを追いかけて素早く調べまくると、調べた数だけ右へ行く予約が蓄積され、以下の画像のようなことになります。

   
   これは「基本移動中(移動予約したムーブコマンドの処理中ではない)」時だけ予約するようにすればOKです。
<  1>
<  2>
<  3>
<  4>
<  5>
<  6>
if(IsBaseMoving()){

   
//論理移動の予約
   
EMC::Move(this,2,1,EMC::NOWAIT);//右に1歩移動(待無)

   IsBaseMoving() は「このイベントが基本移動中」だと真を返します。
   ここで「基本移動中」とは「基本移動ムーブコマンドを処理すべき状態」を指し、
   特に基本移動ムーブコマンドが実行されていない場合でも「何もしない」基本移動ムーブコマンドが処理されているものとして扱います。

   
   
●おわりに
   ムーブコマンドの処理はいかがだったでしょうか?
   ムーブコマンドはイベントキャラクターを自在に操るための機能のひとつであり、その制御は多岐に渡ります。
   また、基本的に動作の完了を待たずに次に進むため、扱いづらいと思うかもしれません。
   しかし毎回動作の完了を待っていると複数のイベントキャラクターを同時に制御できないため、このようになっています。
   


[前へ] [目次へ] [次へ]

最終更新 2017/12/18