けものみち

まったりと、きのむくままに。

9〜10月中盤までのタイピング成果

もうあと2か月半くらいで2019年が終わるとか、あと半年もしないうちに大学卒業するとか信じられないです。時間はあっという間に経ってしまうのですね。


f:id:WhiteFox-Lugh:20191014094734j:plain

さて、前回のタイピング成果まとめからおよそ1か月半たったので、またまとめてみようと思います!

正直、前回の成果まとめ作った時のタイピングのレベルでも「俺はタイピング極めた!」と言ってもほとんどの人には怒られないと思うのですが、この1か月半でまたいろいろと成果が出たので、まだまだ腕は磨けるもの、謙虚にコツコツ練習していこうと思いました。


1. e-typing

腕試しレベルチェックは前回のまとめではスコア 616 が最高でしたが、 それを大幅に更新する 665 が出ました!

なぜか MacBook Air のキーボードで打ってますが。意外と打ちやすいんですよ。MacBook Pro のキーボードは打ち心地最悪なんですけどね。

これは夏休み中の記録で、この記録を出した当時は「たまたまうまくいった」と思っていたのですが、10月にスコア 664 を2回出しているのでもうまぐれではない気がします。

それと、長文では初めてスコア 800 台を出しました!800台は e-typing では Joker ランクと出て、これより上のランクは存在しないようです!(マジか)

それまでのハイスコアが 768 だったので、50点以上も更新するとはちょっとびっくりです!

2. Weather Typing

800 key/m を超える記録が結構出るようになってきました。

リアルタイムの対戦では10ワード先制勝負で 840 kpm とか出てたのでもっといい記録が出るかもしれません。

windows 版だと1文ごとに正確さとスピードを出してくれるのですが、速いやつだと 1100kpm, 遅いと 600kpm くらいで結構ムラがあるのでどうにか下限を上げたいところです。

あとはRTC(Realforce Typing Championship)を意識するとトップスピードで打っても正確さ 95% は切らない練習をするのも必要ですね。これは Weather Typing の対人戦で鍛えたいところです。

3. タイ速

ついにネカフェで隣の人に迷惑がかかるレベルになりましたw

いや、ネカフェほとんど行かないんですが...

次のランク S+14 も目指せそうな気がするので狙ってみたいと思います!

Unity でタイピングゲームを実装をしたので覚え書き

ここ数週間はタイピングの練習にとてもはまっていて、1日1時間、長いと3〜4時間はタイピング練習に費やしてしまっている状態です。いわゆるZタイパーなんてのも目標の一つにいれています。

最近のお気に入りは Weather Typing です。

f:id:WhiteFox-Lugh:20190911073755p:plain

f:id:WhiteFox-Lugh:20190911073809p:plain

複数のワードをランダムに組み合わせて文章を生成しているのでマンネリ化しないし、結構面白い文章が生成されるのでかなり気に入ってます。中でも「試用版おいなりさん」が出てきたときは好きすぎてハンネにしてたぐらいです。


さて、今回の記事は、ちょうどタイピングにはまっていることだし、Unity でタイピングゲームを実装すればいいじゃないか!ということになって実装してみることにしました。

(※ 覚書みたいなものなので気が向いたら Qiita にでもコード付きでまとめなおすかもしれません)


タイピングの入力の判定について

今回実装しようとしたのは e-typingタイ速寿司打など多くのタイピングゲームで採用されている逐次判定方式です。簡単に言うと、一つキーが押されるたびに正しい入力かどうかを判定する方式です。文章も英文ではなく和文です。

この方式なのですが、一見そこまで難しくなさそうなのですが、実装するにあたって考えなければならない点がいくつかあります。

1. 複数入力に対応しないといけない

「し」は si, shi, ci の3通り*1あるとか、「しゅ」は syu, shu の他に「し」+「ゅ」と打つ方法(si + lyu, si + xyu ...)があるとか一つの文章に対して結構色々な入力が考えられます。

特に厄介なのが、

  • 「ん」: 「ん」の後ろに母音、ナ行、ヤ行、ニャ、ニュ、ニョなどがきた時、または文末の「ん」は nn または xn *2 でなければならない。それ以外は n も可
  • 「っ」: 後ろに続く子音を2回入力する。「っか」は kka になるし、「っし」は ssi になる。ただし、「っ」を単独で入力する方法は ltu, xtu, ltsu, xtsu と4パターンあり、「っ」+「か」などと入力する(ltu + ka)のも正解としなければならない

です。これらをうまく判定する方法を考えます。

2. 複数入力に対応すると可能なパターン数が爆発的に多くなる

