【解決済】車を量産させる方法

tkar
記事: 5
登録日時: 2023年2月04日(土) 10:16

【解決済】車を量産させる方法

投稿記事by tkar » 2023年2月04日(土) 10:24

スクリプト初心者です
お世話になります

車を量産させたいのですが、方法がわからなくて困っています
道路を車が走る仕様は、
割りと大きめのマップのため、あと、
動きにいろんなバリエーションを出すため(交差点で右折、直進、左折をランダムで決める)、
車のルートを設定するのではなく、道路をリージョンで動く仕様にしました

十字路だったり、T字路だったり、信号があったり、なかったり、交差点ごとに挙動が違うため、
リージョンの数や(交差点ごとの)ページが多くなってしまいました

それぞれの車に位置を割り当てて制御するため、
車1の乗ってるリージョンを車2の乗ってるリージョンなどに
全て置き換えなくてはならないのですが、
車も沢山作りたいため、
1つ1つポチポチしていくのは大変だと思うので、
何か良い方法はないでしょうか?
色々調べて試してみましたが結局実装まではできませんでした
よろしくお願いしますm(_ _)m

capture5357_2023.02.04.jpg
最後に編集したユーザー tkar on 2023年2月11日(土) 23:28 [ 編集 1 回目 ]

名無し蛙
記事: 302
登録日時: 2015年11月23日(月) 02:46

Re: 車を量産させる方法

投稿記事by 名無し蛙 » 2023年2月04日(土) 19:37

tkar さんが書きました:動きにいろんなバリエーションを出すため(交差点で右折、直進、左折をランダムで決める)、
車のルートを設定するのではなく、道路をリージョンで動く仕様にしました

この仕様に沿ったユーザ定義移動コマンドを作り
移動ルートの設定の右下にあるスクリプト欄から呼び出せばいけるんじゃないかなぁ、と思います。

まず適当なプラグインを作って

コード: 全て選択

/*:
 * @target MZ
 */

(() => {
    'use strict'
    // 立っているマスと同じリージョンの隣接マスに向けて一歩前進する移動コマンド
    Game_Character.prototype.moveRegionRoute = function() {
        const candidates = [2, 4, 6, 8].filter(d => d !== this.reverseDir(this._direction))
            .filter(d => {
                const x = this.x + ((d === 4) ? -1 : ((d === 6) ? 1 : 0));
                const y = this.y + ((d === 8) ? -1 : ((d === 2) ? 1 : 0));
                const regionId = $gameMap.regionId(x, y);
                return regionId === this.regionId();
            });
        if (candidates) {
            const d = candidates[Math.floor(Math.random() * candidates.length)];
            this.moveStraight(d);
        }
    };
})();

自律移動タイプ>カスタムで「動作を繰り返す」にチェックして
右下の「スクリプト」から

コード: 全て選択

this.moveRegionRoute();

と打ち込めばリージョンに沿って動くと思います。

ただし、一つ注意点があってツクールのデフォルトで
負荷軽減の為かランダムで動き過ぎない為か
「画面外のイベントは自律移動を停止する」という仕様が存在します。
広いマップ、かつ規則的に動くイベントが存在すると画面外で渋滞を起こして気になるかもしれませんね。

外す場合はプラグインの中に

コード: 全て選択

Game_Event.prototype.isNearTheScreen = () => true;   

とでも書いておけば制限が外れると思います。

編集:this.setMovementSuccessを削除しました
最後に編集したユーザー 名無し蛙 on 2023年2月07日(火) 01:10 [ 編集 1 回目 ]
tkar
記事: 5
登録日時: 2023年2月04日(土) 10:16

Re: 車を量産させる方法

投稿記事by tkar » 2023年2月05日(日) 08:59

名無し蛙さん
ご回答ありがとうございます!
そんな方法があるんですね…!

スクリプト初心者なので全くと言っていいほど読み解けませんが、
多分この方法を使うと、いちいち置き換えなくても、制御できそうですね!

書いて頂いたスプリクトを、調べたり勉強して、色々やってみたいと思います

車のイベントを全てスクリプトで制御にして、
文字をエディタとかで変換して、
貼り付けたら、量産できるかもと思い、
トライしてみてたのですが、
ランダムの記述でつまずき、
他の動作はいい感じに動いたり、
でも、教えて頂いた方法の方が、良さそうですね

画面外で自律移動を停止してしまう問題ですが、
長くなってしまうのでここでは触れなかったのですが、
その問題に関しても、教えてくださり、ありがとうございます!
名無し蛙
記事: 302
登録日時: 2015年11月23日(月) 02:46

