コミュニティアイコン プチコン 非公式コミュニティ トピック

アバター
say ◆1nbKtD/tFu04
2017/11/26 19:38
質問
妙な現象?
1:while 1
2: vsync
3: b=0
4: while !b
5: b=button(2)
6: wend
7: if !b then ? b
8:wend

上記のコードを実行すると、button関数の動作がおかしくなるようです
vsyncを実行すると、button関数はリセットされる(らしい)のですが、上記コードではリセットされることもなく、重複されるようです
5: b=button(2):vsync
とすれば回避できる話ですが、どうも理屈がわかりません

コメント

アバター
say 2017/11/26 19:46 ◆1nbKtD/tFu04
単に理解が間違っていた と言うのなら、説明を付けて指摘してくれると嬉しいです
アバター
あまさとしおん 2017/11/26 20:42 ◆mzDKTVUAtwqE
4行目から6行目の間にVSYnCがないからでは?
アバター
あまさとしおん 2017/11/26 20:44 ◆mzDKTVUAtwqE
と思ったら、5行目にVSYNCを足すと回避できるって書いてあったorz...
うーん。説明の仕方が分からん
アバター
あきと 2017/11/26 20:58 ◆7TEpcjb/rk2E
sayさんが理屈にあっていないと感じる部分をもう少し詳しく教えてもらいたいのですが、
上のコードを実行すると「どのように」BUTTON関数の挙動がおかしくなりますか?
本当は…のようになるはずが、実行してみるとこうなると書いてもらえるでしょうか。
アバター
say 2017/11/26 21:09 ◆1nbKtD/tFu04
button()の前後にvsyncがあったら問題ない(と言う話の)はずなんだけど、それが効かないから困ってるのよ
流れからして、嫌でもvsyncを通したあとにbutton()が呼ばれてるのに、それがなんでか無効になってる感があるから質問を投げたワケで…
となると、理解が間違ってるくさい と言うことになるんで、質問した次第ですハイ

スコープ?の深さ?により、vsyncの優先度が下がる?
…うーむ…
アバター
こういち 2017/11/26 21:13 ◆ou0jbJnEJ0Kb
sayさんが言いたいのは2行目でVSYNCがあるのにボタンを押した直後に4〜6行目が無視されてしまう
ということだと思います。
チャタリング…ではなさそうですね。
アバター
New3DS大豆マン 2017/11/26 21:14 ◆2FCk4r5A9R8g
vsyncじゃなくてwait 2なら予想通りの挙動になりますが、
vsync n(nは1以上)の場合は変になりますね。
うーん、これは難しい...
アバター
say 2017/11/26 21:22 ◆1nbKtD/tFu04
1〜8ループ(外ループ)は、ボタンを一回押すと一回ループされるはずなんですが(理由は外ループ内の処理を読んで下さい)、それがボタンを一回押しただけにも関わらず、二回(時として三回)ループします

内処理に問題があるというより、「理解が間違ってる?」と言うのが、今のところの判断なんですが、どう理解したらいいのかがわかりません
アバター
おちゃめ 2017/11/26 21:32 ◆jH1opV6FnGyx
VSYNCを実行するとBUTTON()の戻り値が初期化されるという認識は正しくありません。
BUTTON()関数は表示更新のたびに戻り値を更新しているだけであって同一フレームの間は同じ値となります。

私のサイトのプチコン3号入門講座のBUTTON()関数のページを参照
http://ochameclub.web.fc2.com/petitcom3/lecture/button.htm

では、なぜVSYNCを付けるのが推奨されているのかというとその表示更新のタイミングまで待つためです。これによって、BUTTON()関数の誤動作を軽減することができます。

しかし、これですべてが説明できるかというとそうではありません。
VSYNCのタイミング(表示更新のタイミング)とBUTTON()関数等の戻り値の更新タイミングでは微妙なずれがあるためだからです。
このずれによってBUTTON(2)が0になるタイミングでは表示更新のタイミングを迎えておらずもう1回VSYNCを挟まないと正常な動作ができないというわけです。

私のサイトのプチコン3号入門講座のVSYNC、WAITのページにおいて表示更新のタイミングとフレームの区切り線が微妙にずらして書かれているのはこの微妙なずれがあるというのを視認できるようにするためです。
http://ochameclub.web.fc2.com/petitcom3/lecture/vsync.htm