先ほど挙げたように、ひらがな一文字に対して2通り、3通り、場合によっては「しぇ」などのように入力パターンが10通りを越える場合もあり、ひらがなで高々20文字程度の文章であっても、可能な入力パターンが軽く10万、100万と爆発してしまうことがわかるかと思います。

例えば「一家に一台」という例文があった時、愚直に入力パターンを列挙すると i kka ni i ti da i, yi kka ni i ti da i, i ltu ka ni i ti da i, i ltu ka ni yi chi da i, ... などとかなりのパターンが出てくることがわかります。

なので判定のアルゴリズムをきちんと考えないと、判定自体が遅くなってしまい動作が重くなってしまうことが考えられます。

3. キー入力と判定

多くのサイトでは Update() を用いてキーを拾う実装になっているようだったのでとりあえず最初はそう実装していました。

しかし、実際自分でテストプレイしてみると、高速で入力したときに「正しいキーを押したのに押してない判定」になることが結構ありました。

これには Update() が呼ばれた時とキーを押した時が一致しなかったため入力を拾ってくれないとか、そもそもタイピング速度が 60fps で判定できる早さを超えている(タイプウェルなどで測定すると得意な入力に対しては 1フレームを切ることがあるようです)など、いろいろ原因がありそうなので別の方法をとるしかありません。


実装の概要

ひらがな→ローマ字入力へのマッピング

「あ」→ a、「ふ」→ fu, hu、「ん」→ n, nn, xn、「しゃ」→ sya, sha のようにひらがなからローマ字入力へのマップを行う Dictionary を作りました。

あらかじめ文章をひらがなで書いておいて、このひらがなの文章をパースすることで考えられるすべての入力パターンを列挙できるようになります。例えば「一家に一台エアコン」という例文があったとして、変換のイメージは以下のような感じです。

i k ka ni i ti da i e a ko n
yi ltu ca yi chi yi nn
xtu xn
ltsu
xtsu

あとはひらがなの文章の今何文字目をみているかを記録する変数や、各ローマ字入力において今アルファベットの何文字目を見ているかなどを記録すればよいです(この辺の細かい実装については割愛します)。

ただし、上記の例のように「っか」を「kca」と入力するパターンは不正解とする、文末の「ん」は n は不可など例外的なパターンの処理も必要となります。

これで1キーあたりの判定時間は高々20通りくらいのチェックで済むようになったので判定関連に関しては十分高速だと思います。

入力を OnGUI() で受け取る

www.sophiehoulden.com

高速で入力するタイパーに対応する方法に関しては、いい感じの記事が英語で見つかったのでこれを参考にしました。

すごくざっくり言うと、OnGUI() はフレームレートから独立しているので、Event.current を用いてキーを入力するたびにそのキーが何かを受け取って適当に保持しておき、Update() が呼ばれた時にこれらを一括で処理するというものです。

Event.current ではキーを押した時と離したときの2箇所判定があるので、判定は KeyDown の時だけになるように、また、マウスのクリックなど、キーボード以外のイベントは受け付けないようにします。

入力されたキーを次の Update() が呼ばれるまで保持するデータ構造はシンプルに Queue で実装しました。

このように OnGUI() を用いたところ、高速にタイプしても入力漏れがなくなり実際に公開されているタイピングゲームとだいぶ近くなりました。

今の実装では、キーが押された時刻は特に保持してはいないのですが、上記の参考元の記事では、キーを押した時刻を保持しておくと記述があるので、その情報を用いて順番が前後しないようにした方がより安全かもしれません。


入力画面のプロトタイプ

UI 面とかはさておき、とりあえずそこそこの速度で打ってみたり、わざと普段使わない入力方式やよくある打ち間違えなどを混ぜて打ってみたり、問題文を前半ワード + 後半ワードの形式にしてランダムで生成して、ちゃんとうまくパースできているかを確認したりしてみました。だいぶいい感じになったと思います。


このあとは

スコア計算、スコア保存、レーティング機能(音ゲーマー感ありますね)、初心者用にもうちょっと短い文章でタイピング&ローマ字入力を表示してくれる機能、ローマ字だけではなく英文入力に対応するくらいまでは実装してみたいと思います。英文の方が実装は楽そう…。

そこそこの中身になったら、UI を整えて、無料で使えそうなバックエンドも用意して、ランキング機能とかユーザーごとに記録を保存するとか、ツイート機能とかつけてみてネットに公開してみんなにプレイしてもらってもいいんじゃないかなとも考えています。

*1:ci で「し」を入力できるのはタイピング特有っぽいです

*2:これもタイピング特有の入力です