真ん中の円に動く円をぶつけて反射させる動きです。
反射ベクトルの求め方について勉強したノートをこちらに作りました。
反射ベクトルの求め方の勉強
function setup() {
createCanvas(400, 400);
//オブジェクトリテラルで静止円の属性を定義
seishiEn = {
x:width / 2,
y:height / 2,
r:40
};
//同じく動く円を定義
ugokuEn = {
x:100,
y:100,
r:20,
vx:5, //加速度
vy:4, //加速度
};
}
function draw() {
background(220);
//静止円を描く
fill(100, 200, 250);
noStroke();
ellipse(seishiEn.x, seishiEn.y, seishiEn.r * 2);
//動く円を描画
fill(250, 100, 100);
ellipse(ugokuEn.x, ugokuEn.y, ugokuEn.r * 2);
//位置の更新
ugokuEn.x += ugokuEn.vx;
ugokuEn.y += ugokuEn.vy;
//壁との反射
if (ugokuEn.x - ugokuEn.r <= 0 ||
ugokuEn.x + ugokuEn.r >= width) {
ugokuEn.vx *= -1;
}
if (ugokuEn.y - ugokuEn.r <= 0 ||
ugokuEn.y + ugokuEn.r >= height) {
ugokuEn.vy *= -1;
}
//衝突の検出
//現在の中心間の距離を求める
let dx = ugokuEn.x - seishiEn.x;
let dy = ugokuEn.y - seishiEn.y;
let distance = sqrt(dx * dx + dy * dy); //中心間の距離
//衝突時の中心間の距離
let hitDist = ugokuEn.r + seishiEn.r;
if (distance < hitDist) { //衝突したとき
//反射ベクトルを求める
//法線ベクトル
//normalize()でベクトルの長さを1として方向成分のみとする
let normalV = createVector(dx, dy).normalize();
//速度ベクトル
sokudoV = createVector(ugokuEn.vx, ugokuEn.vy);
//ベクトルの反射計算
//R = V - 2 (V・N) N
//VとNの内積(スカラー値)
let dotSeki = sokudoV.dot(normalV);
//反射ベクトルreflecV
let reflecV = p5.Vector.sub(sokudoV,p5.Vector.mult(normalV, 2 * dotSeki));
//新しい速度
ugokuEn.vx = reflecV.x;
ugokuEn.vy = reflecV.y;
//円がめり込まない位置に戻す
//めりこんだ距離
let overlap = hitDist - distance;
ugokuEn.x += normalV.x * overlap;
ugokuEn.y += normalV.y * overlap;
}
}