오늘은 물체를 여러 개 만들어서 2 Dimensional Elastic Collision 2차원 탄성 충돌을 표현해 보려고 합니다~~^^* YEAH~~^^*
음….여러 개의 입자들 각각이 다른 입자들과 충돌하는 것을 스스로 감지하고 이에 따라 자신도 상대방도 2차원 탄성 충돌을 일으키도록 하는 함수 collide(other)에 주목할 필요가 있을 것 같아요….
음….
아, 네…
음, 그렇죠….
네, 그런 것 같아요….
자신의 행동 뿐만 아니라 상대의 행동도 함수 collide()에서 명령하게 되니까요…
//###슬기로운 나와 너의 충돌 생활###//
//###other인 너의 행동도 this인 내가 딱! 정해 줄게!###//
collide(other) {
let impactVector = p5.Vector.sub(other.position, this.position);
let d = impactVector.mag();
if (d < this.r + other.r) {
let overlap = d - (this.r + other.r);
let dir = impactVector.copy();
dir.setMag(overlap * 0.5);
this.position.add(dir);
other.position.sub(dir);
d = this.r + other.r;
impactVector.setMag(d);
let mSum = this.mass + other.mass;
let vDiff = p5.Vector.sub(other.velocity, this.velocity);
let num = vDiff.dot(impactVector);
let den = mSum * d * d;
let deltaVA = impactVector.copy();
deltaVA.mult(2 * other.mass * num / den);
this.velocity.add(deltaVA);
// 이 충돌 후 내가 나아가야 할 바!
let deltaVB = impactVector.copy();
deltaVB.mult(-2 * this.mass * num / den);
other.velocity.add(deltaVB);
// 이 충돌에 후 네가 나아가야 할 바!
}
}
무한 반복 함수 draw()가 모든 입자들의 충돌 감지와 충돌 후 행동을 처리하는 1회 째의 시간 t1 안에서
물체 A가 this이고 물체 B가 other였던 상황이 한 번 있으면, 물체 B가 this가 되는 차례에서는 물체 A를 other로 고려할 필요가 없는 것 같아요. 왜냐하면, 물체 B와 물체 A의 충돌은, 물체 A가 이미 탐지하고 충돌 후의 A와 B의 행동을 이미 명령했었기 때문에요…
함수 draw()가 다시 반복되는 2회 째의 시간 t2 안에서는, 다시 물체 A부터… t1에서 했던 충돌점검과 자신 및 상대의 행동 명령을 물체의 순서대로 주욱 하게 되겠네요…
정리해 보면…자신의 순번 앞의 물체와의 충돌 점검과 충돌 후 서로의 행동 명령을 할 필요는 없는 것 같아요. 자신의 순번 앞의 물체가 이미 그 일을 해 놓았기 때문에요…
네… 함수 collide()는 자신의 행동 뿐만 아니라 충돌 상대의 행동도 명령하고 있다는 것에 주의를 하면, 모든 물체들이 다른 물체와의 충돌을 점검하는 방식을 결정할 수 있을 것 같네요.
즉, “나보다 순번이 빠른 물체와의 충돌은 고려하지 않아도 돼~~^^* 그 아이가 이미 고려해서 그 아이 자신의 행동 뿐만 아니라 나의 행동에 대해서도 명령을 내렸었으니까~~^^*”가 될 것 같아요!
그래서, “나보다 순번이 늦는 물체와의 충돌 만을 점검하고 서로의 행동을 명령하자~~!!“가 되는 것 같군요!

