본문 바로가기
p5.js

[p5.js] 5. Vector, Vector math

by 쿠킷리스트 2021. 10. 2.

학습내용(Random Walk)

#1 : Bouncing ball with no vectors(백터 없이 튕기는 공)
#2 : Vector 연산 add를 사용해 코드 간략하게 만들기
#3 : Vector 연산 subtract(sub)를 사용해보기
#4 : Vector 연산 multiplication(mult), division(div)를 사용해보기
#5 : Vector 연산 magnitude(mag)를 사용해보기
#6 : Vector 연산 normalize 사용해보기

#1 : Bouncing ball with no vectors

//기본 예제
let x = 100;
let y = 100;
let xspeed = 1;
let yspeed = 3.3;

function setup() {
  createCanvas(400, 200);
  background(220);

}

function draw() {
  background(220);
  stroke(0);
  fill(175);
  ellipse(x,y,32,32)
  
  x = x + xspeed;
  y = y + yspeed;
  
  if((x > width)||(x<0)){
    xspeed = xspeed*-1
  }
  if((y > height)||(y<0)){
    yspeed = yspeed*-1
  }
}
//클래스를 활용하기
let ball;

function setup() {
  createCanvas(400, 200);
  background(220);
  ball = new Myball();

}

function draw() {
  background(220);
  ball.move();
  ball.display();
}

class Myball{
  constructor(){
    this.x = 100;
    this.y = 100;
    this.xspeed = 1;
    this.yspeed = 3.3;
  }
  move(){
    this.x = this.x + this.xspeed;
    this.y = this.y + this.yspeed;
    
      if((this.x > width)||(this.x<0)){
      this.xspeed = this.xspeed*-1
    }
      if((this.y > height)||(this.y<0)){
      this.yspeed = this.yspeed*-1
    } 
  }
  display(){
    ellipse(this.x,this.y,32,32);
    fill(175);
    stroke(0);
  }
}

 기본 예제를 바탕으로 class를 활용하는 방식으로 코드를 바꿔보았다(출력되는 결과는 동일). setup()과 draw() 부분은 간결해졌으나 코드 전체를 보면 class ball과 this.가 추가되면서 더 복잡해진듯 한 느낌이다. Vector를 사용하면 훨씬 간결해지지 않을까? 자바스크립트에서 and는 &&, or은 ||로 쓴다.

  • 변수 ball을 먼저 선언해주었고, new 함수를 통해 Myball을 만들었다.
  • contructor()를 통해 Myball의 속성을 입력해주었다.
  • move(), display()를 움직임과 공의 모습을 만들어 주었다.
  • function draw();로 올라가 ball.move();, ball.display();를 추가했다.

#2 : Vector와 Vector 연산을 사용해 코드 간략하게 만들기

let position;
let velocity;

function setup(){
  createCanvas(600,200);
  background(220);
  position = new createVector(100,100);
  velocity = new createVector(1,3.3);
}

function draw(){
  background(220);
  
  position.add(velocity);
  
    if ((position.x > width) || (position.x < 0)) {
    velocity.x = velocity.x * -1;
  }
    if ((position.y > height) || (position.y < 0)) {
    velocity.y = velocity.y * -1;
  }
  
  stroke(0);
  fill(175);
  ellipse(position.x,position.y,32,32);
}

 Vector와 Vector 연산 add()를 사용해서 더욱 간략하게 코드를 만들었다...고 생각했는데 그리 간략해지지는 않았다. 하지만 여러 개의 값을 코드 한줄에 넣을 수 있다는 점이 상당히 유용해 보인다.

  • position과 velocity를 선언했고 new createVector를 사용해 vector값을 만들었다.
  • vector 연산 .add()를 사용해 값을 vector 값을 더해주었다.
  • 기존에 this.를 모두 position.과 velocity.으로 수정해주었다.

 더 복잡한 계산과, 여러개의 오브젝트를 만든다면 효과적일 것 같다. 3d 환경에서는 z값까지 계산해야 할텐데 그때는 Vector가 훨씬 더 유용해지지 않을까?

 The nature of Code에는 Processing 기반으로 코드가 작성되어 있다보니 이걸 다시 p5.js용으로 바꾸는게 쉽지가 않다. Github에 올라와있는 p5.js용 코드를 참고하면서 공부하고 있다. 

 

#3 : Vector 연산 subtract를 사용해보기

