HTML、CSS、JavaScriptタイピングゲームWEBアプリ(JavaScript)

【JavaScriptコード解説】タイピングゲーム作成(3/3)

タイピングゲームのアイキャッチ画像03 HTML、CSS、JavaScript

WEBブラウザで動くタイピングゲームのコード解説(JavaScript)

前回作成したWEBブラウザゲームのコード解説(JavaScript)です。

  • ブラウザゲームのURL
  • GitHubのURL

GitHubのPagesで公開しているのでゲームプレイできます。

タイピングゲーム

コード概要

• タイピングゲームのJavaScript実装
• 単語リストタイマーゲームロジックUI操作の機能を含む
• オブジェクト指向プログラミングを活用したクラス設計
• イベントリスナーを使用したユーザーインタラクションの処理
• モジュール化されたコード構造

JavaScriptの解説

word.js

// タイピングゲームで使用する単語のリスト
const words = [
    'Hello', 'World', 'JavaScript', 'Programming', 'Computer',
    'Algorithm', 'Database', 'Network', 'Security', 'Framework'
];

/**
 * ランダムな単語を取得する関数
 * @returns {string} ランダムに選ばれた単語
 */
function getRandomWord() {
    // Math.random()で0以上1未満の乱数を生成し、
    // words.lengthを掛けて配列のインデックス範囲内の数値にする
    // Math.floor()で小数点以下を切り捨てて整数にする
    return words[Math.floor(Math.random() * words.length)];
}

解説:

  • words配列: タイピングゲームで使用する単語のリストを定義しています。
  • getRandomWord()関数: この配列からランダムに1つの単語を選んで返します。

この部分は、ゲームの基本となる単語リストとその中からランダムに単語を選ぶ機能を提供しています。Math.random()を使って0から1未満のランダムな小数を生成し、それに配列の長さを掛けることで、配列のインデックス範囲内のランダムな数を得ています。Math.floor()で小数点以下を切り捨てて整数にすることで、有効な配列のインデックスとなります。

timer.js

/**
 * タイマークラス
 */
class Timer {
    /**
     * @param {number} duration - タイマーの継続時間(秒)
     * @param {function} onTick - 毎秒呼び出されるコールバック関数
     * @param {function} onComplete - タイマー終了時に呼び出されるコールバック関数
     */
    constructor(duration, onTick, onComplete) {
        this.duration = duration;
        this.remaining = duration;
        this.onTick = onTick;
        this.onComplete = onComplete;
        this.timerId = null;
    }

    /**
     * タイマーを開始する
     */
    start() {
        this.timerId = setInterval(() => {
            this.remaining--;
            this.onTick(this.remaining);
            if (this.remaining <= 0) {
                this.stop();
                this.onComplete();
            }
        }, 1000); // 1000ミリ秒 = 1秒ごとに実行
    }

    /**
     * タイマーを停止する
     */
    stop() {
        if (this.timerId) {
            clearInterval(this.timerId);
            this.timerId = null;
        }
    }

    /**
     * タイマーをリセットする
     */
    reset() {
        this.stop();
        this.remaining = this.duration;
    }
}

解説:

  • Timerクラス: ゲームのタイマー機能を提供します。
  • コンストラクタ(constructor): タイマーの設定(継続時間、毎秒の処理、完了時の処理)を初期化します。
  • start()メソッド: タイマーを開始し、1秒ごとに残り時間を減らします。
  • stop()メソッド: タイマーを停止します。
  • reset()メソッド: タイマーをリセットして初期状態に戻します。

このクラスは、ゲームの時間管理を担当します。コンストラクタで設定された継続時間に基づき、start()メソッドが呼ばれると1秒ごとに残り時間が減少します。setInterval()を使って1秒ごとに処理を実行し、残り時間を更新しています。タイマーが0になったら自動的に停止し、完了時の処理を呼び出します。

ui.js

/**
 * UI操作を管理するオブジェクト
 */
const ui = {
    // HTML要素への参照
    wordElement: document.getElementById('word'),
    inputElement: document.getElementById('input'),
    timerElement: document.getElementById('timer'),
    scoreElement: document.getElementById('score'),
    startButton: document.getElementById('startButton'),

    /**
     * 単語を画面に表示する
     * @param {string} word - 表示する単語
     */
    displayWord(word) {
        this.wordElement.textContent = word;
    },

    /**
     * タイマーを更新する
     * @param {number} time - 残り時間
     */
    updateTimer(time) {
        this.timerElement.textContent = `残り時間: ${time}秒`;
    },

    /**
     * スコアを更新する
     * @param {number} score - 現在のスコア
     */
    updateScore(score) {
        this.scoreElement.textContent = `スコア: ${score}`;
    },

    /**
     * ゲームの状態に応じてUI要素を設定する
     * @param {boolean} isPlaying - ゲームがプレイ中かどうか
     */
    setGameState(isPlaying) {
        this.inputElement.disabled = !isPlaying;
        this.startButton.disabled = isPlaying;
        if (!isPlaying) {
            this.inputElement.value = '';
        }
    },

    /**
     * ゲーム結果を表示する
     * @param {number} score - 最終スコア
     */
    showResult(score) {
        alert(`ゲーム終了!あなたのスコアは ${score} です!`);
    }
};

解説:

  • uiオブジェクト: ゲームのユーザーインターフェース(UI)を管理します。
  • HTML要素への参照: ゲームに必要なDOM要素を取得し、保持します。
  • displayWord(): 画面に単語を表示します。
  • updateTimer(): タイマーの表示を更新します。
  • updateScore(): スコアの表示を更新します。
  • setGameState(): ゲームの状態に応じてUI要素の有効/無効を切り替えます。
  • showResult(): ゲーム終了時に結果を表示します。