Re: 車を量産させる方法

投稿記事by 名無し蛙 » 2023年2月05日(日) 14:14

読み解く意思があるならコメントを振っておきましょうか。
ついでにちょっとだけ処理順序を弄って最適化しました。

コード: 全て選択

/*:
 * @target MZ
 */

(() => {
    'use strict'
    // 立っているマスと同じリージョンの隣接マスに向けて一歩前進する移動コマンド
    Game_Character.prototype.moveRegionRoute = function() {
        // 下(2)、左(4)、右(6)、上(8)の移動候補の中から
        const candidates = [2, 4, 6, 8].filter(d => {
                // イベントの逆方向の向きを除外
                if (d === this.reverseDir(this._direction)) return false;
                const x = this.x + ((d === 4) ? -1 : ((d === 6) ? 1 : 0));
                const y = this.y + ((d === 8) ? -1 : ((d === 2) ? 1 : 0));
                // 隣接マスのリージョンIDを取得
                const regionId = $gameMap.regionId(x, y);
                // 隣接マスと立っているマスのリージョンIDが等しいなら候補に残す
                return regionId === this.regionId();
            });
        // 移動候補が一つでも残っている場合
        if (candidates) {
            // 移動候補の中からランダムで一方向を取得
            const d = candidates[Math.floor(Math.random() * candidates.length)];
            // 取得した方向に一歩前進
            this.moveStraight(d);
        }
    };
    // 全てのイベントの画面外判定の無効化(自律移動の無効化以外にデフォルトで使っている箇所は存在しない)
    Game_Event.prototype.isNearTheScreen = () => true;
})();

tkar さんが書きました:ランダムの記述でつまずき、
他の動作はいい感じに動いたり、

ランダムの記述、とはどういう意味でしょうか?
一応現時点で前進、左折、右折が可能な場合ならランダムで一つ選出される仕様ですけど
ひょっとして交差点では異なるリージョンが交わる、とかそういう仕様ですか?

編集:this.setMovementSuccessを削除しました
最後に編集したユーザー 名無し蛙 on 2023年2月07日(火) 01:10 [ 編集 1 回目 ]
tkar
記事: 5
登録日時: 2023年2月04日(土) 10:16

Re: 車を量産させる方法

投稿記事by tkar » 2023年2月06日(月) 18:19

名無し蛙さん、ありがとうございます!

コメントを付け加えてくださり、ありがとうございます :D
難しいですが、ちょっとは理解できました!
const、prototype、functionなどを調べて勉強しました

一昨日、書いて頂いたプラグインを実際に入れて、動かしてみたのですが、
向きが変わって、その後動かなくなったので、
多分、何か仕様が違うんだろうなと思っていたのですが、
昨日、リージョン内(道路内)に住民が入らないようにするプラグインを入れていた事を思い出し、
訂正してもう一度動かしてみたら、めちゃくちゃスムーズに動いて、驚きました!
個別に定義しなくてもこんなに完璧に動くんですね

すみません><
ランダムでつまずいたというのは、
車の位置を個別に出している方法の事です
調べて、スクリプトで書いてみたのですが、記述が何か間違ってるのか、左折しかしないんです^▽^;
必要ないかもしれませんが、こんな感じです
信号ありの十字路のページの一部です

コード: 全て選択

if($gameVariables.value(102/*車2の乗っているリージョン*/) == 8){
    if($gameSwitches.value(310/*横が信号青*/)){
        this.character(0).forceMoveRoute({
       "list":[{"code":3},
       {"code":0}],
       "wait":true
        })
        $gameSwitches.setValue(325/*車2左から入る*/,true)
    }
}

コード: 全て選択

if($gameVariables.value(102/*車2の乗っているリージョン*/) == 43){
    if($gameSwitches.value(325/*車2左から入る*/)){
        $gameVariables.setValue(68/*ランダム2*/, Math.round(Math.random()*3)+1)
        if($gameVariables.value(68/*ランダム2*/) ==1){
            this.character(0).forceMoveRoute({
           "list":[{"code":4},
           {"code":0}],
           "wait":true
         })
         $gameSwitches.setValue(325/*車2左から入る*/,false) 
        }
        if($gameVariables.value(68/*ランダム2*/) ==2){
            this.character(0).forceMoveRoute({
           "list":[{"code":3},
           {"code":0}],
           "wait":true
            })
        }
        if($gameVariables.value(68/*ランダム2*/) ==3){
            this.character(0).forceMoveRoute({
           "list":[{"code":3},
           {"code":0}],
           "wait":true
            })
        }     
    }
    if($gameSwitches.value(328/*車2下から入る*/)){
        if($gameVariables.value(68/*ランダム2*/) ==2){
            this.character(0).forceMoveRoute({
           "list":[{"code":4},
           {"code":0}],
           "wait":true})
            $gameSwitches.setValue(328/*車2下から入る*/,false)
           
        }
        if($gameVariables.value(68/*ランダム2*/) ==3){
            this.character(0).forceMoveRoute({
           "list":[{"code":3},
           {"code":0}],
           "wait":true})
        } 
    }
    if($gameSwitches.value(326/*車2右から入る*/)){
        if($gameVariables.value(68/*ランダム2*/) ==3){
            this.character(0).forceMoveRoute({
           "list":[{"code":3},
           {"code":0}],
           "wait":true})
            $gameSwitches.setValue(326/*車2右から入る*/,false)
        }
    }
}

