べるもダイアリー

Cave Putorium

ギターと孤独と青い星と戦争と平和と酒と泪と男と女

けいおん!以降、アイドルアニメが新しくPOPするたびに 「俺は美少女にはアイドルよりロックスターやってもらいてえんだ~」 みたいなことを呟いてた。

今思うとけいおん!の唯たちがロックスターだったかというとそれは違う気もするんだけど、 アイドルよりは自分たちの楽しさのために活動しているのが自分には共感しやすかった。

アイドルは自分を魅力的に見せる仕事だが、それは自分のエゴではなく「人に夢を与える」ためであり、その努力の過程そのものがエンターテインメントとしてお出しされる。 でもそれはちょっとキラキラしすぎている。世界が綺麗すぎる。そこに乗っかるには自分はちょっとひねくれすぎているのかもしれない。 ロックスター概念はもっとエゴイストだ。自分が好きなことを好きに表現した上で大勢からチヤホヤされて~というエゴを実現する。 これはめちゃめちゃわかる。好きなことやってチヤホヤされたい。

ついでに言うとロックスターは楽器というメカのオペレーションに卓越したプロフェッショナルであることもめちゃめちゃカッコいい。 女の子に銃を持たせる画は定番で楽しいけど、一般人から見れば少年兵である。 ギターとベースとドラムとキーボードは現実の女の子が持ってても嬉しいでしょう。銃が戦争なら音楽は世界平和である。

というように「けいおん!」以来のロックバンド美少女アニメを求めていたのでなんとなく「ぼっち・ざ・ろっく」をチェックはしていたんですが 五話の初ライブに行く前から薄々感じていた……このアニメ、ひけらかさないけどめちゃめちゃ画が丁寧じゃない!?

ハッとするカット

特にハッとした瞬間はこのカットで、ギャグアニメでありながら五話のこのカットは映画的な時間というのがちゃんと流れていると思うんですよ。 挑戦的に実写もピクセルアートも変わり種のような作画手法をとりいれているけど、奇をてらった用ないやらしさは感じない。 演出の意図がきちんとあって変わった表現も適切に取り入れる。確かな土台のある画を見せてくれる。

ぼっちちゃんの陰キャとしての自信の無さからくる被害妄想と奇行の愛らしさと、それでも楽しいことをみんなとやりたい中で自分の課題を乗り越えていく物語の良さ そういうコンセプトのハマり方も当然前提としてあるんですが、そこに伝えるべき物語を伝える表現の巧みさが乗っかるともう無敵ですよね。 表現の良さっていうのは単に作画だけでも物語だけでもなくて、伝えるべきことを伝える方法の適格さにある。

「あ、久々に音楽触ると楽しいかもしれん」 それがどれくらい続くのかはわからないけど、伝わるべきものが伝わってしまった。

というわけで

10年ぶりくらいにギター買っちゃいました。

Fender Player Plus Stratocaster

My New Gear

楽器屋をふらっと除いたときに目に留まって、サンバーストのグラデーションが綺麗でかっこよかったんですよね。ストラトのサンバーストって同じサンバーストでもグラデーションや色味の違いがいろいろあって、その中でもこれは自分の好み具合だった。こういうトラディショナルな雰囲気のストラトキャスターに2点支持ブロックサドルとロックペグがついて見た目がモダンなのがいい。

定価で13万くらいだと思うんですけど店頭価格8万8千円でした。安い。謎の値引き。 ピックガードのシールが日焼け後になってたので売れ残っちゃったのかな。 それでも10年前ならこの値段でアメスタ全然買えたから楽器は高くなってる。

ナットがちょっと深い気がするのが気になるんですが、どうでしょう? トレモロアームはフローティングさせてますがアームダウンではチューニング安定する一方でアームアップではだいぶシャープしちゃいます。 ナットが悪い気はするんだよな~~~~~~~~~それ以外はすごい気にいってる。

