BETA

Vue + nuxtでボードゲームを6時間で作ってみた

投稿日:2018-11-04
最終更新:2018-11-05
※この記事は外部サイト(https://qiita.com/dorarep/items/b9783ea6cd...)からのクロス投稿です

20年前ぐらいはフリーゲームクリエイターとして活動していたドラレプです。 (大学、社会人になってからはめっきり活動もしなくなって死亡説すら流れていました。)

今はWebエンジニアとしてPHPやらRuby、Javascriptを主戦場にしてゲームからは離れていたのですが、Vueを触っていくうちに「あれ?これボードゲーム作りやすいんじゃ?」という気持ちが芽生えてきました。

Vueがボードゲーム作りに適していると思った理由

  • 状態に合わせたレンダリングはお手の物。
  • 状態の変化に合わせたアニメーションもtransitionなどの仕組みで簡単にできる。

つまりただactionをdispatchしてstateを変化させるだけで、破壊のアニメーションや、コマの移動などの動きの部分まで全部やってくれちゃうわけですね。 この辺りについては過去に軽くUnityやcocosを触った感じに比べると、より簡単に出来そう感があります。 (慣れの問題もあるかと思いますが)

とはいえ作ってみないとわからない問題もあるため、ひとまず作ってみることにしました。

Vueでゲーム作ってみた

Vue + Nuxtで作成開始です。 とにかく、細かいことにこだわらずにスピード重視でまず1つ作りきるを目標にやっていきます。

実際どんなゲームにするか最初の時点では決まっていませんでしたが、作ってるうちにゲームはこんな感じのものになりました。

  • ペンギンとヒヨコは、毎ターン縦横斜めランダムに1マスずつ移動する。
  • プレイヤーとエネミーは、毎ターン樽を好きな場所に1つ落とすことができる。
  • ペンギンとヒヨコは、樽のある位置、フィールド外には移動ができない。
  • ペンギンが移動できなくなったらプレイヤーの勝ち。
  • ヒヨコが移動できなくなったらエネミーの勝ち。

作業の流れをかいつまんで説明していきます。

画面の固定

まずスクロールを封じます。

<style>
    html, body {margin: 0; height: 100%; overflow: hidden}

背景画像も入れておきます。

#container {
    background-image: url('~assets/background.png');
    background-size: cover;

stateに合わせた画面の描画

こんな感じのstateを定義して、それに合わせて画面を描画します。

  • board: 2次元配列に[0-1]を入れて、樽の有無を表してます。
  • player{x, y}: ヒヨコのx, y位置。
  • enemy{x, y}: ペンギンのx, y位置。
  • loser: 敗者は誰か。試合中か否かのゲームステートとしても。

この辺りは特筆することもないので省略。

stateの操作

押した位置のboardを1にしたり、ランダムにキャラクターを動かしたり。 この辺りもゴリゴリ書くだけなので省略。

stateの変化に合わせたアニメーションの作成

準備

ここからが真骨頂ですね! まずアニメーションライブラリのanimate.cssを入れておきます。

yarn add animate.css
module.exports = {
  css: [
    'animate.css'
  ],

樽の落下アニメーション

transitionでenter-active-classをanimated bounceInDownに設定します。 これだけで、boardが1になるだけで落下アニメーションしてくれます!

<template lang="pug">
  transition(
    enter-active-class="animated bounceInDown"
  )
    img(src="~/assets/barrel.png")
</template>

キャラクターの移動アニメーション

transition-groupなどを使ってうまくできないかなと思っていたのですがなかなかうまくいかなかったので、下記ページのやり方を参考にさせて頂きました。

<template lang="pug">
  transition(
    v-on:before-enter="beforeEnter"
    v-on:after-enter="afterEnter"
    v-on:before-leave="beforeLeave"
  )
    slot
</template>

<script>
  let previousPosition = {}

  export default {
    props: {
      uuid: { type:String, default: null },
      duration: { type:Number, default: 300 }
    },
    data: () => {
      return {
        prev: null
      }
    },
    methods: {
      beforeLeave (el) {
        previousPosition[this.uuid] = el.getBoundingClientRect()
      },
      beforeEnter (el) {
        el.hidden = true
      },
      afterEnter (el) {
        el.hidden = false

        if (!previousPosition[this.uuid]) return
        this.move(previousPosition[this.uuid], el.getBoundingClientRect())
      },
      move (previous, current) {
        this.$el.animate([
          { transform: `translate(${previous.x - current.x}px, ${previous.y - current.y}px)` },
          { transform: 'translate(0, 0)' }
        ], { duration: this.duration })
      }
    }
  }
</script>

これで移動時にアニメーションさせたい要素をかこうと、スムーズに移動してくれるようになります!

<template lang="pug">
  smoothly-movable(uuid="player")
    img(src="~/assets/player.gif")
</template>

※uuidがuuidになってないのは気にしないでください

これだけでなにも考えずにstateを変更するだけでアニメーションをしてくれるようになりました!

音の再生

まずwebpackがサウンドファイルをimportできるようにするため、nuxt.config.jsにwebpackのloaderの追加設定を書きます。

    extend (config, { isDev, isClient }) {
      config.module.rules.push({
        test: /\.(ogg|mp3|wav|mpe?g)$/i,
        use: 'file-loader',
        exclude: /(node_modules)/
      });

すると、こんな感じでassetsにあるサウンドファイルを再生することができるようになります!

import clickSound from '~/assets/sound/click.wav';

const audio = new Audio(clickSound)
audio.play()

というわけで完成

というわけで、だいたい作業6時間ほどで完成しました。 素材探してる時間とか、Audioどうやって鳴らすの?みたいな調査の時間もだいぶ取られてるので、実際のコーディング時間はそこまで長くないと思います。

Demo

試しに1つ作りきるが目標なので、ゲーム的なクオリティには期待しないでください。 ※音がなります

感想

というわけで、「思ったより簡単にできた」のが正直な感想でした!

メモリ管理どうなってるの?とか、規模が大きくなってくるとまた別の問題も出てくるかと思いますので、一概にVueがボードゲーム作りに向いているとはまだいえないかもしれません。

とはいえ新しいことを試すときは「変にハードル上げず作りきってみる」が第一だと思ってるので、一歩ずつ色々試していきたいと思います!

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

読書記録: https://booklog.jp/users/dorarep twitter: https://twitter.com/dorarep

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!