6
1

More than 3 years have passed since last update.

Vue.jsで超簡単なタイピングゲームを作ります

Last updated at Posted at 2020-12-06

完成品

demo


App.vue
<template>
  <div id="app">
    <div v-if="playing">
      <span>{{ pressed }}</span>{{ word }}
      <br>
      <br>
      miss:{{ miss }}
    </div>
    <div v-else>Spaceでスタート</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      words: ['apple', 'banana', 'grape'],
      word: '',
      pressed: '',
      miss: 0,
      playing: false,
    };
  },
  created() {
    addEventListener('keydown', (e) => {
      if (e.key !== ' ' || this.playing) {
        return;
      }
      this.playing = true;
      this.setWord();
      this.keyDown();
    });
  },
  methods: {
    setWord() {
      this.word = this.words.splice(Math.floor(Math.random() * this.words.length), 1)[0];
    },
    keyDown() {
      addEventListener('keydown', (e) => {
        if (e.key !== this.word[0]) {
          this.miss++;
          return;
        }
        this.pressed += e.key;
        this.word = this.word.slice(1);
        if (this.word.length === 0) {
          this.pressed = '';
          if (this.words.length === 0) {
            this.word = 'おしまい';
            return;
          }
          this.setWord();
        }
      });
    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

span {
  opacity: 0.5;
}
</style>

配列からランダムな値を取り出す

setWordメソッドを作り、createdで呼び出しています。
その際wordsの中からランダムな値をwordに格納。

App.vue
<template>
  <div id="app">
    <div>
      {{ word }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      words: ['apple', 'banana', 'grape'],
      word: '',
    }
  },
  created() {
    this.setWord();
  },
  methods: {
    setWord() {
      this.word = this.words[Math.floor(Math.random() * this.words.length)];
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

タイピングの処理

keyDownメソッドを作り、createdで呼び出しています。
入力されたKeyと現在のwordの頭文字が一致しない場合はmissが加算。

pressedには入力されたkeyを格納。
wordにはkeyが押されるごとに頭文字を削除し再代入します。
これで入力した文字と未入力の文字を仕分けしています。
wordが全て無くなったらpressedをリセットし、新しいwordを表示させます。

App.vue
<script>
export default {
  data() {
    return {
      words: ['apple', 'banana', 'grape'],
      word: '',
      pressed: '',
      miss: 0,
    }
  },
  created() {
    this.setWord();
    this.keyDown()
  },
  methods: {
    setWord() {
      this.word = this.words[Math.floor(Math.random() * this.words.length)];
    },
    keyDown() {
      addEventListener('keydown', (e) => {
        if (e.key !== this.word[0]) {
          this.miss++;
          return;
        }
        this.pressed += e.key;
        this.word = this.word.slice(1);
        if (this.word.length === 0) {
          this.pressed = '';
          this.setWord();
        }
      });
    },
  }
}
</script>

Viewでpressedword連結させます。
入力されていることが分かりやすいようにpressedspanタグで囲みスタイルをつけます。

あとmissのカウントをここで表示させます。

App.vue
<template>
  <div id="app">
    <div>
      <span>{{ pressed }}</span>{{ word }}
      <br>
      <br>
      miss:{{ miss }}
    </div>
  </div>
</template>

<style>
span {
  opacity: 0.5;
}
</style>

スクリーンショット 2020-12-01 22.33.49.png


単語の重複を防ぐ

現時点だと単語が重複して無限に遊べるので一度出た単語は消してしまいます。

App.vue
<script>

    setWord() {
      this.word = this.words.splice(Math.floor(Math.random() * this.words.length), 1)[0];
    },

</script>

ゲームの開始と終了の処理

dataplayingを追加しSpaceキーを押すことでfalseからtrueにします。

App.vue
<template>
  <div id="app">
    <div v-if="playing">
      <span>{{ pressed }}</span>{{ word }}
      <br>
      <br>
      miss:{{ miss }}
    </div>
    <div v-else>Spaceでスタート</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      words: ['apple', 'banana', 'grape'],
      word: '',
      pressed: '',
      miss: 0,
      playing: false,
    }

</script>

Spaceキーが押されたらplayingtrueになり、ゲームスタートです。
|| this.playingで再スタートを防ぎます。

App.vue


<script>

  created() {
    addEventListener('keydown', (e) => {
      if (e.key !== ' ' || this.playing) {
        return;
      }
      this.playing = true;
      this.setWord();
      this.keyDown();
    });
  },

</script>

wordsが空になったらおしまいと表示させゲーム終了です。

App.vue
<script>

    keyDown() {
      addEventListener('keydown', (e) => {
        if (e.key !== this.word[0]) {
          this.miss++;
          return;
        }
        this.pressed += e.key;
        this.word = this.word.slice(1);
        if (this.word.length === 0) {
          this.pressed = '';
          if (this.words.length === 0) {
            this.word = 'おしまい';
            return;
          }
          this.setWord();
        }
      });
    },
  }
}
</script>

おしまい

以上となります。
もっとこうした方が良いんじゃない?
というのがあれば是非教えて下さいm(_ _)m

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1