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

会話した回数を数えるイベントを作ってみる

前回はローカル変数を使ってみましたが、
ローカル変数はイベントの実行を越えて値を維持することができません。
今回はイベントの実行を越えて値を維持できる「ゲーム変数」について解説します。


●「ゲーム変数」とは
   ゲームでは宝箱の開封状態やイベントの進行状態など、
   イベントの実行を越えて、あるいはゲーム全体で永続的に維持しなければいけない値がいろいろあります。
   そのような値を維持するためにFGSで用意されているのが「ゲーム変数」です。
   「ゲーム変数」に保存した値はセーブ時に自動的にセーブデータに書き込まれ、ロード時に自動的に復元されます。
   
   ゲーム変数には維持期間とアクセス条件が異なる分類があり、
   さらに保持できる値の種類が異なる「整数」と「文字列」があります。
   これらを組み合わせて「ゲームグローバル整数」などといった呼び方をします。
   ゲーム変数の分類は以下の通りです。
分類維持期間アクセス条件
グローバルゲームデータ内で永続いつでも
グループゲームデータ内で永続同じマップグループにいる
グループ一時違うマップグループに移動するまでいつでも
マップゲームデータ内で永続同じマップにいる
マップ一時マップをロードしなおすまでいつでも
イベントゲームデータ内で永続同じイベントIDから
シリアルゲームデータ内で永続同じシリアルIDから
インスタンスマップをロードしなおすまで同じインスタンスIDから
   このうち、「イベント」「シリアル」「インスタンス」分類は特別な名前で
   「グローバル」「マップ」「マップ一時」分類の領域に間借りして保存されます。
   そのため、「イベント」「シリアル」「インスタンス」分類は本当の名前を直接指定すれば
   アクセス条件を無視してアクセスすることができます。
   
   これらの分類はそれぞれ異なる用途が想定されています。
   異なるアクセス条件で保存したゲーム変数は見えませんし、読み取れません。
   また、異なるアクセス条件で同じ名前を使用した場合は独立して保存されます。
   
   例えば、宝箱の開封状態を「シリアル」分類で保存しておけば、
   同じイベントで作成した宝箱の開封状態はそれぞれ別々に管理されます。
   一方で、ダンジョン内を横断するようなギミックは「グループ」分類で保存しておけば、
   同じグループに属するダンジョンマップ内で同じゲーム変数を共有することができます。
   
   使用するゲーム変数は「必要な最小のアクセス条件」を使うことを心がけましょう。
   なぜなら、アクセス可能な範囲が広いほど、「うっかり同じ名前をダブらせてしまう」ようなミスをしやすくなり、
   さらにそのミスをどこで行ったかを調べるのが難しくなります。
   「グローバル」分類のように範囲の極めて広い分類は「メインシナリオの進行状態」など、
   ゲーム上の広い範囲からアクセスしなければならない値に限定して使うべきです。
   
   「グループ一時」「マップ一時」「インスタンス」分類は維持期間が永続ではないので、
   異なるマップグループに移動したり、マップをリロードするとなくなってしまいます。
   これは例えば、「ダンジョンやマップから出たらリセットされるギミック」などに便利です。
   ただし「マップ一時」「インスタンス」分類はセーブデータをロードした場合にも失われるので、
   いつでもセーブできるように構成する場合は注意が必要です。
   
   
●ゲーム変数を読み書きする
   ゲーム変数へのアクセスは「コマンドの挿入」( 第5回参照 )からも入力できますし、
   直接スクリプトを記述しても構いません。


   ●ゲーム変数の取得
      ゲーム変数に保存されている値を読み取ります。
      
      受け取る変数式には読み取ったゲーム変数の値を格納するローカル変数を指定します。
      ここで画像のように型名から書くとローカル変数の定義も同時に行うことができます。
      
      ゲーム変数の種類はアクセスするゲーム変数の分類と種類を指定します。
      
      取得するゲーム変数名には記号を含まない名前を指定します。
      日本語でもOKですが、後で使う時にも一字一句同じ名前が必要なことに留意してください。
      
      存在しない場合の値式には「指定したゲーム変数が存在しない場合」に使用する値を指定します。
      ようするにデフォルト値で、省略した場合は既定値(かなり小さな値で0ではありません)が使われます。
      ちなみに、ローカル変数名ひとつだけでも数値ひとつだけでも「式」です。


   ●ゲーム変数の設定
      ゲーム変数に値を保存します。
      存在しないゲーム変数名を指定した場合は同時に作成されます。
      
      ゲーム変数の種類はアクセスするゲーム変数の分類と種類を指定します。
      
      設定するゲーム変数名には記号を含まない名前を指定します。
      日本語でもOKですが、後で使う時にも一字一句同じ名前が必要なことに留意してください。
      
      設定する値式には「ゲーム変数に保存する値」を指定します。
      ちなみに、ローカル変数名ひとつだけでも数値ひとつだけでも「式」です。



