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

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

주요 내용

각 속도

기억하고 있나요?
위치 = 위치 + 속도
속도 = 속도 + 가속도
지난 두 단원에서 열심히 배운 내용이었죠? 똑같은 논리를 물체의 회전운동에 적용할 수 있습니다.
각 = 각 + 각속도
각속도 = 각속도 + 각가속도
사실 위 내용은 생각보다 더 간단합니다. 왜냐하면 각은 벡터가 아닌 스칼라이기 때문입니다!
이전 응용문제의 답을 이용하여 ProcessingJS에서 일정한 각만큼 막대기를 회전하려면 다음과 같이 코딩할 수 있습니다:
translate(width/2, height/2);
rotate(angle);
line(-50, 0, 50, 0);
ellipse(50, 0, 8, 8);
ellipse(-50, 0, 8, 8);
여기에 운동 법칙을 추가하면 아래와 같은 프로그램이 나옵니다. 막대는 화면에서 출력된 직후 정지한 상태에서 시작해 각이 일정한 각가속도로 회전하면서 점점 더 빠르게 돕니다.
이 개념을 Mover 객체에 적용할 수 있습니다. 예를 들어, 각운동과 관련된 프로퍼티를 Mover 생성자에 추가할 수 있습니다.
var Mover = function(m, x, y) {
    this.position = new PVector(x, y);
    this.mass = m;

    this.angle = 0;
    this.aVelocity = 0;
    this.aAcceleration = 0;

    this.velocity = new PVector(random(-1, 1), random(-1, 1));
    this.acceleration = new PVector(0, 0);
};
이러면 update()에서 동일한 알고리즘에 따라 위치와 각을 갱신합니다!
Mover.prototype.update = function () {

    this.velocity.add(this.acceleration);
    this.position.add(this.velocity);

    this.aVelocity += this.aAcceleration;
    this.angle += this.aVelocity;

    this.acceleration.mult(0);
};
물론 객체를 화면에 표시할 때 회전시킬 필요도 있습니다.
Mover.prototype.display = function () {
    stroke(0, 0, 0);
    fill(175, 175, 175, 200);
    rectMode(CENTER);

    // 회전이 나머지 환경에 영향을 미치지 않도록 하기 위해 
    // pushMatrix와 popMatrix가 필요합니다.'
    pushMatrix();
    // 도형의 위치에 원점을 설정합니다.'
    translate(this.location.x, this.location.y);
    // 각에 따라 회전시킵니다.
    rotate(this.angle);
    rect(0, 0, this.mass*16, this.mass*16);
    popMatrix();
};
이제 실제로 위 코드를 실행해보니 전혀 새로운 기능을 볼 수 없습니다. 이는 각가속도(this.aAcceleration = 0;)가 0으로 초기화되기 때문입니다. 객체가 회전하려면 가속도를 받아야 합니다! 물론, 다른 수에 하드 코딩할 수도 있습니다:
this.aAcceleration = 0.01;
위 논리를 따라 구심력을 기반으로 계산되는 힘을 추가하면 프로그램은 다음과 같이 작동합니다:
시작이 좋아 보이지만 주변 환경에서 작용하는 힘에 따라 각 가속도를 다양하게 할당하면 좀 더 재미있는 결과가 나올 수 있습니다. 보통 물체는 자기 스스로 회전하지는 않기 때문입니다! 이제 토크관성모멘트 개념을 적용해서 각가속도를 좀 더 깊게 모델링 할 수도 있습니다. 이런 수준의 모델링은 이 과정의 범위 밖입니다. 하지만 지금부터 배우는 개념도 조금 복잡해질 겁니다.
지금은 별로 간결하지 않고 빨리 만들 수 있는 코드로도 충분합니다. 단순히 각가속도를 객체의 가속도 벡터의 함수로 나타내서 계산하면 괜찮은 결과를 얻을 수 있습니다. 다음은 이를 적용한 예제입니다:
this.aAcceleration = this.acceleration.x;
제멋대로 정해서 만든 것처럼 보이네요. 하지만 이렇게 해도 충분히 작동합니다. 객체가 오른쪽으로 가속하면 각가속도는 시계 방향으로 작용합니다. 왼쪽으로 가속하면 각가속도는 반시계방향으로 작용합니다. 물론 이 경우 크기를 생각하는 것이 중요합니다.’ 가속도 벡터의 x 성분은 너무 값이 커서 객체가 말도 안 되게 빠른 속도로 회전하게 만들 수 있습니다. 따라서 x 값을 어떤 값으로 나누거나 각속도를 합리적인 범위로 제한하는 것이 실질적으로 도움이 됩니다. 다음은 이런 식으로 변경한 update() 메소드를 구성하는 모든 코드입니다.
Mover.prototype.update = function () {
    this.velocity.add(this.acceleration);
    this.position.add(this.velocity);

    // 수평 가속도를 기반으로 각가속도를 계산합니다.'
    //  값을 나누기해서 너무 커지지 않게 합니다.
    this.aAcceleration = this.acceleration.x / 10.0;
    this.aVelocity += this.aAcceleration;

    // 속도가 지나치게 빠르게 회전하지 않도록 제한합니다.'
    this.aVelocity = constrain(this.aVelocity, -0.1, 0.1);
    this.angle += this.aVelocity;

    this.acceleration.mult(0);
};
다음은 모든 변경 사항을 추가한 프로그램입니다.

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