静止した円を上方に整列させ、下方からの動く円がぶつかったら消える
動く円は反射ベクトルに従って跳ね返る
簡易なブロック崩しがもうすぐできそうです。
const NUM_BLOCKS = 8;
const BLOCK_ROW = 4;
const BLOCK_RADIUS = 20;
const MOVING_RADIUS = 10;
let blocks =[];
let movingBall;
function setup() {
createCanvas(400, 400);
noStroke();
//オブジェクトリテラルで静止円の属性を定義し
//配列に入れる
for (let i = 0; i < NUM_BLOCKS; i++) {
const x = (width / (BLOCK_ROW + 1)) * ((i % BLOCK_ROW) + 1);
const y = i < BLOCK_ROW ? 80 : 160;
blocks.push({
pos: createVector(x, y),
r: BLOCK_RADIUS,
visible: true,
})
}
//同じく動く円を定義
movingBall = {
pos:createVector(width / 2, 350),
r:MOVING_RADIUS,
velocity: createVector(5, 3),
};
}
function draw() {
background(220);
//静止円を描く
fill(100, 200, 250);
for (const block of blocks) {
if (block.visible) {
circle(block.pos.x, block.pos.y, block.r * 2);
}
}
//動く円を描画
fill(250, 100, 100);
circle(movingBall.pos.x, movingBall.pos.y, movingBall.r * 2);
//位置の更新
movingBall.pos.add(movingBall.velocity);
//壁との反射
if (movingBall.pos.x < movingBall.r ||
movingBall.pos.x > width - movingBall.r) {
movingBall.velocity.x *= -1;
}
if (movingBall.pos.y < movingBall.r ||
movingBall.pos.y > height - movingBall.r) {
movingBall.velocity.y *= -1;
}
for (const block of blocks) {
if (!block.visible) continue;
//衝突の検出
//現在の中心間の距離を求める
const distance = p5.Vector.dist(movingBall.pos, block.pos);
if (distance < movingBall.r + block.r) { //衝突したとき
block.visible = false;
//反射ベクトルを求める
//法線ベクトル
//normalize()でベクトルの長さを1として方向成分のみとする
const normalV = p5.Vector.sub(movingBall.pos, block.pos).normalize();
//VとNの内積(スカラー値)
const dotM = movingBall.velocity.dot(normalV);
//ベクトルの反射計算
//R = V - 2 (V・N) N
//反射ベクトルreflecV
const reflecV = p5.Vector.sub(
movingBall.velocity,
p5.Vector.mult(normalV, 2 * dotM)
);
//新しい速度
movingBall.velocity = reflecV;
}
}
}