네~~^^* 그럼 물체 this의 충돌 점검 및 충돌 후 행동 명령 고려 대상인 other를 코드로 표현해 볼까요~~^^*
let particles =[];
//입자 배열 particles[]는 첫 구성요소 particles[0] 부터 마지막 구성요소 particles[particles.length -1] 까지로 이루어 집니다.
for (let i = 0; i < particles.length; i++) {
let particleA = particles[i];
for ( let j = i + 1; j < particles.length; j++) {
let particleB = particles[j];
particleA.collice(particleB);
}
}
//j = i + 1 : particleA보다 순번이 늦는 입자만이 particleB가 될 수 있습니다!
//j < particles.length :
//만약 i가 <particles.length - 1>이라면
//다시 말해서, i가 배열 입자의 마지막 구성요소를 가리키고 있다면
//j = i+1이라서, j = particles.length가 되고
//이것은 j < particles.length 조건을 만족시키지 못하기 때문에
//for ( let j = i + 1; j < particles.length, j++) {} loop를 벗어나게 됩니다.
//즉, i가 배열의 마지막 구성요소 일 경우는, j가 생성되지 않아, 아무 일도 일어나지 않고 j 관련 for loop가 끝납니다.
//i 관련 for loop는 아직 끝나지 않아서, i는 1 증가되어
// i = particles.length가 되는데, 이것은!!!
// i < particles.length 조건을 만족시키지 못하기 때문에
// for (let i = 0; i < particles.length; i++) {} loop도 벗어나게 됩니다.
// 즉, 아무런 일이 일어나지 않고 이중 for 구문이 완전히 끝나게 됩니다.
//다시 말해서, i가 배열의 마지막 구성요소가 되면, 아무런 할 일이 없으므로, 쉬면 되요~~^^* 푸근~히 쉬~세~요~~^^*
네~~^^*
this와 other의 관계성도 코드로 만들었으니, 이제 여러 개의 입자들이 2차원 탄성 충돌을 하는 모습을 표현하는 프로그램의 전체 코드를 완성해 볼까요~~^^* 렛츠 고우~~^^*
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.2/p5.min.js"></script>
<meta charset="utf-8" />
<title>NOC_4_06_ParticlesSystemForces</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<script src="particle.js"></script>
<script src="sketch.js"></script>
</body>
</html>
class Particle {
constructor(x, y) {
this.position = createVector(x, y);
this.velocity = p5.Vector.random2D();
this.velocity.mult(random(2, 6));
this.acceleration = createVector(0, 0);
this.mass = random(2, 6);
this.r = sqrt(this.mass) * 10;
//입자 크기를 좀 줄여 보겠습니다~~^^*
}
applyForce(force) {
let f = force.copy();
f.div(this.mass);
this.acceleration.add(f);
}
update() {
this.velocity.add(this.acceleration);
this.position.add(this.velocity);
this.acceleration.mult(0);
}
collide(other) {
let impactVector = p5.Vector.sub(other.position, this.position);
let d = impactVector.mag();
if (d < this.r + other.r) {
let overlap = d - (this.r + other.r);
let dir = impactVector.copy();
dir.setMag(overlap * 0.5);
this.position.add(dir);
other.position.sub(dir);
d = this.r + other.r;
impactVector.setMag(d);
let mSum = this.mass + other.mass;
let vDiff = p5.Vector.sub(other.velocity, this.velocity);
let num = vDiff.dot(impactVector);
let den = mSum * d * d;
let deltaVA = impactVector.copy();
deltaVA.mult(2 * other.mass * num / den);
this.velocity.add(deltaVA);
let deltaVB = impactVector.copy();
deltaVB.mult(-2 * this.mass * num / den);
other.velocity.add(deltaVB);
}
}
edges() {
if (this.position.x > width - this.r) {
this.position.x = width - this.r;
this.velocity.x *= -1;
} else if (this.position.x < this.r) {
this.position.x = this.r;
this.velocity.x *= -1;
}
if (this.position.y > height - this.r) {
this.position.y = height - this.r;
this.velocity.y *= -1;
} else if (this.position.y < this.r) {
this.position.y = this.r;
this.velocity.y *= -1;
}
}
show() {
stroke(0);
strokeWeight(2);
fill(127, 255, 255);
//추석날 하늘이 참 맑으면 좋겠어요~!!
circle(this.position.x, this.position.y, this.r * 2);
}
}
let particles = [];
function setup() {
createCanvas(400, 400);
for ( let i = 0; i < 10; i++) {
let x = random(width);
let y = random(height);
particles.push(new Particle(x,y));
}
}
function draw() {
background(255);
for (let i = 0; i < particles.length; i++) {
let particleA = particles[i];
for ( let j = i + 1; j < particles.length; j++) {
let particleB = particles[j];
particleA.collide(particleB);
}
}
for (let particle of particles){
particle.update();
particle.edges();
particle.show();
}
}
아 네! 10 개의 입자가 2 Dimensional Elastic Collision 2차원 탄성 충돌을 하는 모습을 우리 보러 같이 갈까요~~^^* Let’s go~~^^*
오 재밌는데요~~^^* 우리 입자를 넉넉히 한 50개 만들어 볼까요~~^^* 크기는 좀더 줄이구요~~? 음~~색깔도 예쁜 단풍잎색으로 해 볼까요~~^^*
하늘은 파랗고 단풍잎은 울긋불긋한 가을이 왔습니다~^^* 추석이 다가오고 있네요~~^^*
즐겁고 행복한 일과 맛있고 영양 많은 먹거리가 우리들의 입자 갯수만큼 풍성한 한가위가 다가오고 있네요~~^^*
오늘도 저와 함께 예쁜 입자들이 예쁘게 서로 충돌하는 모습을 표현해 주셔서 감사합니다~~^^*
2차원 탄성 충돌 코드 공부가 마무리 되었네요~~!!! YEAH~~!!!
오늘도 즐거운 아침! 보내시고요~~^^*
한가위 보름달님에게 무슨 소원을 빌어볼까~~^^* 행복한 고민도 곁들인 점심도 맛있게 드시고요~^^*
내일 또 만나서 우리 코딩 공부 할까요~~^^*
네~~!!! 꿈은 이루어 집니다~~!!!
댓글 남기기