●話した回数をゲームシリアル整数に保存して数える
<  1>
<  2>
<  3>
<  4>
<  5>
<  6>
<  7>
<  8>
<  9>
< 10>
< 11>
//ゲーム変数[シリアル整数]の取得 (ゲーム変数名,デフォルト値)
Integer cnt=GetSerialInt('話した回数',0);

cnt++;
//←このように書くとcntの値を1増やすことができます

//メッセージの表示(待機,消去する) (表示内容)
ECL::WaitLastMessage(
   
"君と話すのは@d回目だね。",cnt);

//ゲーム変数[シリアル整数]の設定 (ゲーム変数名,設定値)
SetSerialInt('話した回数',cnt); 
   上記のスクリプトをイベントに設定して何回か話しかけてみましょう。
   話すたびに回数が増えていくのが分かると思います。
   
   さて、このスクリプトは4つの手順で構成されています。
   一つ一つ見ていきましょう。
   
<  1>
<  2>
//ゲーム変数[シリアル整数]の取得 (ゲーム変数名,デフォルト値)
Integer cnt=GetSerialInt('話した回数',0); 
   ローカル変数として Integer 型の cnt を定義し、
   ゲームシリアル変数「話した回数」の値(デフォルト値0)を代入しています。
   最初にこのイベントに話しかけた時はゲームシリアル変数「話した回数」が存在しないため、0が代入され、
   二回目以降は(手順4で設定した)ゲームシリアル変数「話した回数」の値が代入されます。
   
<  1>cnt++;//←このように書くとcntの値を1増やすことができます 
   ローカル変数 cnt の値を1増やします。
   この ++ はインクリメントと呼び、プログラム上でよく使う「整数変数の値を1増やす」ために使用できます。

<  1>
<  2>
<  3>
//メッセージの表示(待機,消去する) (表示内容)
ECL::WaitLastMessage(
   
"君と話すのは@d回目だね。",cnt); 
   前回行ったのと同じ、式の値を表示する手順です。

<  1>
<  2>
//ゲーム変数[シリアル整数]の設定 (ゲーム変数名,設定値)
SetSerialInt('話した回数',cnt); 
   ゲームシリアル変数「話した回数」の値としてローカル変数 cnt の値をコピーして保存します。
   ゲームシリアル変数はローカル変数より維持期間が長いので、
   次回のイベント実行時にここで保存した値を読み出せます。


●同じイベントを並べて独立して保存されていることを確認してみる
   ゲームシリアル変数がイベントの実行を越えて値を維持していることはわかりました。
   ここで「異なるアクセス条件でアクセスしたら値が独立している」ことを確認してみましょう。
   
   まず、「イベントインスタンス」を増やしてみます。
   「イベントインスタンス」とは、「マップ上で実体化しているイベントオブジェクト」のことです。
   実は今まで配置していたイベントも「イベントインスタンス」でした。
   
   今までは「イベント」と「イベントインスタンス」は1対1になっていました。
   しかしFGSでは一つの「イベント」に対して複数の「イベントインスタンス」を作成できます。
   同じ「イベント」から作成された「イベントインスタンス」は同様の内容を持ちます。
   これは見掛け上イベントをコピーするのと同じですが、
   「イベントIDが同じ」「コピーされるのは実行時」という点が異なります。
   
   「イベントIDが同じ」ということは「イベント」分類のゲーム変数は共有されます。
   「コピーされるのは実行時」ということは根元のイベントを変更するとその全てで変更が共有されます。
   これらを使いこなすのはそれなりに難しいかもしれませんが、一度使えるようになれば重宝するでしょう。
   
   
   さて、それでは実際に「イベントインスタンス」を増やしてみます。
   まず、イベント編集モードにした状態で増やしたいイベントの上にマウスカーソルを合わせ、
   S5キー(キーボードのA) を押します。(選択ボタンから目標のイベントを選ぶこともできます)


   イベントが選択されたことを確認(画面下端の表示)してから、
   二つ目の「イベントインスタンス」を配置したい場所をダブルクリックします。


   「イベントインスタンス(複製)」を配置していることを示す緑色の枠が表示されます。
   「イベントインスタンス(本体)」である青色の枠と違い、この緑色の枠ではイベント内容を編集できません。
   緑色の枠をダブルクリックすると代わりに開くのは「メタデータエディター」といい、
   「イベントインスタンス」ごとに固有の追加情報を設定することができます。
   例えば、「マップ移動」イベントの移動先はメタデータとして保持されています。

   
   これで同じイベント内容を持つイベントインスタンスが二つできました。
   デバッグ実行してそれぞれ独立してゲーム変数が保持されていることを確認してみてください。


