LoginSignup
2
0

More than 3 years have passed since last update.

【Vue.js】Composition-APIで簡単なタイピングゲームを作ってみました

Posted at

以前Vue.jsで作った奴をComposition-APIに書き換えて+αしてみました。

ロジックとかは大体同じです。

環境

version
macOS Catalina 10.15.7
npm 6.9.0
node 10.16.0
vue 2.6.11
@vue/composition-api 1.0.0-rc.2

完成品

demo

demo

AppVue
<template>
  <div id="app">
    <div v-if="!playing">Enterキーでスタート</div>
    <div v-else>
      <div>残り{{ time }}</div>
      <div>単語数:{{ typedWord }} / ミス:{{ miss.num }}</div>
      <br />
      <div>
        <div v-if="miss.status">😫</div>
        <div v-else><br /></div>
        <span style="opacity: 0.3;">{{ typeChar }}</span>
        <span>{{ nowWord }}</span>
      </div>
    </div>
    <br />
    <div v-if="!time">ゲーム終了!おつかれさまでした!🍻</div>
  </div>
</template>

<script>
import { ref, reactive, toRefs } from '@vue/composition-api';
export default {
  setup() {
    // 単語関係ーーーーーーーーーーーーーーーーーーーーーーー
    const wordStore = reactive({
      nowWord: '',  // 出題されている単語
      typeChar: '', // 入力した単語の一文字
      typedWord: 0, // 入力し終えた単語の数
      words: [      // 出題単語
        'dog',
        'cat',
        'monkey',
        'elephant',
        'giraffe',
        'penguin',
        'lion',
        'tiger',
        'pig',
        'cow',
      ],
    });
    // wordsからランダムな単語を1つ取り出す
    const setWord = () => {
      wordStore.nowWord = wordStore.words[Math.floor(Math.random() * wordStore.words.length)];
    };

    // タイピング関係ーーーーーーーーーーーーーーーーーーーー
    const miss = reactive({
      // ミスの回数とミスしたかどうか
      num: 0,
      status: false,
    });
    const keydown = (e) => {
      // 間違えたときの処理
      if (wordStore.nowWord[0] !== e.key) {
        miss.num++;
        miss.status = true;
        return;
      }
      miss.status = false;
      // typeCharに入力できた文字を追加していく
      wordStore.typeChar += e.key;
      // 入力できたらnowWordの頭文字を削除していく
      wordStore.nowWord = wordStore.nowWord.slice(1);
      // 単語を入力し終えたときの処理
      if (!wordStore.nowWord) {
        wordStore.typedWord++;
        wordStore.typeChar = '';
        setWord();
      }
    };

    // カウントダウン関係ーーーーーーーーーーーーーーーーーー
    const time = ref(10); // カウントダウンのタイム
    const countDownTimer = () => {
      const id = setInterval(() => {
        time.value--;
        if (!time.value) {
          // ゲーム終了。keydown関数のキーイベントを削除
          removeEventListener('keydown', keydown);
          clearInterval(id);
        }
      }, 1000);
    };

    // ゲーム開始ーーーーーーーーーーーーーーーーーーーーーー
    const playing = ref(false); // ゲームが始まっているかどうか
    const startGame = (e) => {
      // 入力がEnterキーでなければゲームが始まらない
      if (e.key !== 'Enter') return;
      playing.value = true;
      // 各関数実行
      // startGame関数のキーイベントを削除
      removeEventListener('keydown', startGame);
      // keydown関数のキーイベントを発火
      addEventListener('keydown', keydown);
      setWord();
      countDownTimer();
    };
    // startGame関数のキーイベント発火
    addEventListener('keydown', startGame);

    return {
      ...toRefs(wordStore),
      playing,
      miss,
      time,
      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;
  font-size: 20px;
  margin-top: 100px;
}
</style>


ロジックとそれに関連する変数ごとに分けてまとめるように意識しました。

素のjavascriptで書いてる感じが強かったです。

もっとCompotision-APIの要素を入れたかったですが、これが限界でした笑

2
0
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
2
0