2024-12-02

RGSS-ボタン処理の入ったループをなめらかにする(連打イベントなど)

Comment ShareLink

今回はループ処理でボタン入力をなめらかにする方法を書いておきます。

イベントコマンドのループ処理は、ウェイトを挟まないとエラーが起きます。
ウェイトは1の値で1/20秒。
イベントでの演出で待たせるのはこれで良いのですが、連打イベントや自作メニューなどボタンを押す処理の入ったループをデフォルトのイベントコマンドで作成する場合はどうしてもウェイト部分でぎこちなくなってしまいます。


例としてボタン処理を使うループを以下のように組んでみます。
カウントされてるか確認するために画面の左上にカウント表示のスクリプトも入れてみましょう。
※ここでは連打を想定して「ボタン~が押されている」ではなくスクリプトの「Input.~」を使用

スクリプト : $count = Sprite.new
:      : $count.z = 9999
:      : $count.bitmap = Bitmap.new(160,160)
:      : $count.bitmap.draw_text(16,16,160,32,
:      : "#{$game_variables[1]}")
 ←例で使う変数1
ループ
 ◆ウェイト : 1 フレーム
 ◆条件分岐 : スクリプト : Input.trigger?(Input::C) or Input.repeat?(Input::C)
  ◆変数の操作 : [0001: 連打数] += 1
  ◆スクリプト : $count.bitmap.clear
  :      : $count.bitmap.draw_text(16,16,160,32,
  :      : "#{$game_variables[1]}")
 カウント更新のため再描画
 ◆
 : 分岐終了

: 以上繰り返し

実際これでやってみるとわかると思いますが
反応は0.5秒、押したのにカウントされていないモッサリ感が出ます。ウェイトの只中に引っかかると余計にモッサリします。
視覚的なイベントは「ウェイト」で良くても、即座にボタンの押下が必要なイベントには不向きなんです。


ここでは解決方法3通り紹介しておきます。

初期のイベントコマンドだけで済ませる

全てデフォルトのままのイベントコマンドで組みたいなら
「並列処理」で実行される別のイベント(もしくはコモンイベント)を作成して、実行トリガーにスイッチを設定。
本イベントにループを入れる直前に並列処理イベントを実行するスイッチをONにしてループを開始すればOK。

[本イベント]
 スイッチON
 ループ開始
  ~ウェイト
  ~条件分岐で条件が合えばスイッチOFF、ループ中断

[並列処理イベント(別のイベントかコモンイベントで作成)]
☆実行条件・スイッチON
 条件・ボタン処理
…以上!

ウェイトの代わりにGraphics.updateを入れる

イベントコマンドのウェイトが単純に1/20秒だから反応が遅いわけで、それならループでウェイトを使わずエラーも起きないようにすればいいじゃん?
ということで、
ウェイトの代わりにスクリプトコマンドで「Graphics.update」を入れます。
ループ処理にウェイトを入れないとエラーを吐くのは、長い間画面が更新されずに延々とスクリプトがループすると「不具合起きた?」と判断されるからなんです。スクリプトハングアップな感じになる前にエラって強制終了されるわけです。
だからGraphics.updateを入れてあげれば、ループをそのまま実行できるわけです。
ただ、イベントコマンドのウェイトにはボタン入力も受け付ける処理が備わっていますが、Graphics.update単体は「ボタン入力?ナニソレ?」なんです。ただ画面の更新を行うだけの機能なんです。
だからもうひとつ「Input.update」も一緒にスクリプトコマンドに入れてあげることでボタン入力にも対応できるようになります。

Graphics.update
Input.update

これをループ内のウェイトの代わりに入れるだけ。
問題があるとすれば画面更新しかしてない状態になるのでマップとかアニメーションとか(ここで更新されない要素)が止まります
……問題ありすぎじゃん……

ループ処理をウェイト不要にスクリプト改造する

いちいちイベント作るのめんどいわ!
スクリプトのコピペもめんどいわ!
という人向けに、たった一行スクリプトエディタに追加するだけで終わる方法を伝授しよう…

スクリプトエディタを開く。
その中から「Interpreter 3」を開いて「●以上繰り返し」という注釈のついた項目
「def command_413」
ここのdef command_413のすぐ下に「@wait_count = 1」を追加するだけ。

def command_413
  @wait_count = 1 ←これだけ追加!
  # インデントを取得
  indent = @list[@index].indent
  # ループ
  loop do
   :

これでイベントコマンド「ループ」の中にウェイトを入れなくてもエラーが起きなくなります。
ここでwait_countを1入れるとウェイトされた時の画面更新処理が実行されるわけです。
もう忘れたけどウェイトコマンドは「指定した値*200」になっているんだとかなんだとか。
1と200だとだいぶ違うね。うん。


とまあこんな感じです。
最後の一行だけ追加してスクリプト改造するのが一番ラクかなーと思います。手間もかからないし、ループでいちいちウェイト入れなくても良くなるので。
これで連打イベントも楽に作れるのでぜひ使ってみてください。

category: ,

コメントを投稿