Kadenze_Session2_Vector / Forces
#01 : Newton's Laws of Motion_뉴턴의 운동법칙
- Force(힘) 은 질량을 지닌 물체를 가속하는 벡터 물리량이다.
- 제 1의 법칙 ( 관성의 법칙 )
- 날아가는 화살이 공기저항을 받지않는다면, 같은 방향으로 속도가 변하지 않고 계속 날아갈 수 있듯이, 정지하고 있는 물체는 항상 정지, 운동하는 물체는 항상 같은 속력과 방향으로 운동하려는 것.
- 힘이 없거나, 물체에 가해지는 힘이 서로 상쇄된다면 즉, 알짜 힘이 0이되면 물체의 속도는 일정하게 유지된다는 것을 ‘평형(epuilibrium)’ 이라고 함
*알짜힘은 물체에 가해지는 모든 힘들의 벡터(속력,방향)를 합하여 계산한 것.
- F = MA / 힘은 질량 곱하기 가속.
- A = F/M / 가속도는 힘과 비례하고, 질량에 반비례함.
즉, 세게 밀면 밀수록 더 빨리 움직이고, 질량이 크면 클수록 더 느리게 움직임.
지난시간에서 Vector를 배운 것에 따르면, 프로그래밍에서의 가속도는 객체의 움직임을 제어하는 핵심적인 요소다.
그렇다면, 프로그래밍에서 질량은 어떻게 표현할 수 있을까?
다니엘 쉬프만의 말에 따르면, 픽셀로 처리 할 수 있다고 한다.. 아직까지는 질량을 픽셀로 처리한다는 것이 이해는 되지않지만 어쨌든, 프로그래밍에서 모든 물체들의 질량을 1이라고 생각하면,
다음과 같은 식이 성립된다.
가속도는 힘과 같다는 것이다. 즉, 이 힘이라는 것이 모든 객체를 움직인다고 볼 수 있다.
#02 : Adding Forces
위에서 볼 수 있듯이, 가속도 = 힘이다.
이번에는 가장 간단하게 구현 할 수 있는 힘 중에 중력을 프로그래밍에서 구현하여, 마치 지구의 중력과 같이 객체가 중력의 영향을 받아 바닥으로 움직이게 해보자.
let ball; function setup() { createCanvas(400, 400); ball = new Ball(); } function draw() { background(51); let gravity = createVector(0, 0.1); ball.applyForce(gravity); ball.update(); ball.display(); } |
function Ball() { this.pos = createVector(width/2, height/2); this.vel = createVector(0, 0); this.acc = createVector(0, 0); this.applyForce = function(force) { this.acc = force; } this.update = function() { this.vel.add(this.acc); this.pos.add(this.vel); } this.display = function() { noStroke(); ellipse(this.pos.x, this.pos.y, 16, 16); } } |
- 질량은 고려하지 않았고, 중력 이외에 다른 힘의 작용은 없다.
- 소스코드에서는 new 생성자와 function 함수를 사용하여 클래스를 만들었는데, 이 방법과 클래스를 이용해 만드는 방법의 차이가 있는지 ? 효율성 ? 이 있는지 궁금함.
#03 : Force Accumulation_힘의 축적
this.chkEdge = function() { if(this.pos.y > height) { this.vel.y *= -1; this.pos.y = height; } } |
바운싱 하는 볼을 표현하는데 왜 위치, 속도, 가속도 중에 속도를 -1 곱하는가?
- 볼을 공처럼 튕기기 위해서는 힘이 가해진만큼, 같은 힘으로 튕겨져야 자연스러운 공의 운동을 표현할 수 있기 때문이다.
공이 바닥에 닿으면, 현재 속도 5.XX에 -1을 곱하여 -5.XX로 만든다.
그러면 코드에서는 매프레임마다, 중력이라는 힘이 계속 더해지고 있기 때문에, -5에서 0.1이라는 실수가 계속 더해지는 것을 볼 수 있다.
그렇다면, 이 부분에서의 중력이라는 힘은 물리적 현상이 아닌 것인가..?
현실세계의 물리를 구현하기 위해(그렇게 보이게 하기 위해), 계산한 것뿐인가?
update() { this.checkEdge(); // 영역인식. this.vel.add(this.acc); this.pos.add(this.vel); this.acc.set(0, 0); // 가속도 초기화. } |
- 가속도를 초기화 시키는 이유 : 초기화시키지 않으면 가속도가 계속 증가하며 축적되어, 공이 튕기는 의도를 구현하지 못함.
let wind = createVector(0.5, 0); let gravity = createVector(0, 0.1); ball.applyForce(gravity); ball.applyForce(wind); |
지금까지는 중력이라는 하나의 힘만 적용시켜봤다. 좀 더 현실적으로 만들기 위해, 다른 힘은 어떻게 넣을까? 두 가지 힘을 적용시키기 위해 위와 applyForce() 메소드를 두번 넣어보면, 이상하게도 중력 벡터는 무시하고 새로만든 wind 벡터만 실행된다.
왜 마지막 applyForce() 만 호출되고 이전 호출은 무시하고 실행되는가?
그렇다면, 두가지 힘을 함께 적용시키기 위해서는 어떻게 해야하는가?
- 찾아본바로 F = M*A를 정확하게 말하자면, 알짜 힘은 질량 곱하기 가속도와 같다.
- 알짜힘은 물체에 가해지는 모든 힘들의 벡터(속력,방향)를 합하여 계산한 것.
- 즉, 모든 힘들의 벡터를 더해야한다는 것이다.
this.applyForce = function(force) { //this.acc = force; this.acc.add(force); } |
두 가지 힘을 적용시키기 위해 가속도 벡터에 gravity 벡터와 wind 벡터의 합을 계산한다.
#04 : Adding Mass_질량 더하기
지금까지는 객체의 질량을 상관하지 않고 힘을 구현했다.
각 개별적인 객체에 질량을 더하자면,
위와 같이 가속도 벡터에 힘 / 질량을 해주어야한다.
예로 들자면, this.acc = (force/mass); 이다.
- 질량은 스칼라 값이다.
this.applyForce = function(force) { force.div(this.mass); this.acc.add(force); } |
힘을 나누는 메소드가 추가되었다. 하지만 여기서 문제가 있다. 중력이라는 힘은 매프레임마다 0.1씩 이동해야하지만, 힘은 나누어지는 메소드의 반환 값으로 영구적으로 바뀌기 때문에 물리를 구현하기에 문제가 발생한다. / 즉, 기존 힘 벡터에 영향을 주기 때문에 문제 발생.
이 같이 기존 힘 벡터에 영향을 주지 않는 방법은 객체를 복사하는 방법.
this.applyForce = function(force) { let f = force.copy(); f.div(this.mass); this.acc.add(f); } |
ellipse(this.pos.x, this.pos.y, this.mass*10, this.mass*10); |
질량을 시각화 시키기위해 객체의 부피를 질량 값으로 표현.
- 소스코드 예제
let ball, ball_2; function setup() { createCanvas(400, 400); ball = new Ball(300, height/2, 1); ball_2 = new Ball(100, height/2, 10); } function draw() { background(51); let wind = createVector(0.1, 0); let gravity1 = createVector(0, 0.2*ball.mass); ball.applyForce(gravity1); let gravity2 = createVector(0, 0.2*ball_2.mass); ball_2.applyForce(gravity2); if(mouseIsPressed) { ball.applyForce(wind); ball_2.applyForce(wind); } ball.chkEdge(); ball.update(); ball.display(); ball_2.chkEdge(); ball_2.update(); ball_2.display(); } |
function Ball(x, y, m) { this.pos = createVector(x, y); this.vel = createVector(0, 0); this.acc = createVector(0, 0); this.mass = m; this.applyForce = function(force) { let f = force.copy(); f.div(this.mass); this.acc.add(f); } this.chkEdge = function() { if(this.pos.y > height) { this.vel.y *= -1; this.pos.y = height; } if(this.pos.x > width) { this.vel.x *= -1; this.pos.x = width; }else if(this.pos.x < 0) { this.vel.x *= -1; this.pos.x = 0; } } this.update = function() { this.vel.add(this.acc); this.pos.add(this.vel); this.acc.set(0,0); } this.display = function() { noStroke(); ellipse(this.pos.x, this.pos.y, this.mass*10, this.mass*10); } } |
지금까지 객체에 힘을 구현했고, 질량의 값에 따른 힘도 구현했다.
하지만, 모든 객체를 선언하기에는 소스코드의 줄이 길어지기 때문에 코드의 가독성에 비효율적이다. 그래서, 다음 내용에서는 배열을 활용해 효율적으로 만들어 본다.
#05 : Arrays of Particles_배열로 만들기
let ball = []; function setup() { createCanvas(400, 400); for(let i=0; i<10; i++) { ball[i] = new Ball(random(width), height/2, random(0, 5)); } } function draw() { background(51); let wind = createVector(0.1, 0); for(let i=0; i<ball.length; i++) { let gravity = createVector(0, 0.2*ball[i].mass); ball[i].applyForce(gravity); if(mouseIsPressed) { ball[i].applyForce(wind); } ball[i].chkEdge(); ball[i].update(); ball[i].display(); } } |

let ball = []; function setup() { createCanvas(400, 400); for(let i=0; i<10; i++) { ball[i] = new Ball(random(width), height/2, random(0, 5)); } } function draw() { background(51); let wind = createVector(0.1, 0); for(let i=0; i<ball.length; i++) { let gravity = createVector(0, 0.2*ball[i].mass); ball[i].applyForce(gravity); if(mouseIsPressed) { ball[i].applyForce(wind); } ball[i].chkEdge(); ball[i].update(); ball[i].display(); } } |
function setup() { createCanvas(400, 400); } function mousePressed() { let b = new Ball(random(width), height/2, random(0, 5)); ball.push(b); } function keyPressed() { if(key == ' ') { ball.splice(0,1); } } |
- push(); 함수는 배열 시퀀스에 요소를 추가하는 기능.
- splice(); 함수는 배열 시퀀스의 가장 처음 생성된 요소부터 삭제하는 기능.
수업시간에 학습한 것 토대로 수정.
자바스크립트는 함수의 인자 값 타입에 민감하지 않음. 때문에 오류가 나지 않더라도, 타입을 잘 생각해서 작성하도록 ~
'Coding > P5.JS' 카테고리의 다른 글
< P5.JS > Particle system (0) | 2022.02.09 |
---|---|
< P5.JS > 중간창작 (0) | 2022.02.09 |
< P5.JS > The Nature of Code_Vector (0) | 2021.10.04 |
< P5.JS > 1. P5.JS의 OOP ( Object - Oriented Programming ) (0) | 2021.09.14 |
< P5.JS > 10 print_코드 분석으로 작동 원리 이해와 재해석 (0) | 2021.09.11 |