POTTIRI'S AUTOBIOGRAPHY

ダイエットやITで遊ぶアラフォーエンジニアの自伝ブログです。

爆弾パズルゲームにタイミングとアニメーションを追加

f:id:pottiri:20201115013426j:plain

お疲れさまです。POTTIRIです。
寒くなってきたので我が家も鍋が増えてきました。
今日はおでんです。
以前関東に住んでた頃、スーパーに牛すじが売ってなくて困ったのですが、
おでんに牛すじ入れるのって西の方だけなんです?

さて、本日やっとこさ爆弾パズルゲームで敵を動かすことができるようになりました。

今日のステージ

今日はこちらです。

敵が動くようになりました。
敵の動きを予測してちょうどいいタイミングで爆弾をおいてください😉
現状縦の動きしか実現できていませんが、横や斜めの動きも作っていきたい。
思い描いているのは、

  • 一瞬考えて
  • 一瞬タイミングを測る

そんな小さい小さいパズルを日々のスキマ時間にあわよくばやってもらうゲーム。
ちょっとずつ理想に近づけていきたいです。

あと、爆弾を置いた時に動きをつけたりしています。
これにより爆弾を置くのに一秒かかるようになりました。

爆弾を置いてから爆発まで3秒あり、
この間も敵は動くので4秒後の敵の位置を予測して爆弾を置かないといけないようになりました。
・・・4秒って微妙ですかね・・・?🤔
4秒ってあまり聞き慣れない数字ですよね。
トータル3秒の方が直感的かな・・・?
しばらく様子見です。

他の面はこちらにあるので、万が一興味を持たれたらサイトを訪れてください。

blast.pottiri.tech

技術的な話

今回、爆風に自分なりのアニメーションを入れるようにしてみました。

このアニメーションはCSSの機能で実現しています。

<img src="/static/bomb/explosion-bomb.svg" class="explosion-bomb" />
<img src="/static/bomb/fire.svg" class="blast" style="--animation-second: 0.5s; --translate-x: -112px; --translate-y: 0px; --rotate: 90deg;" />
<img src="/static/bomb/fire.svg" class="blast" style="--animation-second: 0.6s; --translate-x: -112px; --translate-y: 0px; --rotate: 90deg;" />
<img src="/static/bomb/fire.svg" class="blast" style="--animation-second: 0.7s; --translate-x: -112px; --translate-y: 0px; --rotate: 90deg;" />
<img src="/static/bomb/fire.svg" class="blast" style="--animation-second: 0.8s; --translate-x: -112px; --translate-y: 0px; --rotate: 90deg;" />
<img src="/static/bomb/fire.svg" class="blast" style="--animation-second: 0.9s; --translate-x: -112px; --translate-y: 0px; --rotate: 90deg;" />
<img src="/static/bomb/fire.svg" class="blast" style="--animation-second: 1s; --translate-x: -112px; --translate-y: 0px; --rotate: 90deg;" />
.explosion-bomb {
  width: 1.75rem !important;
  height: 1.75rem !important;
  position: absolute;
  z-index: 100;
  animation: explosion-bomb-animation 0.5s forwards;
}
@keyframes explosion-bomb-animation {
  0% {transform: scale(0, 0);}
  90% {transform: scale(2.0, 2.0);}
  100% {transform: scale(0, 0);}
}
.blast {
  width: 1.75rem !important;
  height: 1.75rem !important;
  position: absolute;
  z-index: 100;
  animation-timing-function: linear;
  animation: blast-animation var(--animation-second) forwards;
}
@keyframes blast-animation {
  0% {
    transform: translateX(0px) translateY(0px) rotate(var(--rotate));
    -webkit-transform: translateX(0px) translateY(0px) rotate(var(--rotate));
  }
  90% {
    transform: translateX(var(--translate-x)) translateY(var(--translate-y)) rotate(var(--rotate));
    -webkit-transform: translateX(var(--translate-x)) translateY(var(--translate-y)) rotate(var(--rotate));
  }
  100% {
    transform: translateX(var(--translate-x)) translateY(var(--translate-y)) rotate(var(--rotate)) scale(0, 0);
    -webkit-transform: translateX(var(--translate-x)) translateY(var(--translate-y)) rotate(var(--rotate)) scale(0, 0);
  }
}

爆弾を置いた場所に爆発アニメーションを発生させます。
爆発アニメーションは、
CSSのtransform: scaleを利用します。
.explosion-bombexplosion-bomb-animationの定義内で使っています。
transform: scaleは1が標準です。
0%が最初で、100%が最後。
これを0.5sで一回だけ動かすというのが、
animation: explosion-bomb-animation 0.5s forwards;
という記述です。
forwardsというのが一回だけを意味します。
繰り返すならinifiniteですね。
最初はscaleをゼロにして、一瞬2倍にしてまたゼロにすることで一瞬拡大させてます。
爆発っぽい・・・ですよね。なってない?😅

爆風の方は.blastblast-animationです。
blast-animationtransform: rotateで炎の向きを決めます。
実は炎のが画像は1種類しか用意ししておらず、これをば爆風の向きに合わせて回転させています。
そしてtransform:translateXtransform:translateYで炎を移動させています。
とはいえ炎の向きは8種類あるし、炎の移動パターンは無数にあるので、
これらを事前に用意することはやってられません。
なので炎の移動距離は回転の角度はJavaScriptで計算し、HTMLタグ内のstyle要素で変数として渡すようにしています。
これでいくらでもパターンが作れます。
このCSS定義を0.25sぐらいで実行することで炎が飛んでるように見せています。

が!これだと火の玉がポーンと飛んでくだけで、爆風っぽくありません。
なので、
複数の炎をちょっとずつスピードを変えながら連続で飛ばしてみました。
今の所これで爆風!ということで自分を納得させています(笑)

ところで、この炎を連続で飛ばすという処理ですが、
Vue.jsで実現するにあたり配列にCSS定義をぶち込むことでそれがなせるようになっているのですが、今の所そこの処理がこんなことになってます。

      let $vm = this
      $vm.blasts[skey].push({
        '--animation-second': '0.5s',
        '--translate-x': diffX + 'px',
        '--translate-y': diffY + 'px',
        '--rotate': ROTATE[axis].rotate
      })
      $vm.blasts[skey].push({
        '--animation-second': '0.6s',
        '--translate-x': diffX + 'px',
        '--translate-y': diffY + 'px',
        '--rotate': ROTATE[axis].rotate
      })
      $vm.blasts[skey].push({
        '--animation-second': '0.7s',
        '--translate-x': diffX + 'px',
        '--translate-y': diffY + 'px',
        '--rotate': ROTATE[axis].rotate
      })
      ・
      ・
      ・

そう、なぜかベタ書きです。
6回ぐらいぶち込んでるんだからループ使えよ!と自分でも思うのですが、
ループにすると何故か炎の間隔がすっごい空いて爆風っぽくなくなるのです。

まったくわかりません。
原理的には一緒のはずなんだけど。

突き止められたらご報告します。
不思議だ・・・。

アフィリエイト

これからはじめるVue.js実践入門

これからはじめるVue.js実践入門

  • 作者:山田 祥寛
  • 発売日: 2019/08/22
  • メディア: Kindle版