解決)メモ欄に記述したイベントで条件分岐する方法

アバター
こめかみ
記事: 104
登録日時: 2017年9月06日(水) 19:34
連絡を取る:

解決)メモ欄に記述したイベントで条件分岐する方法

投稿記事by こめかみ » 2021年11月30日(火) 02:25

・メモ欄に<FOOD>と記述したイベントをマップ内に複数配置
・捕食者のイベントを配置
・イベント(捕食者)が自分から一番近いイベント(FOOD)に向かって移動
・捕食者とFOODが重なるとFOODは消滅する(セルフスイッチで再現)
・捕食者はまだ消滅していない自分に近いFOODに向かって移動する
・FOODがマップ上から全て消滅するまで捕食者は行動を続ける

上記を行いたいのですが、
マップ内の「メモ欄に<FOOD>と書かれている」且つ「セルフスイッチがOFF」且つ「指定したイベントから一番近い」を満たすイベントのIDを変数に格納する方法はないでしょうか?

コード: 全て選択

let vid = 1; // 取得する変数番号
let min = 20; // 最大距離
let get = null;
$gameMap.events().forEach(function(event){
 let distance = $gameMap.distance($gamePlayer.x,$gamePlayer.y,event.x,event.y);
 if (min >= distance) { min = distance; get = event; }
});
$gameVariables.setValue(vid, get ? get.eventId() : 0);


条件分岐

コード: 全て選択

$gameMap.event($gameVariables.value(1)).event().meta['FOOD']


上記のスクリプトと条件分岐が近いかもと思ったのですが、これだと「プレイヤーから一番近いイベントのメモ欄にFOODの記述があるか」になってしまい、初心者の知識ではどうすべきかわからない状態です。
(「メモ欄に特定の記述のあるイベントのID」を取得する方法がわかればなんとなかなりそうなのですが...)
何かしらのヒントでも頂けましたらありがたいです。
最後に編集したユーザー こめかみ on 2021年11月30日(火) 21:43 [ 編集 2 回目 ]

アバター
Plasma Dark
記事: 669
登録日時: 2020年2月08日(土) 02:29
連絡を取る:

Re: メモ欄に記述したイベントで条件分岐する方法

投稿記事by Plasma Dark » 2021年11月30日(火) 10:29

この掲示板にはコードを書くための専用タグが用意されているので、コードを貼り付ける場合はそれを用いると良いと思います。
(書き込みフォーム上部の Code ボタンを押すことで手軽に使えます)

jsのコードを書く場合は、実行コンテキストを意識すると良いと思います。
イベントのスクリプトコマンドであれば、そのスクリプトを書くイベントが並列処理であるか否か、捕食者のイベントなのか、被捕食者のイベントなのか、あるいは捕食システムを制御する専用イベントなのか。
どんなアプローチで実装しようとしているかの情報に、これが含まれているとわかりやすいです。

$gameMap.events() で取得できるのは、そのマップ上に存在するイベント(Game_Eventインスタンス)の配列です。
Game_Eventインスタンスからメモ欄のタグやイベントIDを取得する方法は、すでにご提示頂いたコードの中に存在します。

捕食者イベントのGame_Eventインスタンスを取得するベストな方法は実行コンテキスト次第ではありますが、ここではとりあえずコンテキストを限定せずに取得してみます。
(メモ欄に <eater> の記述があるイベントを捕食者とします)

コード: 全て選択

$gameMap.events().find(gameEvent => gameEvent.event() && gameEvent.event().meta.eater);


配列の中から特定の条件を満たす要素をひとつ取得するには、 Array.prototype.find を用います。
https://developer.mozilla.org/ja/docs/W ... Array/find

捕食者から最も近い、生存している被捕食者を取得したい場合、こんな風に書けます。
(生きている=セルフスイッチAがOFF、被捕食者=メモ欄に <food> と書かれたイベントとします)

コード: 全て選択

const eater = $gameMap.events().find(gameEvent => gameEvent.event() && gameEvent.event().meta.eater);

$gameMap.events().reduce((result, gameEvent) => {
  if (!gameEvent.event() || !gameEvent.event().meta.food) {
    return result;
  }
  if (!$gameSelfSwitches.value([$gameMap.mapId(), gameEvent.eventId(), "A"])) {
    return result;
  }
  return result && $gameMap.distance(eater.x, eater.y, result.x, result.y) < $gameMap.distance(eater.x, eater.y, gameEvent.x, gameEvent.y) ? result : gameEvent;
}, null);


配列のすべての要素について計算して結果をひとつにまとめるような場合、 Array.prototype.reduce を用います。
https://developer.mozilla.org/ja/docs/W ... ray/Reduce
日本語だと汎用的な説明がピンと来ないかもしれませんが、今回は生存している被捕食者の配列の中で最も捕食者との距離が近いものを探すために利用しています。

