어제 밤에 문제를 개선해 보려고 했는데요…무한 루프에 빠져서 프로그램이 다운이 자꾸만 되었어요…
피곤해서인지…오류 부분을 못찾고…오늘 아침을 기약하며 잠들었어요…
역시 에너지 충전된 아침 뇌로 다시 들여다 보니, 배열의 이름을 새로 고침하지 않아서 그런 것 같았어요.
아주 사소한 버그였는데…
네~~^^* 버그는 찾고 나면 항상 사소한 것인 것 같아요^^*
이제는 프로그램이 잘 작동이 되어요~~^^* 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~~^^*
내일부터 애니메이션 만들기 도전! 우리 함께 하면 좋겠어요~~^^*
네~!! 꿈은 이루어 집니다~!!
오늘도 멋진 아침! 맛있는 점심! 멋진 하루! 보내시고요~^^*
우리 내일 또 만나요~~^^*
네~~!!! 꿈은 이루어 집니다~~!!!
댓글 남기기