🦜
Goでレースゲームの目の届く範囲を広げる方法
レースゲームの多くは視点が固定で、特にダッシュボードやドライバー視点とかだと普通はモニターに映る視界が不足して、助手席寄り方向の様子がよくわからない。
「普通でない環境」としては「ウルトラスーパーワイドなモニター」とか「3面モニターの連結」環境などが実際に存在はしますが、これらを実現するのに必要なコストはかなり高価です。
もう一つが「VRゴーグル」ですが、これもいろいろ課題が多く、装着ストレスのため長時間プレイが不可能な問題は当分解決しそうにありません。
そこで、安価に目の届く範囲を広げる方法を実現しようと思いました。
必要なモノ
- Webカメラ
- RP2040搭載ボード(RaspberryPi Picoなど)
コネクタがType-CでコンパクトなXIAO RP2040がおススメではある
ゲームタイトル側の要件
- 複数のコントローラーが同時に利用可能
- ゲームパッドの右スティックでカメラ視点をコントロールできること
- デッドゾーンをゼロに設定できること
今のところ確認できているタイトル
- EA Sports WRC
仕組み

トップビュー
- モニター上部にWebカメラを設置
- 通常のFOVは水色の線上
- OpenCVで顔の認識をトラッキングすることでWebカメラの視界における頭部の位置を把握
- 頭部を左にずらしたとき、実際のFOV変化に合わせてゲームパッドの右スティックを右に傾けるとゲーム表示の視界もずれる

左に頭を動かす
ゲームパッドの右スティックを操作する部分の実現
- RP2040搭載ボードにGamepadエミュレーターを実装
- USB-CDCとHIDゲームパッドの複合デバイスとしてファームウェアを構築
- USB-CDC経由でゲームパッドの状態を書き換えることでPCのゲームパッドの認識状態を更新する
実際のコード
実装は二つ
- Go製のホストPCアプリケーション
- TinyGo製のUSBデバイスファームウェア
- face-controller
- main.go PCアプリケーション
- gamepad-emulator
- main.go GamepadEmulatorファームウェア
GoCVによる顔の位置トラッキングの様子
ブロック図

- PCのトラッキングアプリからはUSBシリアルポート経由のJSON-RPCでマイコン内のRPCサービスを呼び出す
- 変更はHIDゲームパッドのステートを更新し、HIDレポートがPCに送られる
- PCからはHIDゲームパッドデバイスはDirectInputないしXInputで認識され、ゲームアプリ上で使える
WIP...
結果
まとめ
- 左に頭をずらしたときに右に視点をずらすというロジック
- 見えないところをのぞき込む動きをフォローするという意図
- これにより見にくいところがしっかり見えるというメリットを感じる
- しかし、実際は右に曲がる時、頭を右に振って構えてしまうことも多い
- そのとき、転回が進んだと誤解してアンダーを出してしまうことも発生しがち
- 結局、このロジックに慣れていく必要はある
- EA-WRCではヘルメット視点のみ上下のカメラ操作が可能でその他の視点は左右のみ
既知の問題と課題
- 顔トラッキングが完全放置で運用できていない:顔をロストしたり再発見したときのリカバリは調整が必要
- ゲームパッドスティック値が飛び飛びになっているため、視界の変更がぎくしゃくする:イージング処理を入れれば多少改善するかも->移動平均処理追加
- CPU負荷がちょっとあるため、非力な環境では動かしづらい:顔トラッキングが完全放置で運用できるようになれば、確認用表示を無くすことができ多少負荷は減らせる->画面無しモード追加
- ゲームタイトルごとの調整がちょっと面倒で調整しきれない場合もある
なぜ仮想JoyStickソフトを採用しなかったか?
- もちろんこれがうまくいけば追加のマイコンボードとか不要にできた
- 改変版もいろいろ出回っていてどれが今のWindowsで動く最新版かがわかりにくい
- ちゃんと動く実際のクライアントコードサンプルが見つからない
- ちゃんとしたコントローラーの動作に不具合が出るという話もある
- 物理デバイスなら超安定動作
ゲームパッドエミュレーターの応用
- シリアル通信を別途PCにつなぐと別の用途が見える
- 例えば、ニンテンドースイッチにゲームパッドとして認識させる
- USBキャプチャーなどもPCに接続
- キャプチャ画像をもとにゲームパッドを操作するという環境が実現できる
- これはWebRTCを通じて遠隔プレイもできるだろう
- また、手元にAI環境が構築できれば、AIによる自動ゲームプレイなんかもできるかも
Discussion