【JavaScript】e-typing風の本格派タイピングゲームを作る(英語編)

2022/10/06
e-typing画像

以前作成したe-typing風タイピングゲームのローマ字版に続き、英語版も作ってみました。シフト操作ありで、英数字に加えて各種記号にも対応した本格モデルです。

今回も以前と同様、本家e-typingの仕様を忠実に再現しました。ちなみに、以前作成したローマ字版はこちらの記事で紹介しています↓

【JavaScript】e-typing風の本格派タイピングゲームを作る | IB-Note

JavaScriptでe-typingの腕試し風タイピングゲームを作りました。ローマ字の入力ゆれにも対応した本格モデルです。

本記事では英語版の特徴やソースコード、仕様などについて詳しくご紹介していきます。

特徴

ローマ字版と同様、以下の特徴をもつタイピングゲームとなっています。

  • 各種設定の切り替え機能
  • キーガイド
  • 進捗状況を示すプログレスバー
  • タイプした部分の色付け
  • 文章が長い場合の自動スクロール機能
  • ミスタイプ時のエフェクト
  • 本家と同様のタイピング結果表示
  • 「ミスだけ」「もう1回」機能

追加要素

以下は私が追加実装したオリジナル機能です。

リアルタイムWPM表示

現在の入力速度が気になることがあるので付けてみました。

(スタート画面の設定でON/OFF設定可能)

スピードバー表示

入力速度が直感的にわかったら便利だなぁと思って付けてみました。700WPM(≒11.67キー/秒)を基準値としてどれくらいの速度かがバーの長さで示されます。

(基準値はソースコード内で変更可能)

スクリーンショット1

※1
本家の仕様と挙動を再現していますが、プログラム自体は私の完全オリジナルです。本家の内部処理については一切把握していません。

※2
運指ガイドはキーボードで力尽きて諦めました。本家と違い運指ガイドなしですが許してあげてください。

デモ

今回もデモを用意したので、試しにプレイしてみてください!

下のボタンをクリックするとゲーム画面が開きます。

※スクリーンサイズの都合上、解像度(横)748px以上のデバイスでのプレイを推奨します。

e-typing風タイピングゲーム(英語版)
ことわざ
日本語表示(J)
英語表示(E)
キーガイド(G)
WPM表示(W)
スピードバー(S)

日本語入力モードをオフにしてください

スペースキーで開始

(終了はEscキーです)

1
2
3
4
5
6
7
8
9
0
-
Q
W
E
R
T
Y
U
I
O
P
@
A
S
D
F
G
H
J
K
L
;
:
shift
Z
X
C
V
B
N
M
,
.
/
shift
space
今回のタイピング結果
前回の結果
---

ソースコードと仕様

ソースコード

こちらがゲームのソースコードです。

コードを確認

仕様

コードの仕様について簡単に説明します。

コードは上から順に本体のHTML, JavaScript, CSSで構成されており、<script> ~ </script>で囲まれた部分がJavaScriptです。JavaScriptコードを編集することで、入力文章を好きなものに変えたり設定を変更したりできます。

先に挙げておくと、JavaScript内でいじってOKな部分は以下の通りです。これら以外は(わかっている人を除き)基本的にいじらないでください。

パラメータ説明
wordJPs表示文章
wordENs英語文章
maxNum出題数の上限
random出題をランダムにするかどうか
resCmt結果画面のコメント表示有無

上記パラメータはソースコード内でもコメントを付けているので、探す際の参考にしてください。

編集時の注意

wordJPswordENsの文章は元コードのように配列内の位置をぴったり合わせてください。

let wordJPs = ["虎穴に入らずんば虎子を得ず", "千里の道も一歩から", ... , "ローマは一日にして成らず"]; // 表示文章
let wordENs = ["Nothing ventured, nothing gained.", "A journey of a thousand miles must start with the first step.", ... , "Rome wasn't built in a day."]; // 英語文章

wordJPs[A, B, C]なのにwordENs[C, A, B]のようになっている場合、表示がずれておかしな状態になってしまいます。