特に面白いのはトーンノブをプルするとフロントが起動してフロント+リアとかフロント+センター+リアができるところ。 ストラトキャスターの普通のラインアップの仕様もこれにすればよくない?と思う。

ギターの音の違いわからない素人なんですが詳しいフォロワーには

plusじゃない無印playerに比べて、PUが特殊なのか不自然にハイが強調されてるっぽいなこれ。もし違和感があったらとりあえずTONEを絞ってみると良いと思う。ロー~ミドルについては値段相応の普通のギターって感じなので悪くないと思う

と意見貰った。確かにハイがちょっとうるさい気はする。

ついでにアンプの代わりにマルチエフェクターでも買おうかなーと考えてたところ、MOOERのGE-200をお勧めされてこれも買ってしまいました。

大学生のときに使っていたToneLab STと比べてアンプシミュレータの進化を感じる……めちゃめちゃ音いいですねこれ。 キャビネットIR使えるのでネットでいろいろ落として試したい。

便利だけどあまりスタジオとかで本物のクソデカアンプとか触ったことないオタクには機種名と特性があんまりよくわからないっすね。 Fender 65 Twin ReverbとかMarshall JCM900とかとりあえず有名なんでしょ?名前は聞いたことあるかも……くらいの`感覚。 アンシミュとしてLINEで使う場合にはキャビネットの選択が重要らしいんですが、アンプモデル選んだ時点で定番の組み合わせのキャビネットが選択されるっぽいのでありがたい。 ただマイクの種類は本当にわからん。ので詳しいフォロワーに解説してもらった。 「SM57は中高域を中心にまあギターのギターらしい音が大体録れる、低域と高域の端っこのほうはやや苦手」 「MD421は素晴らしい低域の特性と若干やかましい超高域」 「e609、e906あたりはまあ特化型じゃなくなってバランス良くなった57と421くらいの感じがある、R-121は概ね全てにおいて優秀」 なるほどっすね~。

ぼろ太さんに誘われてスタジオで遊んできました
ぼろ太氏のエフェクターボード

ペダル機能しない?と思ったそこのあなた

このGE-200、ペダルが特殊で回転のMaxからさらに強く押し込むことでEXPのON/OFFが切り替わるらしい。 でも自分の個体だとどうもこれが動かなくて初期不良を疑っていた。いやちゃんとキャリブレーションはしましたよ? でも押し込みやってみてもEXP切り替わらないんですよ。そんなことある??? うーんたぶん押し込みは感圧スイッチみたいなのでやっていてそれが初期不良なのかなーと思っていたんですが解決しました。

ペダルの裏には当然ゴムがあるんですが、押し込みはこのゴムが押し込まれて潰れる分のペダル回転軸の可変抵抗の微妙な変化を読み取ってスレッショルドを設定しているだけらしい。 つまり前側のゴムがつぶれる方向に回転モーメントをかけるような踏み方をしないと押し込みが検知できない。自分は感圧スイッチだと思い込んでペダル全体を押し込んでいた。 うーーーーーーーーーーーーーーむ。

このゴムも硬くて押し込まれてるか微妙なところあるので、自分でウレタンとか裏に張り付けるのがよさそうっすね。

妻からの差し入れ、なんと妻もベースを最近はじめました。

ジョイスティックを何個も使う飛行機オタク向けのゲーム設定アプリを作った話 #4

使用したライブラリ

  • DirectX SDK www.microsoft.com ジョイスティックの入力値をとるのにこれがどうしても必要だった。今はWindows APIでなんとかなるっぽいのでそのうち .Net Core 5 対応のために移行したい。
  • MahApps mahapps.com せっかく作るならメトロ風UIでモダンなランチャーにしたい、ゲームなんだから見た目はかっこよくあってしかるべきだ。

物理を鍛える脳筋プレイからゲームシステムを理解して正しい魔法を組み合わせるとサクサク進むようになるのじゃ

自分が触ったことのある言語は2つ

会社で触ったVisual Basic 会社で毎日触ってるMATLAB 大学の授業で単位のために触ったJava(覚えてない)

3つだった。 でもJavaはなんかあまり覚えてないしMATLABはライセンス購入にお金がかかる、よしVisualBasicでつくったろ!

こうしてジョイスティックの軸の入力値をスライダーに反映できるGUIまでプロトタイプとして作成したところであることに気が付く。 自分が探したやりたいことのサンプルコードはみんなC#で書かれていた。なんとなく同じ.NETでほぼ置き換えが出来ることは知っているので、VBならどういう文法になるだろうと考えて手で変換しながら打ち込んでみた。でもこれ最初からC#で書いたほうが早いんじゃないか?

C#にすべて変換して計画を再スタートしてみる。

この class ってなんだ?structure とどう違うんだ?????? new ってなに????????

そう、会社の仕事でも構造化プログラミングのひどいやり方みたいなコードしか見てこなかった自分にとっては、未知のテクノロジーとの遭遇だった。

「要は……構造体に関数がくっついて、どのデータはどの関数で動かせばいいかひとまとまりになる……ってコト?」「これ考えた人、もしかして頭いいのでは???」

自分はこれからジョイスティックの設定をデバイスごとに管理しないといけない、するとジョイスティックの割り当て管理データとその処理方法を、ジョイスティックの概念を管理するクラス!というやつにしてあげると便利なのでは……

こうして彼らはデスクリムゾン……ではなくクラスベースのOOPを手に入れたのであった

(まあVBもクラスベースのOOPできますけど)

Class Diagram

  • DeviceControl
    • DeviceList devList DirectX SDKジョイスティックのオブジェクトをとるために必要なデバイスのリスト的なもの
    • Device[] joyStick DirectX SDK側から提供される各ジョイスティックのオブジェクト、こいつを叩くと入力値とか返してくれる。ぶっちゃけDeviceオブジェクトはjoyAssignに参照を渡したのでフィールドとして持ってなくていい気がする……歴史的な経緯で念のため残してある
    • JoyAssgn[] joyAssign AL側で設定を管理するための各ジョイスティックのインスタンス
  • JoyAssgn なんか予約語とかあったら怖いなーと思ってAssignのiを省略している。たぶん無用の心配だった。AL側で設定を管理するための各ジョイスティックのオブジェクト。この中に割り当てた項目のデータとかが入る。このオブジェクト自体をXMLとして出力したり読み込んだりして記録を保存している。
    • string productName 製品名
    • Guid productGUID プロダクトGUIDはデバイス製品ごとに固有のID、個体が違っても同じ製品なら同じIDである。
    • Guid instanceGUID インスタンスGUIDはデバイス個体ごとに固有のID、製品が同じでも違う個体なら違うIDである。
    • DetentPosition detentPosition 戦闘機のスロットルにはエンジンを切る位置とアフターバーナー開始位置があり、その辺には溝があって普通に動かしたときにはそのまま進まないようになっている。ジョイスティックのディテント位置を入力値の位置として保存する役目がある。
    • AxAssgn[] axis
    • DxAssgn[] dx
    • PovAssgn[] pov
  • AxAssgn 物理軸にどのゲーム内軸が割り当てられているか記録する
    • string axisName 割り当てられたゲーム内軸名
    • DateTime assgnDate AL上で割り当てられた瞬間の時間、BMSのゲーム内軸は排他的に割り当てられるため、BMSで複数のデバイスのいずれかの物理軸が同じゲーム内軸に割り当てられていると困る。これによってAL上では一番最近割り当てられた物理軸のみを、ひとつのゲーム内軸に割り当てるようにしている。
    • bool invert 物理軸の入力反転
    • AxCurve saturation 物理軸の入力飽和
    • AxCurve deadzone 物理軸の入力デッドゾーン
  • DxAssgn DXボタンにどの操作項目が割り振られているか記録する
    • Assgn[] assign = new Assgn[4] 4つの動作に対する割り当てが定義されている。ひとつの物理的な動作に対する割り当ては排他的とした。そのほうが設定がこんがらがらないし、一つのボタンに複数の操作項目を割り当てたいケースは滅多にない。
      • [1] ボタン押し下げ
      • [2] ピンキー同時押しでのボタン押し下げ
      • [3] ボタンを離す
      • [4] ピンキー同時押しでボタンを離す
  • PovAssgn Povという方向キーにどの操作項目が割り振られているか記録する
    • DirAssgn[]direction = new DirAssgn[8] 時計回りに12時から始まる8方向への方向キーの入力を記録する
  • DirAssgn Povという方向キーのひとつの方向側にどの操作項目が割り振られているか記録する
    • string[] callback 要素2つの配列になっているが、最初の要素はボタンを押したときの、最後の要素はピンキー同時押しでの操作項目割り当てとなっている。たしかBMSではPOVを離したときの割り当ては対応していない……はず

ところでこれ巨大な神クラスになってないよね?大丈夫かな。

BMS起動時の設定オーバーライド

この辺のデータはOverrideクラスとの連携によっていい感じに設定ファイルが生成され、多態性によって各バージョンとの互換性がとれるようになっている。

情報量「無」みたいな図

めちゃめちゃ簡単に説明すると次の図のようなシーケンスになっている (説明のためにわざと実際のコードとは順序や関数名が異なる部分あり) 実際にはもうちょっと細かいコンフィグファイルとかもいじってる

ジョイスティックを何個も使う飛行機オタク向けのゲーム設定アプリを作った話 #3

設の計: UI

Alternative Launcher は三つのウィンドウから構成される

  • Main window
  • Axis Assign Window
  • Key Mapping window

また、MainWindowは3つのタブから構成される

  • Launcher
  • Axis Assign
  • Key Mapping

Main Window - Launcher

ユーザーはまずAL起動時にMain WindowのLauncherタブを見ることになる。 ここにはBMS本体およびBMSに付属するエディター類の起動パネルが並ぶ、ここからBMS本体の起動パネルを押すと、いい感じにALがBMSの設定ファイルを生成してからBMS本体を立ち上げる。

BMSにはもう一つ課題があり、ゲームインストール時についてくる他のエディターなどを使いこなさないとゲームの機能をフルに楽しめないだけでなく、公式の外部アプリケーションもダウンロードしないとミッショエディタや天候設定などの様々な機能がフルに使えないのである……!初心者やDCSからのお試し組はフォーラムやマニュアルを丹念に読むとは限らないので、ずーっとこうした本体以外のアプリケーションの存在に気が付かないまま「BMSはこんなものか」で評価を終えてしまう可能性がある。これはまずい!

ということでALのこの画面には外部公式アプリおよびフォーラムで必須とされるような3rd製アプリケーションの起動パネルも並べることにした。インストールされていない場合はダウンロードページに飛び、されている場合はそれを起動する。という程度のシンプルなものだが、初心者に「BMSはこういう遊び方が出来ますよ」と紹介するのに良い方法だと考えた。

(あとそれ以外にもゲーム起動時のコマンドラインオプションで有効化される設定があったりするので、そういうのもAL側で有効に出来るようにしといた)

Main Window - Axis Assign

ALでは

  • 「ゲーム内軸」
  • 「物理軸」

と軸の概念を二つに分けて考えた。

  • 「ゲーム内軸」はゲーム内の戦闘機のコクピット内の軸出力であり
  • 「物理軸」はジョイスティックの物理的な軸入力のことである

例えばゲームの中の戦闘機の操縦桿を手前に引く行為はゲーム内軸出力であり、この出力に現実世界のジョイスティックを手前に引く方向の入力を割り当てると、ジョイスティックを手前に引いた時ゲームの中でも操縦桿を手前に引いたことになり、戦闘機の機首は上に向く。(これをピッチアップと呼ぶ)

Axis AssignタブではBMSで割り当て可能なゲーム内軸設定のリストが並び、また物理軸がそのゲーム内軸に割り当てられている場合は、その入力値が表示されるようになっている。適当にジョイスティックを動かすとスライダーが動き、ユーザーはジョイスティックのどの操作がゲーム内のどの操作に対応しているか一目で理解できる。

それぞれのゲーム内軸の項目欄の隣にはASSIGNボタンが存在し、ここを押すとAxis Assign Windowという小窓が表示される。

ところで、BMS本体のUIで問題となっていたPRIMARY DEVICEの設定について、ALではROLL軸を割り当てたジョイスティックを自動的にPRIMARYとして設定されるようにした。

Main Window - Key Mapping

ここではBMSのキーボードおよびジョイスティックのDX/POVボタンの割り当てが表として表示される。 割り当て項目のリストおよびキーボードの割り当てリストはBMS側のKeyFileから読み込まれ、ジョイスティックの割り当て内容はAL側で管理しているジョイスティック設定ファイル(XML形式)から反映される。

例えばこんな感じに:

callback keyboard joystick-1 joystick-2
SimTrimUp POV1 UP
SimTMSUp Shift+Home DX7
SimTMSDown Shift+End DX9
SimCursorEnable Shift+Enter DX1
SimIdleDetent DX32 Release
SimCutoffDetent DX32

(数字が0から始まるのは非プログラマには直感的でない気がしたので、内部的にはDX0であっても+1表記している。ジョイスティック側のドライバも一般的にはそうなっている場合が多い)

行をダブルクリックすると、その割り当て項目をどのジョイスティックのどのボタンにどう割り当てるかを質問してくる Key Mapping Window という小窓が立ち上がる

DCS Worldのキー割り当て画面を参考にしたが、DCSではどのジョイスティックに割り当てるかダブルクリックする列も選ぶことによってユーザーが指定しないといけないのに対して、BMS ALでは対応する割り当て項目の行をクリックすればどのジョイスティックの入力も識別してくれるようにした。個人的にはDCSの割り当て仕様にも使いづらさを感じていたからだ。

Axis Assign Window

Main Window - Axis Assign から特定の項目のAssignボタンを押すと、この小窓が出現する。この画面では、親ウィンドウで選んだ項目であるゲーム内軸に対して。どの物理軸を割り当てるかユーザーが決定できる。

もしまだどの物理軸も設定されていない場合は、AWAITING INPUTSという表示が点滅する。ユーザーが手元のジョイスティックの物理軸を動かすと、画面は反応してその物理軸をゲーム内軸へと割り当てる。

BMS本体のUIでは物理軸はドロップダウンリストで選択する方式だったが、ユーザーはジョイスティックの物理軸の名前が現実のその動きに対応しているのか知らないので、これは直感的ではない。それよりも手元のジョイスティックを直接動かしたときに画面が入力を検知してくれれば、それが一番直感的だ。だからそうした。DCSやIL-2など他のフライトシミュレータでは一般的な方法でもある。

Key Mapping Window

Main Window - Key Mapping タブからリストされたゲーム内操作項目の中から、任意の項目の行をダブルクリックするとこの小窓が開く、ユーザーは親ウィンドウで選択した操作項目に対するジョイスティックボタンの割り当てを行うことになる。

BMS本体のUIではボタンを押したときに反応するよう設定することはできるが、キーファイルではボタンを離したときに特定の操作が反応されるように設定することもできる。そのためALではボタンを離したときの操作もこの小窓から設定できるようにした

また、BMSではピンキーという操作を押し続けている間、DX番号が繰り上がり、ボタン同時押しにより違う操作項目が実行できる機能があるのだが、本体側のUIにこれを設定する機能がない。しょうがないからALには同時押し割り当て機能もつけた

じゃあ、こういうUIをどんな感じで実装したの?つづく!

ジョイスティックを何個も使う飛行機オタク向けのゲーム設定アプリを作った話 #2

さて、BMSジョイスティック設定はどのように管理されているのか、その答えはインストールディレクトリのUser/Configにある。

まずBMSの初回起動時に現在接続しているデバイスごとのプロダクトGUIDとデバイス名がDeviceSorting.txtというテキストファイルに一行づつ記録される。2回目以降の起動時に既存のリストにない新しいデバイスが追加されれば、新たに同ファイルの続きの行に情報が追記される。

BMSのデバイスの割当はこのファイルに書かれたデバイス情報から現在接続されていないデバイスをスキップした並び順で管理される。ここにいろいろな問題が発生する(ついでに言うとこの管理システムすらv4.32あたりの初期バージョンには存在しなかった)

ジョイスティックの設定は2種類に分かれる。ON/OFFのデジタルな操作が行われるDXボタン入力の割当と、操縦桿の傾け具合やスロットルの位置などアナログ入力の割当を管理するAXIS(軸)の割当だ。

DX割当は一つのテキストファイル、AXISの割当は2つのバイナリファイルにて管理される。

DX割当はボタンの識別を連番で管理する。1つ目のデバイスのボタンはそれぞれDX0からDX127までのボタン割り当てを持ち、2つ目のジョイスティックはDX128-255までの番号が割り当てられる。(開発当時のバージョンは128ボタンの代わりに32ボタンまでの対応だった)

AXIS割当はゲーム内戦闘機のそれぞれの入力項目(操縦桿の傾けやスロットル、レーダーカーソル操作など)に対して、何番目のデバイスの何番目の軸入力が割当されているかを記録する。

問題は連番が現在接続されていないデバイスをスキップした番号で認識されることにある。

例えば私の友人の一人はレースゲーム用のハンドルコントローラを接続した状態で初めてBMSの割当を行い、別な日にはハンドルコントローラーを外した状態でBMSを起動した。するとBMSはハンドルコントローラをスキップした連番でジョイスティックを認識するため、ハンドルコントローラー以降のデバイスとして管理されていた番号が一つ繰り下がる。それによりDX番号も128ボタンずつ繰り下がることになる。

例えば384番は3番めのデバイスの最初のボタンだが、繰り下がりが起きれば同じデバイスは2番目、ボタンは255番目となる。しかしボタン設定ファイルには384番目の割当として記録されているので、2つ目のデバイスの1つ目のボタンを押しても前回と違い反応しなくなるか、別な機能が発動する。

軸でも同様のことが発生し、接続されているデバイス数より大きい番号が記録されていた場合にはゲーム起動時に設定がリセットされてしまう。

たとえマニュアルにどれだけ詳細に割り当ての設定方法が書かれていたとしても、ユーザーはまず触って試そうとする。その操作方法が直感的でなければソフトウェアとして出来が悪いと判定されてしまう。

コミュニティは「複雑な戦闘機の操作方法を覚えなければいけないゲームを遊ぶのに、そこでマニュアルを読まない人を助けても楽しめる人ではないと思うよ」と私に言う。しかし戦闘機の操作に興味があってもソフトウェア側の都合に興味があるわけないじゃないか。と私は考える。

ゲーム内容はどんなにマニアックでもいい、でもユーザーインターフェースがマニアックであってはだめだ。

この問題を解決するために、自分が開発したAlternative Launcher(AL)は次の管理方法をとる。

  • ユーザーはAL上のUIでデバイスの割り当てを設定する
  • AL上でのデバイスの設定内容はデバイスのIDごとに保存された個別のファイルに書き込まれる
  • ALからBMSを起動する瞬間にALは自前の管理ファイルの内容をもとにBMSの一連の設定ファイルを正しい連携づけがなされるよう生成する

結果として期待される効用:
バイスIDごとに割り当てを管理するため連番による設定の入れ替わりが発生しない

さて、それをどのように実装するのか、つづく!

ジョイスティックを何個も使う飛行機オタク向けのゲーム設定アプリを作った話 #1

転職活動のためにエントリを書きます。 自分で何を考えてどうやったのか記録を残しておくことが大事っぽいと雰囲気で転職活動しているうちにわかってきた。 業務経験もいろいろあるんですが、なにぶんレガシーコードと必死で格闘してきた経験がほとんどなので、自分で新しい何かを生み出した例としては個人で開発したゲーム連携アプリの話を書いておこうかなと思います。

なにぶん、5年も前にガーッとv1.0まで組み上げたソフトウェア開発の話なので記憶的には怪しいところも多く、途中で満州に行ったかと思えば女優だったことが判明したり、ピアノを与えられると上手に演奏しだしたり、あるいはCIAの暗殺者だったことが判明したりする可能性があります。

マジのオタクのためのゲーム

普通ゲームというのはスポーツだとか戦争だとか、現実の人生の競技性がある部分をめちゃめちゃ抽象化してエンタメ化するわけですが、フライトシミュレータは現実の再現を目指します。そういう不思議なジャンルがこの世にはある。

FPSだったら現実の人間と違い、主人公は常に走れてすごいジャンプしながらアサルトライフルを乱射できないと「ゲームとしてつまらん!」となるところですが、フライトシミュレータの場合は飛行機のシステムや挙動が現実とズレていたらジャンルとして欠点になります。逆に航空機ゲームをカリカチュアライズするとACE COMBATシリーズのようなものになり、これは別ジャンルとして名作です。

近年の航空機シミュレータは航空機のコクピット内のシステムもほぼ実機と同じように再現しており、エンジンを始動してコクピット内のいろいろコンピュータ的なものを取り扱うのも本物と同じ手順が要求され、公に公開されているマニュアルがそのままマニュアルとして使えるほどです。操作手順に関しては実機の運用者と同じだけの知識を要求されます。マジでオタクです。

困りが発生

さて、そうなるとマウスとキーボードだけで操作するには限界が出てきます。そこでフライトシミュレータのオタクはパソコンにつなぐことが出来る操縦桿とかスロットルだとかペダルだとかコクピット内の特定のパネルだとかを再現したデバイスを複数接続して使うことになります。そしてひとつの操縦桿にはスイッチが20個くらいついてたりします。

具体的にはこんなものが発売されてます。 www.thrustmaster.com

問題は市販のジョイスティックとシミュレータ内で操作する飛行機の操縦桿等のシステムはそのまま同じものを扱えるわけではないということです。巷で市販されているA-10Cのジョイスティックでシミュレータ内のF-16を操作しないといけなかったりします。 (まあA-10CとF-16Cの操縦桿はほぼ同じなのでそこはなんとかなるんですが) 市販されているジョイスティックはレプリカ系ばかりとも限らないので、そういう意味でもこのミスマッチをどうするか?という話になります。

見てください。この宇宙船みたいなジョイスティック…… gaming.logicool.co.jp

自分でやれ

で、実際にシミュレータを遊ぶ上で最初に何をやらないといけないのかというと、「このデバイスのこのボタンはゲーム内の飛行機のこのボタンに対応させる」「このデバイスのこのスライダーを動かすとゲーム内ではここが動くようにする」……みたいな作業をユーザーがちまちま行わないといけません。まあある程度ポピュラーなデバイス向けにはデフォルトの割り当てを用意しておく場合もありますが、基本はユーザー任せとなります。

ほとんどのシミュレータはデバイスごとに設定を記憶してくれるので、初回プレイ時にこの作業を行えばあとは何も変えずに遊べます。(というのは理想論で、オタクはどうせ新しいデバイスを買ったり、より遊びやすい設定を模索しはじめるのだが)

呼び覚まされる太古の神

さて、数ある(正直そんなに無い)シミュレータの中で私が最も愛する作品があります。伝説的なオーパーツとして名を残したFalcon4.0、その制作会社の倒産のあともリークされたソースを元に有志が開発を20年以上続け、今なおアップデートを続けるシミュレータ、FalconBMSです。

www.youtube.com

www.falcon-bms.com

RTSとフライトシミュレータを融合したFalcon4.0のオーパーツといえるシステムの継承に限らず、AIの考え方、現実の戦術や目視距離などなどパイロットとしての体験を再現するために重要な要素をどれもとても丁寧に調整しているため、私は世界最高の戦闘機シミュレータだと思っているのですが、古いゲームをボランティアでアップデートし続けているため、グラフィックやUIに難もあり、やはり見てくれとユーザビリティが良くなければどれだけ本質を磨いたとしても人々にリーチすることはありません。今日でも現役でアップデートが続いている複数のシミュレータの中では最もプレイ人口が少なくマイナーな方です。

実際、ジョイスティックの設定という面でも様々な困りが存在し:

  • ジョイスティックの種類を内部では接続順で覚えるので、これが入れ替わると設定がごちゃごちゃになる
  • 使わないハンドルコントローラとかをレースゲーム用に繋いでる人が別な日にはそれを外してゲーム開始したりすると当然ごちゃごちゃになる
  • なんならゲーム自体のUIも設定方法がわかりづらくて、PRIMARY DEVICEというプルダウンメニューから最初に操縦桿だけを選んで割り当てを開始しないといけないのだが、これを今から割り当てるデバイスを選ぶためのプルダウンだと勘違いする人が多く、これが原因で「別なデバイスの割り当てを始めるたびに他のデバイスの設定がリセットされる。なんで!?」「古いゲームだからデバイス一つしか対応してないのか・・・・・・」みたいに勘違いする人が続出。(実際Falcon4.0が出たころのフライトシミュレータってデバイス複数に対応できていなかったのだが、BMSは当然対応している)
  • 日本語OSユーザはさらに文字化けするデバイス名と格闘しながら割り当てをしないといけない
  • ぶっちゃけBMS公式はゲーム内のUIではなくインストールディレクトリに同梱したエクセルのマクロで割り当て設定ファイルを生成することを推奨しているが、インストールディレクトリなんてオタクの中のオタクしか見ねえよ。
  • そのマクロもボタン設定しか生成しないので、操縦桿を傾けた時の反応みたいなアナログ入力の設定はゲーム内UIでしか対応してない。そこが一番リセットされやすい設定なのだが……

など至る所でおしまいが発生していた。

割り当てがよくわからんとなってイライラしたらみんな諦めてDCS Worldを始めます。そらそうよ。

もしかして、自分が何とかするしかない……ってコト?

こういう状況を見ている中で開発に「割り当てはわからない人多いからこう改善しないとおしまいでは???」とフォーラム投稿を続けていましたが、ボランティア開発チームは自分が作りたい本質にしか興味がないのであまり相手にされず、「もしかして、自分が何とかするしかない……ってコト?」と気づくことになる。

自分が当時考えていたこと:

  • ジョイスティックの設定はジョイスティックのIDなり名前ごとに紐づいた設定として管理されるべきではないか
  • ジョイスティックのIDごとに設定を管理する外部ソフトが作成できたら、そこからゲームを起動する直前に毎回ゲームの設定ファイルを生成すればいいのではないか
  • この外部ソフトを代替のランチャーとして配布すればユーザーは何も考えなくてもゲームを起動するたびに正しい設定ファイルが常に上書きされる。というのはどうだろう。
  • 思いついた人間がやるしかない。

そう、思いついた人間がやらないと他にやってくれる人ってマジでいないんですよ。

当時自分が触ったことがある言語は

構造化プログラミングさえまともにできていない業務経験しかない中で、ここからC#OOPの世界に入っていくことになります。

つづく!