function setup() {
  createCanvas(640,360);
}

function draw() {
  background(51);

  let mouse = createVector(mouseX,mouseY);
  let center = createVector(width/2,height/2);
  mouse.sub(center);

  translate(width/2,height/2);
  strokeWeight(2);
  stroke(255);
  line(0,0,mouse.x,mouse.y);
}

 이번 sub 예제를 보면서 이해가 되지 않던 부분이 translate()이다. reference에서 봤을 때는 이전 translate값에 다음에 translate 값이 더해지는 것 같은데, 예제 코드에서는 어떻게 사용되는 건 지 감이 잡히지 않는다. translate값도 바꿔보고, line 값도 변경해보니 예제에서 translate는 선을 뻗는 중심 설정하는 것 같다. 그래도 이해가 잘 안돼서 혼자서 코드를 작성해봤는데 결과가 똑같이 나온다.

function setup() {
  createCanvas(640, 360);
}

function draw() {
  background(51);
    let mouse = createVector(mouseX,mouseY);
    strokeWeight(2);
  stroke(255);
  line(width/2,height/2,mouse.x,mouse.y);
}
  • 선의 출발점(중심)을 line()에서 잡아 줬다.
  • translate나 vector 연산 등이 필요가 없었는데, 단지 설명하기 위해 위와 같이 코드를 짠걸까?

#4 : Vector 연산 multiplication(mult), division(div)를 사용해보기

 vector에서 크기를 두배 키우거나 1/3로 줄이고 싶을 때는 vector에 2를 곱하거나, vector에 1/3을 곱해야한다. 다른 vector를 곱하는 게 아니라 숫자를 곱한다.

function setup() {
  createCanvas(640,360);
}

function draw() {
  background(51);

  let mouse = createVector(mouseX,mouseY);
  let center = createVector(width/2,height/2);
  mouse.sub(center);
  mouse.mult(0.5)

  translate(width/2,height/2);
  strokeWeight(2);
  stroke(255);
  line(0,0,mouse.x,mouse.y);
}
  • mult를 통해 mouse의 x,y 값을 1/2 줄인만큼, 마우스와 좌표(320, 180)의 거리 반만큼 선이 생긴다.
  • 이번에는 위 sub 예제처럼 translate을 빼면 똑바로 동작하지가 않는다. translate를 어떻게, 왜 쓰는걸까?
  • division(div)도 원리가 똑같다. 1/2 줄이고 싶다면 div(2)를 사용.

#5 : Vector 연산 magnitude(mag)를 사용해보기

 Vecort에서 magnitude는 점과 점이 이동한 거리를 나타낸다. the natrue of code 설명을 보면 피타고라스의 정리와 함께 설명해준다. 

function setup() {
  createCanvas(640,360);
}

function draw() {
  background(51);

  let mouse = createVector(mouseX,mouseY);
  let center = createVector(width/2,height/2);
  mouse.sub(center);

  let m = mouse.mag();
  fill(255);
  stroke(0);
  rect(0,0,m,10);
  text('vector mag : '+ mouse.mag().toFixed(0), 2, 20)

  translate(width/2,height/2);
  strokeWeight(2);
  stroke(255);
  line(0,0,mouse.x,mouse.y);
}
  • 내가 이해한 것이 맞나 싶어서 예제에 text를 추가해 magnitude 값이 숫자로 나오게 해보았다.

#6 : Vector 연산 normalize 사용해보기

 Vector normalize는 vector의 magnitude를 1로 바꾸어 unit vector(단위 백터)로 만드는 것. vector를 정규화? 시킨다.

function setup() {
  createCanvas(640,360);
}

function draw() {
  background(51);

  let mouse = createVector(mouseX,mouseY);
  let center = createVector(width/2,height/2);
  mouse.sub(center);
  mouse.normalize();
  mouse.mult(100);

  translate(width/2,height/2);
  // Draw the resulting vector
  stroke(255);
  strokeWeight(2);
  line(0,0,mouse.x,mouse.y);
}
  • mouse.normalize();로 magnitude를 1로 만든 후 100을 곱해서 magnitude 값을 100으로 고정시켰다.
  • 따라서, 마우스가 어디를 가리키던 선의 길이는 100으로 고정.

느낀 점

 the nature of code가 다 영어로 되어있다보니 읽는데 시간이 좀 걸린다. 공부할게 많다...

댓글