주요 내용
컴퓨터 프로그래밍
코스: 컴퓨터 프로그래밍 > 단원 5
단원 6: 각운동각 속도
기억하고 있나요?
위치 = 위치 + 속도
속도 = 속도 + 가속도
속도 = 속도 + 가속도
지난 두 단원에서 열심히 배운 내용이었죠? 똑같은 논리를 물체의 회전운동에 적용할 수 있습니다.
각 = 각 + 각속도
각속도 = 각속도 + 각가속도
각속도 = 각속도 + 각가속도
사실 위 내용은 생각보다 더 간단합니다. 왜냐하면 각은 벡터가 아닌 스칼라이기 때문입니다!
이전 응용문제의 답을 이용하여 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를 적용합니다.