コード中のresultの値は、最初はnullです。(reduceの第2引数に指定しています)
gameEventの値は、$gameMap.events()で取得した配列の中の要素ひとつです。
(reduceは配列の中身をひとつひとつ順番に見ていきます)

配列から最初に被捕食者を見つけたとき、resultの値はそのイベントのGame_Eventインスタンスになります。
次に被捕食者を見つけたとき、互いの捕食者との距離を比較して、小さいほうをresultの値とします。
これを繰り返して、捕食者から最も近い、生存している被捕食者のイベントを取得します。

そうしたら、そのイベントのIDを変数に記録するんでしたね。

コード: 全て選択

const VARIABLE_ID = 1;
const eater = $gameMap.events().find(gameEvent => gameEvent.event() && gameEvent.event().meta.eater);
const nearestAliveFood = $gameMap.events().reduce((result, gameEvent) => {
  if (!gameEvent.event() || !gameEvent.event().meta.food) {
    return result;
  }
  if (!$gameSelfSwitches.value([$gameMap.mapId(), gameEvent.eventId(), "A"])) {
    return result;
  }
  return result && $gameMap.distance(eater.x, eater.y, result.x, result.y) < $gameMap.distance(eater.x, eater.y, gameEvent.x, gameEvent.y) ? result : gameEvent;
}, null);

$gameVariables.setValue(VARIABLE_ID, nearestAliveFood ? nearestAliveFood.eventId() : 0);


頭の体操になりそうだったので、大部分をプラグインに任せるやり方で実装してみました
要件を詳しく掘り下げたわけではないので、これをそのまま使うことは推奨しませんが、コードが参考になれば幸いです。
アバター
こめかみ
記事: 104
登録日時: 2017年9月06日(水) 19:34
連絡を取る:

Re: メモ欄に記述したイベントで条件分岐する方法

投稿記事by こめかみ » 2021年11月30日(火) 15:03

>Plasma Dark 様
コードのタグで貼り付けなおしました。
ご返答ありがとうございます。初心者が実装するには難度が高い要望でした;;
どの記述がどこを指しているのか、~の場合はどう記述するのか検索する時点でおぼつかなかったため、勉強になります。
制御用の別イベントでの並列処理、または並列コモンイベントで行う予定でした。
まずは記載いただいたスクリプトを制御イベントを流用しましたが、セルフスイッチがうまく判定しないようです。その部分のみ削ると近くの被捕食者に向かう事はできました!
この場合にはどこを改変すべきでしょうか?
またプラグインの流用方法も教えて頂きたいです。
ヒントをと言いつつ更に細かい質問をし申し訳ありません。
添付ファイル
3.png
2.png
1.png
アバター
こめかみ
記事: 104
登録日時: 2017年9月06日(水) 19:34
連絡を取る:

Re: メモ欄に記述したイベントで条件分岐する方法

投稿記事by こめかみ » 2021年11月30日(火) 21:43

>Plasma Dark 様
セルフスイッチの件、解決致しました!
!$gameSelfSwitchesの!を削ると想定通りの挙動になりました(??)

コード: 全て選択

  if ($gameSelfSwitches.value([$gameMap.mapId(), gameEvent.eventId(), "A"])) {
  return result;


ともかく解決いたしました!
順序だてて丁寧に教えて下さりありがとうございました。
Jsはわからない事だらけですが、今後に役立てていきます。
アバター
Plasma Dark
記事: 669
登録日時: 2020年2月08日(土) 02:29
連絡を取る:

Re: 解決)メモ欄に記述したイベントで条件分岐する方法

投稿記事by Plasma Dark » 2021年11月30日(火) 23:43

セルフスイッチの件、解決致しました!
!$gameSelfSwitchesの!を削ると想定通りの挙動になりました(??)


ああ、記事に書いたコードでは被捕食者が生きている判定が逆転していましたね。
ご対応頂いた通り、!を消すとセルフスイッチがONの場合にすでに消滅している判定となり、意図通りに動くようになります。

制御用の並列イベントは毎フレーム実行すると、イベントが増えたときにパフォーマンスの低下が気になるかもしれません。
適度にウェイトを挟んであげると良いと思います。

またプラグインの流用方法も教えて頂きたいです。


とりあえず動かす方法を書いておきます。
制御用のイベントは不要です。
捕食者と被捕食者のメタタグ設定をし、被捕食者のイベントにセルフスイッチAをONにするだけの設定をします。
捕食者は移動ルートを固定にしておきます。
これだけで動くはずです。
アバター
こめかみ
記事: 104
登録日時: 2017年9月06日(水) 19:34
連絡を取る:

Re: 解決)メモ欄に記述したイベントで条件分岐する方法

