S-H-GAMELINKS / Novel.Game.Engine.LINKS

ノベルゲームエンジン「LINKS」
Other
13 stars 1 forks source link

セーブデータ一覧から戻ったときにメッセージが無限ループする #20

Open yumetodo opened 7 years ago

yumetodo commented 7 years ago

再現手順

  1. 起動する
  2. 「LOAD」を選択する
  3. 「ロード画面に移行しますか?」で「はい」にカーソルを合わせ、Enter
  4. 「戻る」を選択する
  5. 「戻りますか?」で「はい」にカーソルを合わせ、Enter
  6. 「ロード画面に移行しますか?」で「いいえ」にカーソルを合わせ、Enter
  7. 無限ループ

6でマウスやNキーを押した場合は無限ループしないが、そもそも「ロード画面に移行しますか?」がでるのがおかしい。

yumetodo commented 7 years ago

メッセージはSAVEDATA_LOAD()関数から出ている。これが呼ばれるのはGAMEMENU_CHOICE(), SHORTCUT_KEY(), TITLE_MENU_CHOICE()関数からで、概ねいずれも

        //ロード
        if (GAME_y == (game_menu_base_pos_y * 2) && CheckHitKey(KEY_INPUT_RETURN) == 1 || GAME_y == (game_menu_base_pos_y * 2) && ((GetMouseInput() & MOUSE_INPUT_LEFT) != 0)) {

            //セーブデータロード処理
            SAVEDATA_LOAD();
            WaitTimer(300);
        }

のようなコードである。

つまり、「戻りますか?」で「はい」にカーソルを合わせ、Enterを押したときの判定が残っているため、と考えられる。

yumetodo commented 7 years ago

キー判定が残っていることの対策は戻る前にキー判定がすべて消えるのを待つことになるが、コードが煩雑になるため、できれば #21 のアプローチでfixしたい。

S-H-GAMELINKS commented 7 years ago

以前、開発途中で同じ現象に遭遇したことがあります。

カーソルの位置とEnterでのメニュー選択をしていたことによって、メッセージボックスでのEnter入力をメニュー画面のキー判定と認識して処理していたことが原因でした。

その時は、WaitTimer()を使用して、処理をストップさせてキー入力が行われないように処理しましたね。

S-H-GAMELINKS commented 7 years ago

おそらく、他なメッセージを呼び出しているものでも同様のケースが考えられますね。

ちなみに、確認した限りでは、ゲームメニュー関連は問題ありませんでした。

が、タイトルでEscapeキーでのゲーム終了メッセージでも同様の現象が確認されました。

wakin- commented 6 years ago

マストドンの方で気になっていたので見てみました。 マウス操作の場合は左クリックの「ダウン→アップ」という2操作で次の状態に進みますが、キー操作の場合「ダウン」という1操作で次の状態に進んでいて、これが次の状態でも効いてしまっているようです(キーを押した指が上がっていない)。 キー操作でも「ダウン→アップ」の2操作を要するようにすればユーザの操作を拾いやすくなるのかな、と思いました。

加えて、TITLE_MENU_CHOICEの中でSAVEDATA_LOAD_LOOPが回っているようなので、

とした方が良いのでは、と思いました。

yumetodo commented 6 years ago

ゲームのwhileはひとつにする

これはコードが管理不能になってしまうので避けたいです。状態が分離していません。ループの中から別のループに行ってしまうのは問題ですが

左クリックの「ダウン→アップ」という2操作で次の状態に進みますが

これはどういうことでしょうか?離されたことを検知するような機能をDxLib::GetMouseInput()は有していないはずなので押下しているかのみを拾っているはずです

wakin- commented 6 years ago

左クリックの「ダウン→アップ」という2操作で次の状態に進みますが

これはどういうことでしょうか?

正確には、MessageBoxYesNoに対する操作が、マウスでは「ダウン→アップ」の「アップ」時に効いてるのに対して、キーでは「ダウン」時に効いているという事です。

yumetodo commented 6 years ago

マウスでは「ダウン→アップ」の「アップ」時に効いてるのに対して

えっ、DxLib::GetMouseInput()ってそういう挙動するんですか・・・?

S-H-GAMELINKS commented 6 years ago

いや、ちょっと違うようですね……

DxLib::GetMouseInput() 自体は、クリックされた段階(ダウン時)のみを判定しているようです。 ref:http://dxlib.o.oo7.jp/function/dxfunc_input.html#R5N8(`GetMouseInput()`の項目参照)

実際に、LINKS ver 3.20で動作確認しましたが、wakinさんが仰られている

「ダウン→アップ」の「アップ」時に効いている

という挙動は確認されています。

恐らく、メッセージボックスを表示させている関数 MessageBox()が原因じゃないかと思うのですが……

yumetodo commented 6 years ago

メッセージボックスはDxLibの範疇にないし、こちらから制御のしようもないわけですが(そのくせキー判定が暫く残る)、メッセージボックス上での挙動の話です・・・?

S-H-GAMELINKS commented 6 years ago

恐らくは、それ臭いんですよねぇ……

たぶん、MessageBox()上ではマウスの場合は「ダウン→アップ」という挙動で、キー操作の場合「ダウンのみ」なのかも……?

yumetodo commented 6 years ago

メッセージボックス上のことを言っているのでしたらそのとおりですが、その挙動にDxLib側で合わせても問題の解決にはならないし、 #28 を超えるコード量が必要になるので、何を言いたいんだろう感

yumetodo commented 6 years ago

28 を超えるコード量

というのは、実質.NETのWindowsFromにあるようなkeyeventとかボタンのイベントをだいたい実装しないと実現できないという意味です

S-H-GAMELINKS commented 6 years ago

それは……結構な量ですね……

あと、wakin さんとしては、「キー操作も、キーを離したときを拾うようにすればよいのでは?」と意見を述べられたかったのだと思います。

yumetodo commented 6 years ago

それは……結構な量ですね……

むしろGUIライブラリ作るような作業。

「キー操作も、キーを離したときを拾うようにすればよいのでは?」

メッセージボックスの挙動に干渉できる方法があるならぜひ実装してコードを投げていただきたい。

S-H-GAMELINKS commented 6 years ago

ふうむ…

とりあえずは、yumetodoさんのKeyStateクラスを使っていく方向しかないですね

yumetodo commented 6 years ago

なんかあれを作っていると、結局ノベルゲーに必要だったのはゲームライブラリじゃなくてGUIライブラリなんじゃないかと切実に感じる(WPFとか!)

S-H-GAMELINKS commented 6 years ago

確かに確かに…

そういう意味では、GUIでノベルゲームが作れるティラノビルダーとかLight.vnとかはどうやってるのやら…

yumetodo commented 6 years ago

WindowsFormとかWPFとかWin32GUIアプリからMessageBox呼んでもこの手の問題が起きないのは、DxLibがDirectInput/XInput という低レイヤを直接見に行っていて、Win32が内部的に持っているバッファを無視しているからだろうなぁ

S-H-GAMELINKS commented 6 years ago

それが、こういった形で表に出てきたわけですなぁ……

yumetodo commented 6 years ago

高速化のためのコラテラル・ダメージ