capture5380_2023.02.06 .jpg

実際のマップではないですが、こんな感じになっています
歩道がある交差点は信号があります

なんかめちゃくちゃ複雑になっていてすみません^^;
もっといい方法があると思うのですが、
隣が、とか高度な事ができないので、
シンプルにリージョンごとに右に進む、とか決めています


複雑なので、ちょっと説明しますね

1、2、3、4は乗っていたら右、左、下、上に進む

101、102、103、104は、住人が通る事のできる場所として分けてありますが、車の挙動は、101は1、102は2、、、と同じ

信号は、縦横で切り替わります
全て同じタイミングで統一しています
横が青スイッチ(310)、縦が青スイッチ(311)(黄色の時とかあるのでそれぞれ分けてあります)

信号ありの十字路は、8、9、10、11で信号が青かどうかで進むか止まる、同時に車2がその方角から入ったスイッチをON
(8なら左から入ったスイッチ(325)をON)

信号ありのT字路は24、25、26で信号が青かどうかで進むか止まる、同時に各方角から入ったスイッチをON
今気づいたのですが、これ、8、9、10、11と同じでも大丈夫ですね;
交差点ごとにページを変えてるから変えなくても大丈夫でした^^;

信号なしの十字路 20、21、22、23は信号は関係なくそのまま侵入、どの方角から入ったかのスイッチをON

信号なしのT字路 16、17、18は信号は関係なくそのまま侵入、その方角のスイッチをON
(20、21、22、23と同じで大丈夫でした)

信号なしの上下逆のT字路 40、41、42は信号は関係なくそのまま侵入、その方角のスイッチをON
(20、21、22、23と同じで大丈夫でした)

交差点上の43、44、45、46
左上、43の挙動は、6こ
これまた複雑なので画像を用意しました
画像の矢印のパターンがあります
左からは3こ、下からは2こ、右からは1こ
同様に44、45、46も6こ
20230206_152618  .jpg

31、32は端なので、逆方向の端にランダムで移動させる

長くなってすみませんm(_ _)m
こんな感じのマップになっています
名無し蛙
記事: 302
登録日時: 2015年11月23日(月) 02:46

Re: 車を量産させる方法

投稿記事by 名無し蛙 » 2023年2月07日(火) 01:09

なるほど。矢印床みたいにけっこうガッチリ決まってるんですね
それなら単純にswitch文で今現在のリージョン判定した方が簡単そうな気がしますね
とりあえずリージョン1,2,3,4(101,102,103,104)の動きだけ定義するならこんな感じですか

コード: 全て選択

    Game_Character.prototype.moveTest = function() {
        // 立っているリージョンIDが
        switch (this.regionId()) {
        // 1と101の場合
        case 1:
        case 101:
            // 右に移動
            this.moveStraight(6);
            break;
        // 2と102の場合
        case 2:
        case 102:
            // 左に移動
            this.moveStraight(4);
            break;
        // 3と103の場合
        case 3:
        case 103:
            // 下に移動
            this.moveStraight(2);
            break;
        // 4と104の場合
        case 4:
        case 104:
            // 上に移動
            this.moveStraight(8);
            break;
        }
    };

これを少しずつ拡張していけば目当ての仕様に近づくのではないかなぁと。
ついでにthis.setMovementSuccessの記述は不要な事に気付いたので削除しました。
主に使いそうなコードを簡単に書くと

コード: 全て選択

// 2,4,6,8を指定するとその方向に移動します
// ちなみに2468とはテンキーの位置2(下),4(左),6(右),8(上)に対応しています
this.moveStraight(d);

// 一歩前方に前進する
this.moveForward();

// 現在のキャラクタの向きを2,4,6,8で取得します
const d = this.direction();

// 指定された向きの後ろを2,4,6,8で取得します
const d = this.reverseDir(this.direction());