しかし、普通にBUTTON()関数の値が0になったかの判断ではなくVSYNCの更新ごとにBUTTON()判定を行えばこの微妙なずれを意識する必要はないため特に解説は行っていません。(必要ならば次の更新の機会に書き加えます)
アバター
myu314 2017/11/26 21:34 ◆gfQW2/zTwMto
なんというかバグというか仕様みたいなのに引っかかってる予感です。
とりあえず7行目は単純に?B でよいのでは:)
あと現象理解するには、4〜6のWHILE/WENDの前後に?MAINCNTを入れると良いです。何故かフレームまたがってBUTTON(2)が反応しちゃってるって現象が確認できます。
理由の1つは簡単で、VSYNCって前のフレームから指定フレーム以上進んでないときだけ次のフレームまで待つ命令なので、WAITがかからず同じフレームを繰り返すためBUTTON(2)が反応します。
で、これだけならVSYNCをWAITに変更してやれば問題無いはずなんですが、そうはなりません。
想像ですが、別スレッドで動いてるシステム(プチコン)側の処理の仕方がまずくて、タイミングによっては(フレーム境界で)矛盾した値が取得できちゃうんじゃないかなーと。
アバター
しんいち 2017/11/26 22:34 ◆lHy.hAWXbthn
起きてる現象は実はそんなに難しくないんだけど、説明がややこしいかな。
1つ目は、BUTTON()関数で値を取得する時は、1フレームあけないと前のBUTTON()の値が残ってるということ。それがBUTTON(2)でも。
2つ目は、VSYNCは前のVSYNCからの経過時間が既に過ぎていれば待たないということ。
この2つの理由により、2:VSYNCがあるけど、4〜6のボタン入力待ちループで時間過ぎちゃって、ボタン押して4〜6ループ抜けて?Bの後、2:VSYNCに行っても時間過ぎてるから待たれなくて、また5:B=BUTTON(2)に行った時に前回のBUTTON(2)から1フレーム経ってないからBに前の値が入って、直ぐに4〜6ループ抜けてまた?B、その後の2:VSYNCは4〜6ループ直ぐに抜けてるからVSYNC有効でちゃんと待たれて、その後の5:B=BUTTON(2)は前回のBUTTON(2)から1フレームあいてるから前の値が残ってない。
ということが起きてるのかと。
#やはり説明ややこしい^^;
アバター
たんじぇ 2017/11/27 11:16 ◆rgeRmwbR2YXi
WHILE-VSYNC-WEND が「ゲームループ」と呼ばれるもので、1秒で60回呼ばれる処理(1/60秒で1回処理)されることが、ほとんどのゲーム作りというか、画面で何か動かすときのプログラムの作りの基本になります。
この1/60秒で画面表示や更新やボタン処理などをする作りになります。

(windowsとかHTML+javascript とかはまた作りが違ってて、あっちはOS側から画面更新してとかキーボード情報が押されたよとか通知がくるイベントドリブンという方式)

1秒に60回処理させるのが一般的ってのが、わりと一般的すぎてなかなか説明されないことが多いのです。

ゲームの液晶画面もTVもブラウン管時代のTVも1秒に60回の画面更新があって、
1回の画面更新の終わりの信号が垂直同期信号といってVSYNC という名前なのです。(細かいこと言うとTVは1秒に約60回であって正確に60回ではないけど詳しく知りたい場合は「NTSC信号」を検索)

なので、1回の画面更新が終わったちょうどいいタイミングで、プチコン内部としても3DS/WiiUのボタン情報を取得して、プチコンに扱える情報として更新していて、プチコンはBUTTON関数でボタン情報を返しているという仕組みです。(BUTTON関数がVSYNCで更新される おちゃめさんの説明)

投稿プログラムのなにが間違っているかと言うとなれば、WHILE-VSYNC-WEND の中に、VSYNCを使わない無限ループが存在しているので、1秒に60回更新の処理が行われなくなる作りが間違いということになります。

なので「BUTTONと一緒にVSYNCを使うと正しく動く」というのは、
WHILE-VSYNC-WENDの中に、さらにVSYNCがあるゲームループができあがることによって、BUTTON関数が正しく動作するようになるということです。
アバター
たんじぇ 2017/11/27 11:26 ◆rgeRmwbR2YXi
(miiverse時代だとこのくらいの長さでも投稿文字数制限ひかっかってたので回答する側は便利な時代!)

プチコンは思ったようにコードが書けて、設計はあんまり気にしなくても動作するのが利点なので、あんまりちゃんとした設計をしなきゃみたいなことは押し出したくないところだけど、
そういった設計がプチコン内部では行われているので、どうしてもVSYNCにからむところは内部のつくりというか、コンピュータでプログラムすることを意識しないといけなくなってしまうのです。
アバター
私は誰? 2017/11/28 7:38 ◆ECSI85YSg0OW
VSYNCさんの役割考えると、ループの頭に居たり、そもそもループの中にいなかったりしてる時点で、違和感有りまくり。

(多重ループの場合なら中心の)ループの終了の直前に存在するのが、自然な感覚。
(理屈でなく個人的な感覚)
アバター
キルル2 2017/11/28 12:23 ◆rGE712Ruejv7
そのコードを書いて実行してみましたが、特に挙動がおかしいと感じた部分はありませんでした
ただ、1回ボタンを押しただけで2回か3回ループが回るので、求めている挙動とは違うということでしょうか
原因については、既に沢山の方々が解説してくれていますね

コメントを書く

  • こちらは「プチコン3号」「プチコンBIG」など、プチコンシリーズに関する話題を扱ったコミュニティです
  • プチコンシリーズにまったく関係ない書き込みはご遠慮下さい。削除の対象となります
  • こちらにはその他のゲームや雑談のコミュニティはなく、作る予定もありません (ひとりで管理できないため)。ごめんなさい
  • ユーザー登録なしで書き込みができます
  • 秘密の合い言葉は成りすましの防止 (トリップ機能)、書き込みの編集時の本人認証に使用します
  • 秘密の合い言葉に他人に推測されやすい言葉、他サービスと同じパスワードは入力しないでください。
  • 書き込むと、投稿時に入力したお名前と秘密の暗号が記憶され、ログイン状態になります

- WEB PATIO -