意外と簡単!VueJSで反射神経ゲームをつくってみよう(ダウンロード可)

さてさて、このところElectron開発が楽しいのでそちら関連の記事が多くなっていますが、やはりたまにはその他の話題も、ということで今回はVue.jsを使った開発のご紹介です。

テーマは、「反射神経ゲーム」です。

というのも、このブログではできるだけビギナーの方にもわかりやすく、興味をもてる話題を提供したいので、今回はいつものような業務感をなくしてゲームのつくり方を記事にしてみます。

では、今回も最後に教材ソースコードを用意しましたので、ぜひスキルアップに役立ててくださいね。

開発環境: Vue 2.5、Google Chrome 70

やりたいこと

まず丸い形をしたボタンを25個用意します。

そのボタンはランダムで1個だけ色が変わるので挑戦者はこの赤丸をクリックしていきます。

そして、赤丸を10個クリックするとゲーム終了。要するに最短時間を目指すゲームです。(ちなみに間違ったボタンをクリックした場合は+10秒ペナルティを加算します)

レイアウトをつくる

では、まずはレイアウトをつくりましょう。
実際のHTMLコードです。

<html>
<head>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet">
    <style>

        body {
            padding: 15px;
        }

        .circle-button {
            margin: 10px;
            text-align: center;
            vertical-align: middle;
            height: 75px;
            width: 75px;
            border-radius: 50%;
            color: #999999;
            border: 4px solid #CCCCCC;
            background: #fff;
            outline: none !important;
        }

        .current-button {
            color: #f44336;
            border: 4px solid #f44336;
        }

    </style>
</head>
<body>
    <div id="app">
        <h1>Vueで反射神経ゲーム!</h1>
        <hr>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <br>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <br>
        <button class="circle-button"></button>
        <button class="circle-button current-button"></button>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <br>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <br>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <button class="circle-button"></button>
        <br>
        <br>
        <h4>00:00:00 秒</h4>
        <button class="btn btn-lg btn-dark">スタート</button>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js"></script>
    <script>

        new Vue({
            el: '#app'
        });

    </script>
</body>
</html>

これを実行したものがこちらです。

では、このレイアウトを使ってJavaScriptのコードを書いていきましょう!

JavaScriptのコードをつくる

丸ボタン部分をつくる

まずは丸ボタンをvueで表示する部分を作っていきます。

<span v-for="buttonNumber in 25">
    <button class="circle-button" @click="onClick()"></button>
    <br v-if="buttonNumber%5 == 0">
</span>

使うのはv-forです。v-forは配列やオブジェクトのループによく使われますが、このように数字でも利用することができます。(ただし、数字は0ではなく1から始まります)

また、v-ifを使って、buttonNumber÷5がゼロになる、つまり5の倍数のときだけ<br>で開業するようにしています。そのため、ボタンが5つずつ上からならんで5列、合計25個のボタンが作成されることになります。

実際に実行したものがこちら。

※ ボタンをクリックしたときの挙動は後でつくります。

経過時間の部分をつくる

まずは、経過時間(秒)を格納する変数secondsを登録します。

そして、キャッシュがきくcomputedsecondsInHMSという名前の秒を「時:分:秒」表記に変換する疑似変数をつくります。

methods: {
    strPad(number) {

        let str = number.toString();

        if(str.toString().length == 1) {

            str = '0'+ str;

        }

        return str;

    }
},
computed: {
    secondsInHMS() {

        const hours = Math.floor(this.seconds / 3600);
        const minutes = Math.floor(this.seconds % 3600 / 60);
        const seconds = Math.floor(this.seconds % 3600 % 60);
        return this.strPad(hours) +':'
                + this.strPad(minutes) +':'
                + this.strPad(seconds)

    }
}

なお、数字がひと桁の場合はゼロを足して「05」としたいのでmethodsstrPad()も追加しています。

では、HTMLへ設置しましょう。

<h4>{{ secondsInHMS }} 秒</h4>

そして、テストで4000秒経過したものとして実行したものがこちらです。

スタートボタンをつくる

では、スタートボタンをクリックした時のコードをつくります。

まずは時間のタイマーが格納される変数timerを登録。