投稿記事by こめかみ » 2021年12月01日(水) 01:04

>Plasma Dark 様
アドバイスありがとうございます。並列処理の方はウェイトを少し挟んでみます。
プラグインを導入し、画像の設定でプレイしたのですが動かずでした。
セルフスイッチの設定方法が間違っておりますでしょうか?

※スクリプト制御の際に、マップ内に<eater>イベントがいない状態で<food>が2体以上いた場合
エラー "cannot read property 'x' of undefined" が起きました。
現状、同一マップに<eater>を用意しておけば回避できるのですが、解決できないか挑戦してみます(_ _)
(<eater>が存在しない場合の処理を追記すれば良いのでしょうか?)
添付ファイル
3.png
2.png
1.png
アバター
Plasma Dark
記事: 669
登録日時: 2020年2月08日(土) 02:29
連絡を取る:

Re: 解決)メモ欄に記述したイベントで条件分岐する方法

投稿記事by Plasma Dark » 2021年12月01日(水) 01:39

プラグインを導入し、画像の設定でプレイしたのですが動かずでした。


被捕食者は並列実行ではなく、決定ボタンにしてください。
また、セルフスイッチAをONにする処理はすべての被捕食者に入れて、
2ページ目をセルフスイッチAがONになった状態(消滅した状態)にすると見た目それっぽく動きます。

※スクリプト制御の際に、マップ内に<eater>イベントがいない状態で<food>が2体以上いた場合
エラー "cannot read property 'x' of undefined" が起きました。


捕食者がいる前提で組んだので、捕食者がいなければその座標が取れずにこういうエラーになりますね。
捕食者がいない場合、制御装置のスクリプト2行目のeaterはundefinedになります。
捕食者がいない状態でこのスクリプトを実行する意味はないですが、どうしても常に実行したい要求があるのでしょうか。
アバター
こめかみ
記事: 104
登録日時: 2017年9月06日(水) 19:34
連絡を取る:

Re: 解決)メモ欄に記述したイベントで条件分岐する方法

投稿記事by こめかみ » 2021年12月01日(水) 02:45

>Plasma Dark 様
何度も申し訳ございません。

新規プロジェクト、追加プラグインは捕食のみ

全被捕食者のメモ欄に<food>
1ページ目には何もコマンドを入れず
2ページ目の出現条件にセルフスイッチAがON
両ページともトリガーは決定

捕食者のメモ欄に<eater>
1ページ目には何もコマンドを入れず
トリガーは決定


上記の処理で合っておりますでしょうか?

捕食者がいる前提で組んだので、捕食者がいなければその座標が取れずにこういうエラーになりますね。
捕食者がいない場合、制御装置のスクリプト2行目のeaterはundefinedになります。
捕食者がいない状態でこのスクリプトを実行する意味はないですが、どうしても常に実行したい要求があるのでしょうか。

別マップからイベントを呼び出すプラグインで<eater>を呼び出そうと思ったのですが、エラーが起きてしまい、そこの改善ができないかと思っておりました。(<eater>を初期配置しておいたマップで別<eater>呼び出すとエラーは起きないのですが、座標の取得が初期配置<eater>基準で動いてしまう)
が初期配置<eater>を別<eater>が呼び出される位置に移動させて動かし、別<eater>をそこに追従させる方法で解決できそうです。
ややこしい話ですみません;;
最後に編集したユーザー こめかみ on 2021年12月01日(水) 03:03 [ 編集 2 回目 ]
アバター
こめかみ
記事: 104
登録日時: 2017年9月06日(水) 19:34
連絡を取る:

解決中)メモ欄に記述したイベントで条件分岐する方法

投稿記事by こめかみ » 2021年12月01日(水) 02:59

____________________________________________________
最後に編集したユーザー こめかみ on 2021年12月01日(水) 18:04 [ 編集 1 回目 ]
アバター
Plasma Dark
記事: 669
登録日時: 2020年2月08日(土) 02:29
連絡を取る:

Re: 解決)メモ欄に記述したイベントで条件分岐する方法

投稿記事by Plasma Dark » 2021年12月01日(水) 10:39

上記の処理で合っておりますでしょうか?


被捕食者の1ページ目にはセルフスイッチAをONにするコマンドのみを入れます。

別マップからイベントを呼び出すプラグインで<eater>を呼び出そうと思ったのですが、エラーが起きてしまい、そこの改善ができないかと思っておりました。


別マップからイベントを呼び出すプラグインが何者で、どうやって呼び出しているかわかりません。
以下で対処できる気はしますが、後者の変更方法は捕食者の呼び出し方次第です。

- 別マップから呼び出したときにスイッチを操作して制御装置を起動する
- 捕食者のインスタンス取得を対象プラグインに合わせて適当に変更する

“MV:質問” へ戻る