このオブジェクトは、ゲームの視覚的な部分を担当します。HTML要素への参照を保持することで、それぞれの要素に対して簡単に操作が可能になります。HTML要素の内容を更新したり、ゲームの状態に応じて入力フィールドやボタンの有効/無効を切り替えたりする機能を提供します。

game.js

/**
 * ゲームクラス
 */
class Game {
    constructor() {
        this.score = 0;
        this.currentWord = '';
        // 60秒のタイマーを作成
        this.timer = new Timer(60, this.updateTimer.bind(this), this.endGame.bind(this));
    }

    /**
     * ゲームを開始する
     */
    start() {
        this.score = 0;
        this.updateScore();
        this.nextWord();
        this.timer.start();
        ui.setGameState(true);
    }

    /**
     * 次の単語を設定する
     */
    nextWord() {
        this.currentWord = getRandomWord();
        ui.displayWord(this.currentWord);
    }

    /**
     * ユーザーの入力をチェックする
     * @param {string} input - ユーザーの入力
     * @returns {boolean} 入力が正しければtrue、そうでなければfalse
     */
    checkInput(input) {
        if (input === this.currentWord) {
            this.score++;
            this.updateScore();
            this.nextWord();
            return true;
        }
        return false;
    }

    /**
     * タイマーを更新する
     * @param {number} remaining - 残り時間
     */
    updateTimer(remaining) {
        ui.updateTimer(remaining);
    }

    /**
     * スコアを更新する
     */
    updateScore() {
        ui.updateScore(this.score);
    }

    /**
     * ゲームを終了する
     */
    endGame() {
        ui.setGameState(false);
        ui.showResult(this.score);
    }
}

解説:

  • Gameクラス: ゲームのメインロジックを管理します。
  • コンストラクタ: スコアや現在の単語、60秒のタイマーを作成します。
  • start(): ゲームを開始し、初期化処理を行います。
  • nextWord(): 次の単語を設定し、画面に表示します。
  • checkInput(): ユーザーの入力をチェックし、正解の場合はスコアを増やして次の単語に進みます。
  • updateTimer(): タイマーの表示を更新します。
  • updateScore(): スコアの表示を更新します。
  • endGame(): ゲームを終了し、結果を表示します。

このクラスはゲーム全体の中心的な役割を果たし、スコア管理やタイマー機能など多くの重要なロジックがここに集約されています。コンストラクタで初期化されたスコアやタイマーは、ゲーム開始時に設定されるため、新しいセッションごとに状態がリセットされます。特に、ユーザーから入力された文字列と現在表示されている単語との比較(checkInputメソッド)は、このゲームの核心部分です。一致した場合にはスコアが増加し、新しい単語へ移行します。

main.js

// ゲームインスタンスを作成
const game = new Game();

// スタートボタンにクリックイベントリスナーを追加
ui.startButton.addEventListener('click', () => {
    game.start();
    ui.inputElement.focus(); // 入力フィールドにフォーカスを当てる
});

// 入力フィールドに入力イベントリスナーを追加
ui.inputElement.addEventListener('input', (e) => {
    const input = e.target.value;
    if (game.checkInput(input)) {
        e.target.value = ''; // 入力が正しければ入力フィールドをクリア
    }
});

解説:

  • Gameインスタンスの作成: 新しいゲームオブジェクト(インスタンス)生成。
  • スタートボタンのイベントリスナー: クリックでゲームを開始し、入力フィールドにフォーカスを当てます。
  • 入力フィールドのイベントリスナー: 入力があるたびにゲームロジックをチェックし、正解の場合は入力をクリアします。

この部分は、ユーザーの操作とゲームロジックを結びつける役割を果たします。ボタンクリックや入力に応じて適切なゲーム機能を呼び出し、ユーザーとゲームのインタラクションを管理しています。

以上が、このタイピングゲームの主要なコンポーネントとその機能の解説です。これらの部品が組み合わさることで、ゲームシステムが構築されています。各部分が独立していながらも連携して動作することで、保守性の高い構造になっています。

まとめ

コードの特徴

• ES6+の機能(クラス、アロー関数、テンプレートリテラル)の活用
• カプセル化とモジュール化
によるコードの整理
• コールバック関数を使用したイベント駆動型プログラミング
• **ドキュメントオブジェクトモデル(DOM)**操作による動的なUI更新
• JSDoc形式のコメントによるコードドキュメンテーション
• ランダム関数を使用した単語選択ロジック
• タイマー機能の実装による時間制限付きゲームプレイ
• イベントリスナーを使用したユーザー入力の処理

コードはオブジェクト指向プログラミングの原則に従って構造化されており、主要な機能がクラスとオブジェクトに分割されています。

Gameクラスはゲームの中心的なロジックを管理し、Timerクラスは時間制限機能を提供します。uiオブジェクトはDOMとの相互作用を担当し、ユーザーインターフェースの更新を処理します。これらのコンポーネントが協調して動作することで、シームレスなゲーム体験を実現しています。

コード全体を通して、ES6+の機能のクラス構文、アロー関数、テンプレートリテラルが効果的に使用されており。また、JSDoc形式のコメントを使用することで、コードの可読性と保守性が向上しています。

イベントリスナーの使用により、ユーザーの入力に対して即座に反応するインタラクティブな体験が可能になっています。さらに、ランダム関数を使用した単語選択により、ゲームに予測不可能性と再プレイ価値を加えています。全体として、このコードはモダンなJavaScript開発のベストプラクティスを示す良い例となっており、拡張性と保守性に優れた設計になっています。初心者にとっては学習の良いリソースとなり、経験豊富な開発者にとっては効率的なゲーム開発の基盤として活用できる質の高い実装といえるでしょう。

コメント

タイトルとURLをコピーしました