LIGのメルマガ、はじめました!
LIGのメルマガ、はじめました!

【canvas初学者必見】マウスカーソルを避けていくパーティクルアニメーションを作ろう!

ぜんちゃん

こんにちは、フロントエンドエンジニアのぜんちゃんです。

そろそろ夏ですね。夏といえばスイカ割り。

もしくは、canvasですね。

秋になる前にcanvasについての記事をもう一つ出してみることにしました。

前回の記事

前回の記事は見てくださりましたか?

前回は、canvasで左から右に円が流れるパーティクルアニメーションを作りました。

うーんでも何か足りない……。

 

もっと表現力を!!

 

前回みたいなグラフィック表現もいいけど、ユーザの操作によって、変化が加わるような表現をしたい!

というわけで今回は、前回作成したパーティクルアニメーションにユーザのアクションによる変化を追加してみようと思います!

今回作るもの

マウスカーソルを軽やかに避けていってますね……!!

作り方

canvasでパーティクルを作る基本的な方法は、前回の記事で説明しました。

update() {
  this.x += this.directionX;
  if(this.x > canvas.width + this.radius) {
    this.x = -this.radius;
  }  
  this.render();
}

基本的なパーティクルでは、上記のように「丸の位置を少しずつ動かす」という処理をしています。

今回は、ここのupdateの処理の中で計算をします。

マウスの位置取得

まず、マウスの位置を取得する必要があります。そのためにmousemoveイベントを登録し、マウスカーソルの位置を変数に入れておくようにします。

const mouse = {
  x: null,
  y: null
}

window.addEventListener('mousemove', (event) => {
  mouse.x = event.x;
  mouse.y = event.y;
});

衝突検知の計算

ある一つのパーティクルが、カーソルに近づいているか(衝突とみなされる距離に位置しているか)どうかは、衝突検出における円形衝突の式をもとに求めることができます。

今回は衝突検知を行うことで、カーソルとパーティクルが衝突しているかを判断し、衝突していれば何かしらのアクションを行うように処理します。

参考サイト
https://developer.mozilla.org/ja/docs/Games/Techniques/2D_collision_detection#%E5%86%86%E5%BD%A2%E8%A1%9D%E7%AA%81

衝突検知の円形衝突を簡単に説明すると、「二つの円の中心座標の距離と、二つの円の半径の和を比較することで衝突しているかを調べることができる」ということです!

この計算方法を使って衝突検知のロジックを書くと、このような記述になります。

detectCollision () {
  // 衝突しているかどうか
  const dx = mouse.x - this.x;
  const dy = mouse.y - this.y;
  const distance = Math.sqrt(dx * dx + dy * dy);
  return distance < mouse.radius + this.radius;
}

これで衝突を検知することができるようになりました!

円を逆方向に動かす

衝突検知ができるようになったので、次は衝突を検知したら円を逆方向に動かすようにしてみます。

// もし衝突していたらカーソルから離れるようにする
if (this.detectCollision()) {
  if (this.x > mouse.x) {
    this.x += this.radius;
    if (this.directionX < 0) this.directionX = -this.directionX;
  }
  if (this.x < mouse.x) {
    this.x -= this.radius;
    if (this.directionX > 0) this.directionX = -this.directionX;
  }
  if (this.y > mouse.y) {
    this.y += this.radius;
    if (this.y < 0) this.directionY = -this.directionY;
  }
  if (this.y < mouse.y) {
    this.y -= this.radius;
    if (this.y > 0) this.directionY = -this.directionY;
  }  
}

これで完成です!

おまけ

先ほど実装した衝突検知のロジックを使って、マウスカーソルのHoverで円が流れるスピードを早くしてみたり……

マウスカーソルのHoverで円のサイズを大きくしてみたり……

いろいろな表現ができて面白いですね(^_^)

まとめ

前回canvasで作成したパーティクルアニメーションに、衝突検知の計算を使ってマウス連動するアニメーションを作成しました。次は、さらになめらかに動かす方法やまた違った表現方法を探ってみたいと思います!

それではまた! ぜんちゃんでした〜

M o n g o