Silverback9

#야생으로

Creative Coding 독학 제238일 2024년11월20일(수)

어제 밤에 문제를 개선해 보려고 했는데요…무한 루프에 빠져서 프로그램이 다운이 자꾸만 되었어요…

피곤해서인지…오류 부분을 못찾고…오늘 아침을 기약하며 잠들었어요…

역시 에너지 충전된 아침 뇌로 다시 들여다 보니, 배열의 이름을 새로 고침하지 않아서 그런 것 같았어요.

아주 사소한 버그였는데…

네~~^^* 버그는 찾고 나면 항상 사소한 것인 것 같아요^^*

이제는 프로그램이 잘 작동이 되어요~~^^* YEAH~~^^*

자 그럼 어제 시도해본 사고 실험을 되짚어 볼게요~^^*

먼저, endPoint!

첫 번째 회전에서는 b를 endPoint로 하고 두 번째 회전부터는 a를 endPoint로 하기로 했었지요~^^*

그리고, concatenate 배열 합치기!

예전 배열에 새 배열을 덧붙이기로 했었지요~

그럼 핵심 코드를 살펴 볼까요~^^**

(1) segments[]와 더불어 endPoint를 글로벌 변수로 만들어 놓겠습니다~^^* 하나 이상의 함수에서 segments[]와 endPoint의 값을 변화시킬 수 있겠네요.

let segments = [];
let endPoint;

(2) 태초의 선을 만들 때, 첫 번째 회전을 준비하기 위해, b를 endPoint로 지정하겠습니다~^^*

function setup(){

  createCanvas(400, 400);
  
  let a = createVector(200, 200);
  let b = createVector(200, 100);
  
  endPoint = b;

  segments.push(new Segment(a, b));
}

(3) 첫 번째 회전이 끝나면, a를 endPoint로 지정하겠습니다~^^*

(4) 회전하여 만들어진 새로운 newSegments[]를 전체 segments[]에 concatenate 덧붙이겠습니다~^^*

function mousePressed() {
  let newSegments = [];
  //마우스 클릭으로 생성 회전 변화되는 segment들을 담는 배열입니다. 
  
  for (let s of segments) {
  
    let newS = s.rotate(endPoint);
    newSegments.push(newS);
    
  //endpoint를 origin으로 하여 90도 회전하여 생긴 새로운 선 segment를 배열 newSegments[]에 저장합니다. 
  //첫 회전의 endPoint는 b입니다. 함수 setup()에서 지정해 놓았었죠~^^*
  
  }  
  
  endPoint = newSegments[0].a; //(3)
  //두 번째 회전부터는 a가 endPoint가 됩니다~^^*
  
  segments = segments.concat(newSegments); //(4)
  //마우스 클릭으로 생성된 newSegments[]를 전체 segments[]에 담습니다~^^*
}

자 그럼 이제 우리 전체 코드를 함께 살펴 볼까요~~^^*

class Segment {
  constructor(a, b) {
    this.a = a;
    this.b = b;
  }
  show(){
    stroke(0);
    strokeWeight(2);
    line(this.a.x, this.a.y, this.b.x, this.b.y);
  }
  
  rotate(origin) {
    let va = p5.Vector.sub(this.a, origin);
    //벡터 Origin에서 벡터 A로 향하는 벡터 va입니다.
    
    let vb = p5.Vector.sub(this.b, origin);
    //벡터 Origin에서 벡터 B향하는 벡터 vb입니다. 
    //이 프로그램에서 벡터 Origin은 벡터 B와 동일할 것입니다.
    //그래서 동일 벡터 뺄셈의 결과인 벡터 vb의 크기는 0가 될 것입니다.
    
    va.rotate(-PI/2);
    vb.rotate(-PI/2);
    //반시계방향 90도 회전하겠습니다.
    //두 벡터의 방향은 일치합니다.
    
    let newA = p5.Vector.add(origin, va);
    //크기(0 + va = va)인 새로운 벡터 newA입니다.
    
    let newB = p5.Vector.add(origin, vb);
    //크기(0 + 0 = 0)인 새로운 벡터 newB입니다. 
    //원래 B의 위치 그대로입니다. 
    
    let newS = new Segment(newA, newB);
    //newA와 newB를 잇는 선 newS입니다. 
    
    return newS;
  }
}

let segments = [ ];
let endPoint;

//전체 segments[]와 endPoint는 글로벌 변수로 지정하여, 모든 함수들이 그 값을 변화시킬 수 있도록 하겠습니다~^^*

function mousePressed() {
  
  let newSegments = [];
  
  for (let s of segments) {
  
    let newS = s.rotate(endPoint);
    newSegments.push(newS);
    
  }  
  
  endPoint = newSegments[0].a;
  
  segments = segments.concat(newSegments);
  
  //두 번째 회전부터는 endPoint가 a입니다. 
  //마우스클릭으로 생성 회전 변화된 newSegments[]를 전체 segments[]에 덧붙입니다~^^*
}

function setup(){

  createCanvas(400,400);
  
  let a = createVector(200, 110);
  let b = createVector(200, 105);
  
  endPoint = b;

  segments.push(new Segment(a, b));
}
//벡터 a와 b을 생성하여, 클래스 Segment의 시작점과 끝점으로 삼습니다. 
//생성된 클래스 Segment를 배열 segments의 구성요소로 넣습니다.
//첫 회전의 endPoint는 b입니다~^^* b가 첫 회전의 origin이 되겠네요~^^*
//화면에 Dragon Curve를 많이 담아내기 위해 segment 길이는 5로 하겠습니다^** //110 - 105 = 5 ~^^* 

function draw(){

  background(220);

  for (let s of segments) {
    s.show();
  } 
} 

//클래스 Segment를 저장한 배열 segments의 구성요소인 모든 s들을 보여줍니다.

어린이들의 슈퍼 스타 공Dragon의 깃털이 펼쳐집니다~~^^*

좀더 큰 화면으로 보시겠다면~ 캔버스 (800by800)버전으로 감상하셔요~~^^*

오늘 저와 함께 어제의 사고 실험을 코드로 완성해 주셔서 감사합니다~~^^*

내일은 이 멋진 펼쳐짐을 애니메이션으로 보여주는 코드 만들기를 도전해 볼까요~^^*

한 고비 넘기면 다음 고비가~~^^* 고비고비 넘어가며 공Dragon은 튼튼해 집니다~^^*

함께 도전도 해보고 어려움도 함께 해결해 내며 씩씩해 지는 공Dragon~~^^*

내일부터 애니메이션 만들기 도전! 우리 함께 하면 좋겠어요~~^^*

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

오늘도 멋진 아침! 맛있는 점심! 멋진 하루! 보내시고요~^^*

우리 내일 또 만나요~~^^*

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

댓글 남기기