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

【HTML,CSS,JS】タイピングゲーム作成(1/3)

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

WEBブラウザで動くタイピングゲーム

今回は、HTML、CSS、JavaScriptを使用して簡単なタイピングゲームを作成します。

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

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

タイピングゲーム

アプリ概要

• タイピングゲームアプリケーション
• ユーザーは制限時間内に表示される単語を正確に入力
• スコアは正確に入力できた単語の数

VSCodeで作ってみよう

作成手順
  1. フォルダを作成
  2. 「.html」「.css」「.js」の各ファイルの作成
  3. 「Go Live」でブラウザを立ち上げ実行

まず「VSCode」を起動します。

左上の「ファイル」をクリックして「フォルダを開く」を選択します。

エクスプローラー内で作りたい場所を決め、「新しいフォルダー」をクリックして新規フォルダ「TypingGames」を作成します。

ポップが出ますが、自分で作成したフォルダなので「はい、作成者を信頼します」をクリックします。

このような階層でフォルダファイルを作成していきます。

project_root/

├── index.html

├── css/
│   └── style.css

└── js/
    ├── word.js
    ├── timer.js
    ├── game.js
    ├── ui.js
    └── main.js

TypingGames」の横にあるの新規フォルダと新規ファイルのマークをクリックして「css」「js」フォルダを作成してください。次にフォルダ内に以下のファイルを作成してください。

必要なファイル
  • index.html
  • style.css
  • word.js
  • timer.js
  • game.js
  • ui.js
  • main.js

ファイルが作成出来たら、以下の完成コード対応するファイルにコピペしてください。

コードの細かい解説は次のページで行いますのでとりあえず動かしてみましょう。

コードの右上にコピーマークがあります。

HTML (index.html)

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>タイピングゲーム</title>
    <!-- スタイルシートの読み込み -->
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <div class="container">
        <h1>タイピングゲーム</h1>
        <div id="game">
            <!-- タイピングする単語を表示する要素 -->
            <p id="word"></p>
            <!-- ユーザーの入力を受け付ける入力フィールド -->
            <!-- autocomplete, autocorrect, autocapitalize, spellcheckを無効にして予測変換を防止 -->
            <input type="text" id="input" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false">
            <!-- タイマーを表示する要素 -->
            <p id="timer"></p>
            <!-- スコアを表示する要素 -->
            <p id="score"></p>
        </div>
        <!-- ゲームを開始するボタン -->
        <button id="startButton">スタート</button>
    </div>
    <!-- JavaScriptファイルの読み込み(順序が重要) -->
    <script src="js/word.js"></script>
    <script src="js/timer.js"></script>
    <script src="js/game.js"></script>
    <script src="js/ui.js"></script>
    <script src="js/main.js"></script>
</body>
</html>

CSS (css/style.css)

/* ページ全体のスタイル */
body {
    font-family: Arial, sans-serif;
    display: flex;
    justify-content: center; /* 水平方向の中央揃え */
    align-items: center; /* 垂直方向の中央揃え */
    height: 100vh; /* ビューポートの高さいっぱいに設定 */
    margin: 0;
    background-color: #f0f0f0;
}

/* ゲームコンテナのスタイル */
.container {
    text-align: center;
    background-color: white;
    padding: 2rem;
    border-radius: 10px; /* 角を丸くする */
    box-shadow: 0 0 10px rgba(0,0,0,0.1); /* 影をつける */
}

/* ゲーム部分のスタイル */
#game {
    margin-bottom: 1rem;
}

/* タイピングする単語のスタイル */
#word {
    font-size: 2rem;
    margin-bottom: 1rem;
}

/* 入力フィールドのスタイル */
#input {
    font-size: 1.5rem;
    padding: 0.5rem;
    width: 80%;
    margin-bottom: 1rem;
}

/* タイマーとスコアのスタイル */
#timer, #score {
    font-size: 1.2rem;
    margin-bottom: 0.5rem;
}

/* スタートボタンのスタイル */
button {
    font-size: 1.2rem;
    padding: 0.5rem 1rem;
    cursor: pointer; /* ホバー時にカーソルを変更 */
}

JavaScript (js/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)];
}

JavaScript (js/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;
    }
}

JavaScript (js/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);
    }
}

JavaScript (js/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} です!`);
    }
};

JavaScript (js/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 = ''; // 入力が正しければ入力フィールドをクリア
    }
});

コピペが終わったら左上の「ファイル」のメニューから「すべて保存」を押してください。

※Ctrlを押しながらKを押して、キーを離してSを押すとショートカットキーですべてのファイルを保存できます。

最後に右下の「Go Live」をクリックするとブラウザが立ち上がりプログラムが実行されます。

以下のようにブラウザが立ち上がりゲームが開始されます。

まとめ

アプリの特徴

• シンプルで直感的なUI設計
• 60秒の制限時間
• ランダムに選ばれる英単語
• リアルタイムのスコアとタイマー表示
• 入力予測や自動補完を無効化し、純粋なタイピングスキルを測定
• モジュール化された JavaScript コード構造

このアプリケーションは、ユーザーのタイピングスキルを楽しく向上させることを目的としたインタラクティブなタイピングゲームです。HTMLCSSJavaScriptを使用して構築されており、モダンなウェブ技術を活用しています。

ユーザーインターフェースはシンプルで、コードはモジュール化されており、各機能(単語管理、タイマー、ゲームロジック、UI操作)が別々のファイルに分けられています。これにより、コードの保守性と拡張性が向上しています。

コメント

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