KAEDE Hack blog

JavaScript 中心に ライブラリなどの使い方を解説する技術ブログ。

JS ゲーム製作 p5.js 複数円の衝突を関数化する - 円を増やす準備

何をするか

p5.js

kei-s-lifehack.hatenablog.com

前回の記事で 2円の衝突判定の実装をやったが、関数化はされていなかったので、 ゲームを作るために必要な関数化を行う。

そのために以下の処理を行う

2円のオブジェクト化

円の描画

テキストの描画

2円のオブジェクトからの距離の計算

2円のオブジェクトからの衝突の是非の計算

を関数化していく

円をオブジェクト化する

変数でのベタ書き

最初はこうしていた。

  let x0 = 120;
  let y0 = 180;
  let r0 = 60;

  let x1 = mouseX;
  let y1 = mouseY;
  let r1 = 120;

固定座標の 円 0 と mouse の座標が同期される 円 1 の 座標と半径を変数で記述していた

オブジェクトにする

function draw() {
  const circleA = {
    x: 120,
    y: 180,
    r: 60,
  };
  const circleB = {
    x: mouseX,
    y: mouseY,
    r: 120,
  }
}

draw() の関数内にオブジェクトとして円を作る。

そうするとこれから書く距離の測定や衝突の判断に、円のオブジェクトを2つ指定するだけでよくなる。

なお draw() 関数外だと mouseX, mouseY が機能しない。

距離の取得

距離の取得の処理

  let distance = sqrt( (x1-x0)**2 + (y1-y0)**2 );
  let distanceComma2 = nfc(distance, 2);
  let distanceText = `Distance: ${distanceComma2}`;

まず、前回に2つの円から距離を取る処理を書いた

これを関数化する

距離の取得の関数化

function getDistance(circleObjectA, circleObjectB) {
  let x0 = circleObjectA.x;
  let y0 = circleObjectA.y;
  let x1 = circleObjectB.x;
  let y1 = circleObjectB.y;

  let distance = sqrt( (x1-x0)**2 + (y1-y0)**2 );
  let distanceComma2 = nfc(distance, 2);
  let distanceText = `Distance: ${distanceComma2}`;
  return distanceText;
}

これで 2円から距離を返す関数ができた。使ってみる

  const distanceOf0and1 = getDistance(circleA, circleB);
  console.log(distanceOf0and1);

  sketch.js:8 Distance: 246.45

ちゃんと計算されているのが確認できた。


円の表示

  circle(x0, y0, 2*r0)
  circle(x1, y1, 2*r1)

これで描画していたのを、円をオブジェクト化したので

function drawCircle(circleObject){
  circle(circleObject.x, circleObject.y, 2*circleObject.r)
}
  drawCircle(circleA)
  drawCircle(circleB)

こうなる

テキストの表示

関数化する前

  strokeWeight(1);
  stroke(0);
  textSize(32);
  text(distanceText, 3, 420);

その度にスタイルを記述した後に text() で書いてた

関数化する

スタイルを固定化して関数化する。

function displayText(message,fromLeft,fromTop){
  strokeWeight(1);
  stroke(0);
  textSize(32);
  text(message, fromLeft, fromTop);
}

先ほど getDistance() で取得したテキストを使って

  displayText(distanceOf0and1, 3, 420)

f:id:kei_s_lifehack:20210416080551p:plain

ちゃんと表示された。


衝突

ここまでで 円のオブジェクト化と描画系と距離の計算まで関数化したので

ようやく衝突処理もオブジェクト化できる

関数化する前

  let isHit = distanceOf0and1 < r0 + r1;

衝突判定は2つの円の距離より各円の半径の和が小さいかどうかで判定する。これを関数化したい

関数化後

function isHit(circleA, circleB) {
  let distance = getDistance(circleA, circleB);
  let isHit = distance < circleA.r + circleB.r;
  return isHit
}

  isHit(circleA, circleB)

これで円を増やしても実装できる!

kaede0902.github.io

実際に動いているコードはこちら

github.com

ブランチはこちら。Pull Request あったらください