Silverback9

#야생으로

Creative Coding 독학 제170일 2024년09월13일(금)

오늘은 물체를 여러 개 만들어서 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~~!!!

오늘도 즐거운 아침! 보내시고요~~^^*

한가위 보름달님에게 무슨 소원을 빌어볼까~~^^* 행복한 고민도 곁들인 점심도 맛있게 드시고요~^^*

내일 또 만나서 우리 코딩 공부 할까요~~^^*

네~~!!! 꿈은 이루어 집니다~~!!!

댓글 남기기