●コピーしたイベントと増やしたイベントインスタンスの違いを確認してみる
   次は、イベントを「コピー」した場合と先ほどの「イベントインスタンスを増加」させた場合の違いを確認します。
   どちらの手順で増やした場合でも「シリアルID」は別のものになります。
   そのため「シリアル」分類のゲーム変数では違いが分かりづらいため、
   回数を保存するゲーム変数を「イベント」分類に変更します。
   
   なお、各分類のゲーム変数にアクセスするためのメソッド名(操作を行うために使う名前)は以下の通りです。
   一時分類を指定する場合はゲーム変数名の先頭を # で始めます。
分類読み取り書き込み
グローバル整数GetGlobalIntSetGlobalInt
グループ整数
グループ一時整数
GetGroupIntSetGroupInt
マップ整数
マップ一時整数
GetMapIntSetMapInt
イベント整数GetEventIntSetEventInt
シリアル整数GetSerialIntSetSerialInt
インスタンス整数GetInstanceIntSetInstanceInt
グローバル文字列GetGlobalStrSetGlobalStr
グループ文字列
グループ一時文字列
GetGroupStrSetGroupStr
マップ文字列
マップ一時文字列
GetMapStrSetMapStr
イベント文字列GetEventStrSetEventStr
シリアル文字列GetSerialStrSetSerialStr
インスタンス文字列GetInstanceStrSetInstanceStr
   
<  1>
<  2>
<  3>
<  4>
<  5>
<  6>
<  7>
<  8>
<  9>
< 10>
< 11>
//ゲーム変数[イベント整数]の取得 (ゲーム変数名,デフォルト値)
Integer cnt=GetEventInt('話した回数',0);

cnt++;
//←このように書くとcntの値を1増やすことができます

//メッセージの表示(待機,消去する) (表示内容)
ECL::WaitLastMessage(
   
"君と話すのは@d回目だね。",cnt);

//ゲーム変数[イベント整数]の設定 (ゲーム変数名,設定値)
SetEventInt('話した回数',cnt); 
   使用するゲーム変数の分類を「シリアル」から「イベント」に変更しました。
   
   続けて、イベントを「コピー」するためにイベント本体の青い枠に
   マウスカーソルを合わせて Ctrl+S2キー(キーボードのCtrl+C) を押します。


   そして隣にイベントを「ペースト」するために Ctrl+S3キー(キーボードのCtrl+V) を押します。


   この方法でコピーした場合、イベント内容を含めたフルコピーが作られます。
   ペーストしたイベントにはコピー元のイベント名が付いていますが、イベントIDは新しく割り当てられます。
   ペーストした方のイベントも本体なので、イベントエディターで内容を編集できます。
   ペーストした方のイベントの表示メッセージをちょっとだけ変更しておきましょう。
<  1>
<  2>
<  3>
<  4>
<  5>
<  6>
<  7>
<  8>
<  9>
< 10>
< 11>
//ゲーム変数[イベント整数]の取得 (ゲーム変数名,デフォルト値)
Integer cnt=GetEventInt('話した回数',0);

cnt++;
//←このように書くとcntの値を1増やすことができます

//メッセージの表示(待機,消去する) (表示内容)
ECL::WaitLastMessage(
   
"君と話すのは@d回目だ!",cnt);

//ゲーム変数[イベント整数]の設定 (ゲーム変数名,設定値)
SetEventInt('話した回数',cnt); 
   
   デバッグ実行してそれぞれに話しかけてみましょう。
   「イベント」分類のゲーム変数にしたので、
   同じイベントIDを持つ本体と左側のイベントインスタンスでは話した回数が共有されています。
   一方で、コピーペーストした右側のイベントでは話した回数が共有されていませんし、
   変更したイベント内容も独立して保持されています。




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

最終更新 2018/10/29