ゲームに新しいオーバーワールドのメカニクスを導入したいのですが、新しい操作方法をどのように追加すればよいかがわかりません。
例えば、Zキーを押したときに一時的なダッシュ移動を実行させたい場合、Zキーでイベントで定義したアクションを実行するにはどうすればよいでしょうか?また、異なるキャラクターを操作しているときに、そのキーの機能を切り替えられるようにすることも可能です。
同様に、これらのボタンがキーボードだけでなくコントローラーでも操作可能にするにはどうすればよいでしょうか?
ゲームに新しいオーバーワールドのメカニクスを導入したいのですが、新しい操作方法をどのように追加すればよいかがわかりません。
例えば、Zキーを押したときに一時的なダッシュ移動を実行させたい場合、Zキーでイベントで定義したアクションを実行するにはどうすればよいでしょうか?また、異なるキャラクターを操作しているときに、そのキーの機能を切り替えられるようにすることも可能です。
同様に、これらのボタンがキーボードだけでなくコントローラーでも操作可能にするにはどうすればよいでしょうか?
私の理解では、MZにおけるキーボードとコントローラーのマッピングはrmmz_core.js内の2つのオブジェクト、Input.keyMapperとInput.gamepadMapperに格納されています。それぞれは、キーコードまたはボタンインデックスを「ok」や「shift」のようなアクション名にマップしているだけです。注意点として、Zキーはデフォルトで決定ボタン(キーコード90 → “ok”)として割り当てられているため、これをダッシュに割り当てると決定ボタンが使えなくなってしまいます。既存のキーを避けるか、そのトレードオフを許容できるならZキーを維持してもよいでしょう。
私が考える実装方法は、js/pluginsフォルダ内に小さなプラグインファイルを作成し、両方のマップに新しいアクションを追加することです。例えば以下のようになります:
Input.keyMapper[67] = "dash"; // Cキー
Input.gamepadMapper[6] = "dash"; // ボタン6(通常はトリガー)。0〜5および12〜15は既に使用済み
その後、並列イベントとして設定された共通イベントを作成し、条件分岐→スクリプトタブでInput.isTriggered("dash")をチェックし、その中にダッシュ用のイベント処理を記述します。キャラクターごとの処理については、さらに条件分岐をネストして、パーティの先頭にいるキャラクターを確認します。これは、キャラクター切替時にON/OFFするスイッチを使用するか、$gameParty.leader().actorId() === 2のようなスクリプトチェックを行い、それぞれに異なるイベント処理を実行するのがよいでしょう。
コントローラーのサポートは、gamepadMapperに追加するだけで自動的に有効になります。Input.isTriggeredは、入力がキー由来なのかボタン由来なのかを区別しないためです。
完全に理解できているかどうかわかりませんが、試してみます。Dashは、私が実行できるアクションの例として挙げただけです。
プレイヤーが押せるボタンを4つ用意し、それぞれが異なるアクションを実行してほしいのです。
並列処理+条件分岐+ボタン押下という部分は理解しています。
キーボードのZ、X、A、Sをボタンとして割り当てたいと考えています。この場合、Z(OK)とX(メニュー)は、対応するマップではメニューを開けないため問題ありません。
ここで困っているのは、実際に新しいボタンを定義し、それを条件分岐に組み込む方法です。
エディターにはそれを定義する場所がなく、名前はプラグインファイル内で自由に作成する文字列です。すでに Input.keyMapper に登録されていないキーは自由に使用できます。
4つのキーの場合:
Input.keyMapper[90] = "action1"; // Z
Input.keyMapper[88] = "action2"; // X
Input.keyMapper[65] = "action3"; // A
Input.keyMapper[83] = "action4"; // S
これを js/plugins フォルダー内に .js ファイルとして保存し、プラグインマネージャーで有効にします。A と S はデフォルトでは何にも割り当てられていません。Z と X はそれぞれ「OK」と「ESC」に割り当てられているため、独自の名称を割り当てることでそれらの機能が上書きされますが、Enter キーは依然として OK の役割を果たし、Space キーは ESC の役割を果たすため、メニューは正常に動作し続けます。
条件分岐では、[ボタン] ドロップダウンにはエンジン固有の名前しか表示されないため、新しく作成した名前は [スクリプト] タブに記述します:
Input.isTriggered("action1")
その後、分岐ごとに名前を切り替えます。isTriggered は1回押した瞬間の判定であり、キーを押し続けている間に連続して発火させたい場合は Input.isPressed を使用します。
わかりました!
この文脈でZとXを使用すると、すべての状況でOKとEscapeが上書きされてしまうのでしょうか?
ああ、keyMapper はグローバルだね。ゲーム全体でキーコードごとに1つの名前しか割り当てられないから、そのプラグインが実行されると、Z はメニューや戦闘中を含めてどこでも「アクション1」になってしまうよ。
でも、ランタイムで切り替えることはできるよ。ただのオブジェクトだからさ。プレイヤーがそのマップに入ったときに、オートランか移動イベントで Script コマンドを実行すればいいんだ:
Input.keyMapper[90] = "action1";
Input.keyMapper[88] = "action2";
そして、マップを離れたときに元に戻すんだ:
Input.keyMapper[90] = "ok";
Input.keyMapper[88] = "escape";
どちらの切り替え直後に Input.clear() を呼び出すことをお勧めするよ。そうすれば、すでに押されていたキーの状態が変更後に引き継がれてしまうのを防げるから。
ああ、なるほど。4ボタンマップにプレイヤーを移動させる共通イベントの最初に、
Input.keyMapper[90] = “action1”;
Input.keyMapper[88] = “action2”;
Input.clear()
を配置しました。
そして、4ボタンマップからプレイヤーを退出させる共通イベントの最後に、
Input.keyMapper[90] = “ok”;
Input.keyMapper[88] = “escape”;
Input.clear()
を配置しました。
つまり、これらのスクリプトコマンドを挿入することで、プレイヤーがその設定を指定したマップにいる間のみ、action1とaction2、およびokとescapeが別の機能として共存できるということですね?
ほぼそうです。キーコードは一度に1つの名前しか保持しないため、プレイヤーがそのマップにいる間、Zは「action1」であり、それ以外は何もありません。OKとEscapeがそこで機能し続けるのは、それらが他のキー(OKはEnterとSpace、EscapeはEsc、Insert、およびテンキーの0)にも割り当てられているからです。それらのキーは変更されていませんでした。
注意すべき点はセーブです。keyMapperはセーブファイルの一部ではないため、プレイヤーが4ボタンマップの状態でセーブし、後にそのファイルを読み込むと、ZとXが再びOKとEscapeとして認識され、それらを再設定するための共通イベントが実行されません。
その場合、私はおそらく最初の半分をマップ自体に配置された並列処理イベントに移動します:
Input.keyMapper[90] = "action1";
Input.keyMapper[88] = "action2";
Input.clear();
その後、すぐにイベント消去(Erase Event)を追加して、それが1回だけ発火するようにします。イベント消去はマップを離れると解除され、マップを再設定すると再び有効になるため、そのマップの新しい読み込み時(セーブファイルからの読み込みを含む)に毎回実行されます。退出用の共通イベントは、現状のままにしておくことができます。
了解しました。その通りにして、共通イベント送信者からそれを削除しました。
4ボタンマップには、ボタンを定義するための並列処理イベントがあります。
条件分岐を設定し、(スクリプト-if アクション1がトリガーされた場合)
(それが動作していることを証明するためにテキストボックスを表示)
としました。
そして、4つのアクションすべてに対してそれを行いました。しかし、ZXASを押してもテキストボックスが表示されません。何か間違えましたか?
条件分岐が同じイベント内に配置されている場合、[イベントの消去] はそれらに到達する前に処理全体を停止してしまうため、キーが設定された後、それらを確認する処理が実行されません。
もう一点は、前の投稿での私の誤りです。消去されたイベントはマップから離れて戻ってくると復活しますが、消去状態はセーブデータの一部として保存されるため、プレイヤーがそのマップ上でセーブした場合、ロードしてもイベントは消去されたままになります。これが私がその対応でカバーしようとしていた具体的なケースです。
そこで、[イベントの消去] を削除し、並列イベント1つで両方の役割を担わせるようにします:
Input.keyMapper[90] = "action1";
Input.keyMapper[88] = "action2";
Input.keyMapper[65] = "action3";
Input.keyMapper[83] = "action4";
そして、そのイベント内の下部に4つの条件分岐を配置します。並列イベントは毎フレームリスト全体を実行するため、マッピングは常に再適用され、コストはかかりません。ただし、Input.clear() はこのイベントには含めないでください。これは現在の入力をクリアしてしまうため、毎フレーム実行すると条件分岐が入力を見る前に入力が消費されてしまいます。
終了用の共通イベントは、そのままで構いません。
確認すべき点として、プラグインファイルにまだ 90 と 88 が残っている場合は、それらの2行を削除してください。さもないと、Z と X は特定のマップでのみ有効になるのではなく、起動時から action1 と action2 として設定されてしまいます。
ボタンを定義する条件分岐は、アクション1〜4の設定とは別に、並列処理イベントとして独立して存在していましたが、あなたの指摘を受けて、設定部分をボタン定義イベントの上部に移動し、すべてを統合しました。(Input.clear()を除く)
今からプラグインファイルを確認します。
分岐はすでに独立した並列イベントとして存在していたため、Erase Event(イベント消去)が分岐をブロックしていたわけではありません。そのため、これらを組み合わせただけでは何も変わらない可能性があります。まずテストを行い、それでも反応しない場合は以下の手順を確認してください。
セッター(変数設定)を移動した際に、Erase Event が一緒に移動していないか確認してください。もし結合されたイベント内に Erase Event が含まれている場合、分岐が実行される前にイベント全体が終了してしまいます。
一時的に分岐の1つのスクリプトを Input.isTriggered("ok") に変更し、マップ上に立っている状態で Enter キーを押してください。テキストボックスが表示される場合、イベント自体とテキスト表示は正常であり、問題はキー名の側にあることを意味します。“ok” を押しても何も表示されない場合、イベントが全く実行されていないため、ページトリガーが「並列処理」になっているか、ページ条件がすべてオフになっているか、そしてイベントが実際に立っているマップ上にあるかを確認してください。
そのマップでのプレイテスト中に F8 キーを押してコンソールタブを開き、Input.keyMapper[90] と入力して Enter を押してください。“action1” と出力されるはずです。もし “ok” と出力される場合、セッターが効いていないことになります。
分岐の1つのスクリプト行の正確なテキストを投稿してください。セッター内の名前とチェック内の名前は、大文字小文字を含めて完全に一致し、スペースがあってはなりません。
イベントページのスクリーンショットも役に立ちます。それらが見えれば、具体的な問題を指摘できます。