data: {
    seconds: 0,
    timer: null
},

そして、@clickstart()が実行されるようにします。

<button class="btn btn-lg btn-dark" @click="start()">スタート</button>

start()の中身はこうなります。

methods: {
    start() {

        this.seconds = 0;

        if(this.timer != null) {

            clearInterval(this.timer);

        }

        this.timer = setInterval(() => {

            this.seconds++;

        }, 1000);

    },
    
    // 省略

},

まずは始めにtimernullかどうかをチェックし、もしすでに時間タイマーが実行されているなら、clearInterval()でこれをクリアします。

そして、setInterval()で、1秒(1000ミリ秒)ごとに変数secondsを1ずつ足していきます。

これで時間が経つにつれて秒数が1ずつ増えるようになりました。

赤い丸をランダムで表示する部分をつくる

では、赤い丸をランダムで表示して、それがクリックされたら成功カウントを追加していく部分をつくっていきましょう。

まずは変数です。

data: {
    seconds: 0,
    timer: null,
    count: 0,
    currentNumer: 0
},

赤丸のクリックが成功したら、このcountを増やしていきます。
また、currentNumberは、現在表示されている赤丸の番号、つまり答えです。

では、次に1〜25の25個の数字をランダムにつくってcurrentNumberを更新するメソッドsetRandomNumber()をつくります。

methods: {

    // 省略

    setRandomNumber() {

        this.currentNumber = Math.floor((Math.random() * 25) + 1);

    },

    // 省略

},

そして、このsetRandomNumber()start()の一番最後の部分と1秒毎に実行されるsetInterval()の中の2ヶ所で実行するようにしましょう。(つまり、1秒毎にクリックすべき場所が変わります)

また、成功カウントが分かるcountもゲームがスタートしたらすぐに初期化するようにします。

start() {

    // 省略    

    this.count = 0;

    // 省略

    this.timer = setInterval(() => {

        this.setRandomNumber();
        this.seconds++;

    }, 1000);

    this.setRandomNumber();

},

次に、CSSで実際に赤丸を表示する部分です。

まず、classをメソッドで作成するよう:classへ変更しbuttonClass()を登録します。

<span v-for="buttonNumber in 25">
    <button :class="buttonClass(buttonNumber)"></button>
    <br v-if="buttonNumber%5 == 0">
</span>

buttonClass()の中身はこうなります。

buttonClass(number) {

    let classNames = ['circle-button'];

    if(number == this.currentNumber) {

        classNames.push('current-button');

    }

    return classNames;

}

やっているのは、ランダムにつくられた番号と現在の番号が同じ場合に赤丸のクラス、current-buttonを追加しているだけです。

これで赤丸がランダムに表示されるようになりました。
テストで実行してみましょう。

丸ボタンをクリックしたときのコードをつくる

では、最後に丸ボタンがクリックされたときのコードです。

<button
    :class="buttonClass(buttonNumber)"
    @click="answer(buttonNumber)"></button>

まず丸ボタンをクリックしたときにanswer()が実行されるようにします。

methods: {
    answer(number) {

        if(number == this.currentNumber) {

            this.count++;

            if(this.count == 10) {

                clearInterval(this.timer);
                alert("ゴール!\n結果は、「"+ this.secondsInHMS +"」でした。");

            }

            this.setRandomNumber();

        } else { // ペナルティ

            this.seconds += 10;

        }

    },

    // 省略

answer()の中では、クリックされたボタン番号とランダム番号が同じかをチェックして、もし同じ(正解)ならcountを1増やします。そして、もし成功カウントが10になったらタイマーを止め、ゲーム完了のアラートを表示します。

逆に間違ったボタンをクリックした場合は+10秒のペナルティです。

デモを用意しました

今回開発した反射神経ゲームは以下から体験できます。

Vueで反射神経ゲーム!

※ なおIEは対応してません。(ゴメンナサイ…IEはもう見限ったんですT^T)

教材ソースコードをダウンロード

今回実際に開発したソースコード一式を以下からダウンロードすることができます。cdnを使っているので、展開してindex.htmlを開くだけで実行できますよ!

VueJSで反射神経ゲーム