macOSで音ゲーを作る上での障壁と懸念事項

macOSで動く音ゲーを開発したい

最近SpriteKitの記事をよく書いていますが,macOSで動く本格的な音ゲーを作りたいと思いチマチマと下準備を進めていました。 前の記事で紹介したリポジトリがまさにそれです。

以前からそれらしいものを組んで検証していたのですが,音ゲーの核の部分であるタイミングが(体感的に)全くといいほど正確ではなく,どうしたものかと悩んでいて手が止まってしまい放置…というありがちな挫折の仕方を経験しました。

そこで,一旦解決していかなければならない懸念事項を挙げ,同じ失敗を繰り返さないように慎重に検証を重ねて組みなおしていこうと思いたちました。macでゲーム作る上での一番の障壁は以外と未踏の領域が多くて勝ちパターンが定まっていない(あるいはノウハウの需要がなく情報がシェアされにくい)ことだと思います。勝ちパターンを作れていけたらいいなぁという期待も込めてできるだけ音ゲー開発に関する記事は書いていきたいです。

コントローラ or キーボードからの入力

今の実装だとキーボードからの入力はmacで標準のNSResponderを継承したSKNodeのコールバックで知ることができます。コントローラに関しては,I/OKitのHIDDeviceManaerに登録した入力要素の値が変わった時に呼び出されるコールバックで処理できます。話をキーボードに固定すると,以下の3パターンの実装が考えられ,タイミングの違いを検証してみる必要がありそうです。

  • NSResponderで処理
  • I/OKitのコールバックで処理
  • I/OKitのコールバック呼び出しを待たず,高頻度でデバイスの値をチェックする独自のスレッドでチェック

気になるのは,I/OKitのコールバックの呼び出しタイミングがNSResponderのタイミングと一致してるのか,またI/OKitで調べられるデバイスの入力状態の更新タイミングとコールバック発生タイミングにどれくらいの差異があるのかという点です。

WindowsではDirectInputを利用していれば間違いがないそうですが,macOSに関してはそういった(ゲーム開発等に使えるかもしれない)情報があまりでてこないので謎が多いです。 経過時間の測定に関しては調べが付いていて,macOSでは mach_absolute_time() を使うことで,ゲーム開始時からの経過時間をナノ秒単位で計測できるため,入力を受け取ったあとの処理については問題はなさそうです。繰り返しになりますが,問題は,いつその入力を知ることができるのか,最速のパターンを知りたいということです。意外とNSResponderが最速だったりして。

現在はSpriteKitの仕組みに乗っているので描画周りのタイミングは任せるとして,その他のタイミング制御は全部で自前で処理していくのが良さそうですね。 タイミングが厳密なゲームにSpriteKitでは厳しいとかそういうのはないですよね???(無知)

mach_absolute_time()の精度と動作条件

問題がなさそうと言いつつも,不安になるもので,mach_absolute_time()関数がmacOS上において一番正確な値を取得できる関数であるかの裏を取る必要があります。また,一部の環境でしか動きませんということでは困ります。Windowsに比べてだいぶ環境の統一が為されているmacでは心配なさそうなきもしますが…。

やはりWindowsにおいてはQueryPerformanceCounter()を使うべしとの知見が簡単に得られましたが,macこれ使っとけという声を拾うことが難しい印象でした。StackOverflow曰く,

stackoverflow.com

stackoverflow.com

精度上々かつクロックの動作効率の変動に影響されないというmach_absolute_time()が攻守ともに優れいている印象です。クロックの変動をうけるのは中々に面倒臭いらしいので,話が簡単になるmach_absolute_timeを採用したいところです。ちなみにWindowsにおけるQueryPerformanceCounterも,CPUの周波数の変動を受ける模様。

所感

コントローラとキーボードからの入力は,一旦上に挙げたパターンの検証で一番早くレスポンスできるものを採用する。経過時間の取得はとりえあえず mach_absolute_time() で。後々もっといい方法があることがわかったらそちらに鞍替えする。

こういう心配ごとばかりに囚われてゲームをそれらしく形にしていくという作業を疎かにする癖をやめたいです…。でも知りたい。知見のある方はアドバイスください。

チラ裏ですが,タイミングの正確さはそこそこにして,プログラムでユーザの入力の癖をみて自動で判定タイミングをミリ秒ずらして挙げて補正という逃げ方もありかなぁと考えています。LR2とかそれでめっちゃ光りますし。