Silverback9

#야생으로

Creative Coding 독학 제056일 2024년05월22일(수)

오늘은 어제 공부한 push()____pop() 을 사용해서, 물체마다 독립적인 상대좌표를 부여하여 물체들이 자신의 중심을 기준으로 회전하는 것을 표현해 보겠습니다~^^*

태양계의 물체들에게 이 독립적 상대좌표를 각각 부여하고 자신의 중점을 기준으로 회전시키면…, 와우! 행성들이 태양을 중심으로 공전을 하면서 자신 내부를 중심으로 자전하는 모습을 표현하게 되는 것인가요??? 와우!!!! 얼른 만들어 봅시다!!! 와우!!!

아래 동영상 강의를 클릭하시면 오늘 공부내용을 바로 시작(4:55)하실 수 있어요~^^*

좌표체계의 생성과 변화를 그림으로 그려보았습니다. (1) 물체들의 캔버스 위 위치이동은 두 번째 좌표체계에서 서로 함께 이루어지고, (2) 각 물체의 내부중심 회전은 세 번째 좌표체계에서 독립적으로 따로따로 이루어 지는데, (1)과 (2)는 동시에 이루어 지는 것이겠지요? 공전(orbit)과 자전(rotation)!!

자세한 내용은 코드 안의 주석들을 참고해 보셔도 좋을 것 같아요~~^^*


class Mover{
  constructor(x,y,vx,vy,m, R, G, B){
    this.pos = createVector(x,y);
    this.vel = createVector(vx, vy);
    this.acc = createVector(0,0);
    this.mass = m;
    this.r = sqrt(this.mass)*2; 
    this.Red = R;
    this.Green = G;
    this.Blue = B;
    
    this.angle = 0;
    this.angleV = 0;
    this.anvleA = 0;
  }
  
  applyForce(force){  
    let f = p5.Vector.div(force, this.mass);
    this.acc.add(f); 
  }
  
  attract(mover){ 
    let force = p5.Vector.sub(this.pos, mover.pos);
    let distanceSq = constrain(force.magSq(),100, 1000);
    let G =0.5;
    let strength = G*(this.mass*mover.mass)/distanceSq;
    force.setMag(strength);
    mover.applyForce(force);
  }
  
  update(){
    this.vel.add(this.acc);
    this.pos.add(this.vel);
    
    this.angleA = this.acc.x/100;
    //현재 이 물체의 x축 위치이동 가속도 값의 1/100을 회전 각 가속도 값으로 설정합니다.
    
    this.angleV += this.angleA;
    this.angle += this.angleV;
    //회전각 가속도 값을 회전각 속도 값에 더하고, 회전각 속도 값을 회전각 값에 더합니다. 
    
    this.acc.set(0,0);
    //위치이동 가속도값을 0로 세팅합니다. 함수 draw()의 무한반복성으로 인해 Force의 누적과 연계된 가속도 값의 반복누적을 예방하기 위한 조치입니다. 
  }
  
  show(){
    stroke(255);
    strokeWeight(2);
    fill(this.Red,this.Green,this.Blue, 100);
    
    push();
    //이 물체에게만 적용되는 작업들의 시작입니다. 

      translate(this.pos.x, this.pos.y);
      //좌표체계가 이 물체의 위치좌표(x,y)을 원점(0.0)으로 하는 상대좌표로 바뀝니다. 
      rotate(this.angle);
      //이 물체의 회전각 값만큼 좌표체계가 회전합니다. 

      line(0,0, this.r,0);
      //원점(0,0)에서 수평으로 반지름 거리까지를 선으로 표현합니다. 

      ellipse(0,0, this.r*2);
      //원점을 중점으로 r크기의 반지름을 가진 원을 그립니다. 
      //이 물체의 중점을 기준으로 회전하는 것이 선을 통해 표현됩니다. 

    pop();
    //이 물체에게만 적용되는 작업들의 종료입니다. 
    
//정리해 보면, 
//1. 각 물체의 중점을 원점으로 하는 상대좌표가 각 물체마다 독립적으로 생기고, 각 물체의 중점을 기준으로 회전하는 모습이 선으로 표현됩니다.
//2. 이때 회전각의 크기는, 이 물체가 전체 캔버스의 좌표체계 안에서 갖는 x축 위치이동 가속도값이 반영된 것입니다. 
//3. 전체 캔버스의 좌표체계는 캔버스 한가운데를 원점으로 갖는 상대좌표 체계입니다. 
//4. 원래의 전체 캔버스의 좌표체계는 왼편의 위쪽 모서리를 원점으로 갖습니다.    
    
  }
}
let movers = [];
let Sun;