また、内部処理が正しくできるよう、英文にシングルクォーテーション(')が含まれている場合は全体をダブルクォーテーション(")で囲んでください。逆に、ダブルクォーテーションが含まれている場合は全体をシングルクォーテーションで囲んでください。例えば、以下のような感じになります。

let wordENs = ["Rock 'n' Roll", '"See," he said.'];

ローカル環境での遊び方

ローカル環境で遊ぶための手順は以下の通りです。

  1. ソースコードをコピーします。
  2. メモ帳を開き、コピーしたコードを貼り付けて.htmlファイルとして保存します。(名前はtyping-game.htmlなどお好きに)
    メモ帳のスクリーンショット
  3. 保存した.htmlファイルをダブルクリックするとブラウザが開き、ゲームをプレイできます。
    ゲームファイル画像

プログラム解説

基本的な構成はローマ字版と同じなのでそちらに譲るとして、本記事では英語版特有の処理について解説します。

かな→ローマへの変換や複数入力パターンへの対応が不要であるため、ローマ字版よりは全体的にシンプルなコードになっていますが、英文タイピングを正しく実現するために少し工夫が必要な部分もあります。

英文データ変換

まず、英文タイピングでメインとなる英文データの処理について。ローマ字版と違いかな→ローマ変換はありませんが、表示文章にスペース記号とHTML要素<u>␣</u>を含む必要があるため、元の英語文章と対応させた形で変換を行います。

英文データ変換

この変換処理を担っているのが以下のコード部分で、英語文章を読み込んだ時にスペースは<u>␣</u>で、他はそのままの形で1文字単位で配列resultに追加していき、最終的に文章全体のデータが格納されたresultを返します。

// データ変換
function convData(data) {
  const convMap = {' ':''};

  let remStr = String(data), slStr;
  let result = [];

  function splice() {
    let oneChar = remStr.slice(0, 1);
    remStr = remStr.slice(1);
    return oneChar;
  }

  while (remStr) {
    slStr = splice();
    if (slStr == ' ') {
      result.push(convMap[slStr]);
    } else {
      result.push(slStr);
    }
  }

  return result;
}

これにより、実際にタイピングする文章と表示文章をうまい具合に対応させることができます。

キーガイド

英文タイピングでは大文字や記号の入力でシフト操作が必要になるため、キーガイドもシフト操作を考慮した設計に変更します。

キーガイド画像

ローマ字版では@atmarkなどキーガイド用のクラス名への変換が必要な一部の記号のみ変換処理を行っていましたが、それをシフト操作にも応用します。具体的には以下のような形で変換を行います。

// 対応キーの変換
function keyConvert(key) {
  const keyMap = {
    'A':['a', 'rShift'], 'B':['b', 'rShift'], 'C':['c', 'rShift'], 'D':['d', 'rShift'], 'E':['e', 'rShift'],
    'F':['f', 'rShift'], 'G':['g', 'rShift'], 'H':['h', 'lShift'], 'I':['i', 'lShift'], 'J':['j', 'lShift'],
    'K':['k', 'lShift'], 'L':['l', 'lShift'], 'M':['m', 'lShift'], 'N':['n', 'lShift'], 'O':['o', 'lShift'],
    'P':['p', 'lShift'], 'Q':['q', 'rShift'], 'R':['r', 'rShift'], 'S':['s', 'rShift'], 'T':['t', 'rShift'],
    'U':['u', 'lShift'], 'V':['v', 'rShift'], 'W':['w', 'rShift'], 'X':['x', 'rShift'], 'Y':['y', 'rShift'],
    'Z':['z', 'rShift'], '!':['1', 'rShift'], '"':['2', 'rShift'], '#':['3', 'rShift'], '$':['4', 'rShift'],
    '%':['5', 'rShift'], '&':['6', 'lShift'], "'":['7', 'lShift'], '(':['8', 'lShift'], ')':['9', 'lShift'],
    '?':['slash', 'lShift'], '-':'hyphen', '@':'atmark', ';':'semicolon', ':':'colon',
    ',':'comma', '.':'period', '/':'slash', ' ':'space'
  };

  if (keyMap[key]) {
    return keyMap[key];
  } else {
    return key;
  }
}

上のコードではA['a', 'rShift']と変換することにより、Aを打つときにaと右シフトをキーガイドに表示させることができます。他のアルファベットや記号についても同様です。

キー入力判定

英語版のキー入力判定はローマ字版と違って複雑な場合分け処理がいらないので、以下のようにかなりシンプルな形で表現できます。(わかりやすいようにコメントを付けています)

if (key == wordEN[idx1]) { // 入力キーが対象の文字と一致しているかどうか
  sentence.innerHTML = colorTyped(); // 打った部分を色付け
  if (missFlag) { // 入力一致前にミスっている場合
    recordHTML += '' + key + '';
    weakKeys.push(key); // ミスったキー(現在のキー)を苦手キーに追加
    missFlag = false; // ミス判定フラグをOFFにリセット
  } else {
    recordHTML += key;
  }
  textMove();
  correct++; // 正解文字数を1増やす
  idx1++; // 次の文字へ
} else { // ミスってる場合
  if (key != 'Shift') { // シフトはスルーする
    missFlag = true; // ミス判定フラグON
    missed();
  }
}
if (idx1 == wordEN.length) { // 文章を打ち切った場合
  record.push(recordHTML);
  recordHTML = '';
  idx1 = 0;
  wordSet(); // 新しい文章をセット
} else {
  if (!missFlag) selActive();
}

プレイ中のキー入力判定で必要なコードはこれだけです。スッキリ!

対象の英文データと1文字ずつキーの一致判定を行いますが、キーは大文字・小文字などしっかり区別されているため、大文字や記号の場合も直接判定することができます。ただし、そのままだとシフトを押すたびにミス判定になってしまうため、入力キーがシフト(Shift)の場合はスルーするようにします。

コメントはまだありません