If you're seeing this message, it means we're having trouble loading external resources on our website.

웹 필터가 올바르게 작동하지 않으면 도메인 *. kastatic.org*.kasandbox.org이 차단되어 있는지 확인하세요.

주요 내용

상호 인력

처음에 한 물체가 다른 물체를 끌어당기는 간단한 프로그램에서 시작해 한 물체가 다른 여러 물체를 끌어당기는조금 더 복잡한 프로그램으로 점차 난이도를 올려 여기까지 왔습니다. 이제는 여러 물체가 서로 끌어당기는_ 조금 더 복잡한 프로그램을 짜야 합니다. 시스템 내부의 모든 물체가 자기 자신을 제외한 다른 모든 물체를 끌어당기는 상황을 구현해야 합니다.
사실 필요한 것들은 이미 거의 만들어 놓았습니다. Mover 객체의 배열을 만들었던 프로그램을 생각해봅시다:
var movers = [];

for (var i = 0; i < 5; i++) {
    movers[i] = new Mover(
        random(0.1, 2),
        random(width),
        random(height));
}

draw = function() {
    background(255, 255, 255);
    for (var i = 0; i < movers.length; i++) {
        movers[i].update();
        movers[i].display();
    }
};
여기서 draw() 함수만 바꿔주면 모든 것이 끝납니다. 현재 위 프로그램은 모든 Mover i에 대해 update와 display를 사용하도록 짜여있습니다. 이제 이 코드를 모든 Mover i가 대해 다른 모든 Mover j를 끌어당기면서 update와 display를 호출하도록 바꿔주면 됩니다.
for (var i = 0; i < movers.length; i++) {
    // 모든 mover에 대해 다음을 계산
    for (var j = 0; j < movers.length; j++) {
        var force = movers[j].calculateAttraction(movers[i]);
        movers[i].applyForce(force);
    }
}

for (var i = 0; i < movers.length; i++) {
    movers[i].update();
    movers[i].display();
}
기존의 update와 display를 불렀던 for문 위에 새로운 반복문을 만들었습니다. 각 Mover에 update를 부르기 전에 모든 인력을 계산해 놓기 위함입니다. 만약 첫 번째 for문 전에 Mover를 업데이트한다면 그것은 그다음에 할 인력의 계산에 영향을 주기 때문에 맞지 않습니다.
아직 Mover에게 사용할 calculateAttraction() 메소드가 정해지지 않아 코드가 작동하지 않습니다. 이전 예제에서는 Attractor 객체의 calculateAttraction() 메소드를 다뤘습니다. 이제 Mover가 다른 Mover를 끌어당기므로 이 메소드를 복사해서 Mover 객체로 옮겨줍시다.
Mover.prototype.calculateAttraction = function(m) {
  var force = PVector.sub(this.position, m.position);
  var distance = force.mag();
  distance = constrain(distance, 5.0, 25.0);                        
  force.normalize();

  var strength = (G * this.mass * m.mass) / (distance * distance);
  force.mult(strength);
  return force;
};
모두가 예상하다시피, 여기에는 작은 문제가 하나 있습니다. 모든 Mover i와 Mover j에 대해 i 가 j 일 경우는 괜찮을까요? 예를 들어, 3번 Mover가 3번 Mover를 끌어당길 수 있나요? 물론 이런 일은 일어날 수 없습니다. 물체가 5 개 있다면 3번 Mover는 자기 자신을 제외한 0, 1, 2, 4 번 Mover를 끌어당겨야 합니다. 그렇지만 3번과 1번 Mover 간의 힘과 반대로 1번과 3번 Mover 간의 모든 힘을 계산하고 적용해야 할 필요는 있습니다. 이렇게 계산한 힘은 같지만, 이에 따른 가속도는 각 물체의 질량에 따라 달라질 것입니다. 아래 나와있는 표를 살펴봅시다:
0 ⇢ 1, 2, 3, 4
1 ⇢ 0, 2, 3, 4
2 ⇢ 0, 1, 3, 4
3 ⇢ 0, 1, 2, 4
따라서, for문을 수정하여 내부의 반복문으로 스스로 끌어당기는 Mover를 피하도록 만들고 예제를 마무리합니다.
for (var i = 0; i < movers.length; i++) {
    for (var j = 0; j < movers.length; j++) {
       if (i !== j) {
         var force = movers[j].calculateAttraction(movers[i]);
         movers[i].applyForce(force);
       }
    }
}
지금까지 만든 코드는 다음과 같습니다:

본 "내추럴 시뮬레이션" 과정은 다니엘 쉬프만(Daniel Shiffman)이 저술한 "The Nature of Code"의 내용을 차용한 것이며, 본 내용물의 저작권은 Creative Commons Attribution-NonCommercial 3.0 Unported License를 적용합니다.