function setup() {

  createCanvas(400,400); 
  //좌표체계의 원점(0,0)은 캔버스 왼편 위쪽 모서리에 있습니다. 
  
  for( i = 0; i < 8; i++){
    //8의 태양계 행성을 만듭니다. 
    
    let pos = p5.Vector.random2D();
    let vel = pos.copy();
    vel.setMag(random(5,15));
    vel.rotate(PI/2);
    pos.setMag(random(100, 150));
    let m = random(10, 25);
    
    let r = random(255);
    let g = random(255);
    let b = random(255);
    //다양한 색깔을 가집니다. 
    
    movers[i] = new Mover(pos.x, pos.y, vel.x, vel.y, m, r, g, b); 
  }
  
  Sun = new Mover(0,0,0,0, 500, 255, 0,0);
  //붉은 태양을 만듭니다. 붉은색은 R:255 G:0 B:0 입니다. 
}


function draw() {
  background(0);
  
  translate(width/2, height/2);
  //캔버스 한가운데가 원점(0,0)이 되는 상대좌표체계로 바뀝니다. 

  for(let mover of movers){
    Sun.attract(mover); 
    mover.attract(Sun);
    for(let other of movers){
      if (mover !== other){
        mover.attract(other);    
    }
   }
  }
  for(let mover of movers){
  mover.update();  
  mover.show(); 
  }
  Sun.update();
  Sun.show();
}
거꾸로 다시 정리해 보면,
    
1. 왼편 위쪽 모서리를 원점으로 갖는 원래의 캔버스 좌표체계가
2. 캔버스 한가운데를 원점으로 갖는 상대좌표체계로 바뀌었고, 
3. 이를 기준으로 위치이동 좌표와 위치이동 속도와 위치이동 가속도 값이 설정되었습니다.
4. 각 물체의 중점을 원점으로 갖는 상대좌표체계가 각 물체마다 독립적으로 만들어졌고,
5. 이 원점을 기준으로 회전하는 회전각 값과 회전각 속도와 회전각 가속도 값이 설정되었습니다. 
6. 우리 프로그램에서는 전체 캔버스 위의 위치이동 x축 가속도값이 물체 내부의 회전각 가속도 값으로 임의적으로 반영되었습니다. 

이것을 클릭하여 mover.js 파일과 sketch.js 파일을 열어 코드를 살펴 보셔요~^^* 삼각형을 눌러 프로그램을 실행시켜 붉은 태양과 8개의 아름다운 행성들이 공전하며 자전하는 모습을 관찰해 보셔요~^^* 행성들 내부의 하얀 선을 보시면 자전을 느껴보실 수 있으시겠죠~~^^*? 네~ 종료는 사각형~~~^^*

지구가 하루에 한 번씩 자신의 큰 몸을 한 바퀴 부지런히 돌리고 있는데, 그 소리가 들리지 않는 것은, 우리가 지구의 공기를 아름다운 음악으로 가득 채우고 있기 때문일까요? It’s All Music!!

우리 각자의 하루도 부지런히 그리고 즐겁게 한 바퀴 돌려 볼까요~^^* 점심 맛있게 드시구요~^^*

오늘도 코딩 공부 함께 해 주셔서 감사합니다~^^* 우리 내일 또 만나서 코딩공부 함께 해요~^^*

네, 꿈은 이루어 집니다~~~~!!

댓글 남기기