// 配列の中からランダムで1要素をチョイスする
const array = [2, 4, 6, 8];
const d = array[Math.floor(Math.random() * array.length)];

// (応用)前方、左方、右方の中からランダム一方向に前進
let array = [2, 4, 6, 8];
array  = [2, 4, 6, 8].filter(d => d !== this.reverseDir(this.direction()));
const d = array[Math.floor(Math.random() * array.length)];
this.moveStraight(d);

この辺ですかね。
tkar
記事: 5
登録日時: 2023年2月04日(土) 10:16

Re: 車を量産させる方法

投稿記事by tkar » 2023年2月08日(水) 14:57

名無し蛙さん
表記の仕方、とても助かりますm(_ _)m

早速打ち込んこんでみました!
仕様に合わせてリージョンも置き換えたりして、
かなり理想的な挙動をしてくれるようになりました!
感激です

そこでちょっとお聞きしたいのですが、
「左から入った場合」と、条件を指定しなくてはいけない場面があるのですが、今のところ、その車限定のスイッチを使用しているのですが、
やはり調べてみても、わからなくて、
よかったら教えて頂けないでしょうか?

よろしくお願いしますm(_ _)m

あと、もう1点、
端に行った時に、ランダムで逆方向の端に移動するという仕様を実装したいのですが、
調べて何通りか試してみたのですが、エラーが出たり、止まったままになったりして、わからなくて、
宜しければそちらも教えて頂けないでしょうか?

お手数おかけして申し訳ございません。

test.gif
test.gif (224.6 KiB) 閲覧数: 783 回
名無し蛙
記事: 302
登録日時: 2015年11月23日(月) 02:46

Re: 車を量産させる方法

投稿記事by 名無し蛙 » 2023年2月08日(水) 22:40

tkar さんが書きました:そこでちょっとお聞きしたいのですが、
「左から入った場合」と、条件を指定しなくてはいけない場面があるのですが、今のところ、その車限定のスイッチを使用しているのですが、
やはり調べてみても、わからなくて、
よかったら教えて頂けないでしょうか?

「左から進入した」という事は「車体は右を向いている」という事です。

コード: 全て選択

const d = this.direction();
if (d === 6) {
}

で事足りると思うのですが、
これでも不足する部分があるという事でしょうか?(往復二車線道路でUターンを禁止する為?)
イベント依存のスイッチが欲しいのならば

コード: 全て選択

// 名前は自由に決めて良いですけど慣例として
// ①内部的に使用する変数は最初に_(アンダーバー)を付ける
// ②2語以上の単語の連なりの場合、最初の単語の頭文字は小文字、2つ目以降の頭文字を大文字にする
// という変数の命名規則が存在します
// スイッチへの代入
this._switch1 = true;
// スイッチの判定
if (this._switch1) {
    // 処理
}
this._var1 = 6; // 変数でも良いし
this.変数2 = 2; // 全角文字も一応使用可能です
if (this._switch2) {
  // 未定義の状態で判定するとundefinedが返り偽判定になります
}

等、適当に作って良いです。
が、バグの温床にもなるので変数・スイッチを作る場合は必要最小限が好ましいです。
このスイッチはセーブ時のマップ情報に含まれますが、マップ切り替えする事でリセットされます。

tkar さんが書きました:端に行った時に、ランダムで逆方向の端に移動するという仕様を実装したいのですが、

同マップの特定の位置にワープさせたいんですか?

コード: 全て選択

this.setPosition(x, y);

で移動すると思います。
tkar
記事: 5
登録日時: 2023年2月04日(土) 10:16

Re: 車を量産させる方法

投稿記事by tkar » 2023年2月10日(金) 15:46

名無し蛙さん
いつもありがとうございますm(_ _)m

そうですね
すみません説明がわかりにくかったですね
「左から入った場合」というのは、交差点に入る時にどの方角から入ったか、という意味ですm(_ _)m

そうなんです!二車線でUターンをさせないために必要で……

入った方角を条件にいれていないと、交差点のリージョンに乗った時に、交差点内を永遠にぐるぐる回るという挙動も発生してしまうため、スイッチの表記の仕方を、質問させて頂きましたm(_ _)m

詳しく説明も入れてくださり、ありがとうございます!
教えて頂いたお陰で、思い通りの挙動を完成させる事ができました!
スイッチを全て置き換えなくても、イベントをコピーするだけで、車を沢山配置する事ができました

本当にありがとうございますm(_ _)m

test2.gif
test2.gif (614.03 KiB) 閲覧数: 678 回

“MZ:質問” へ戻る