Silverback9

#야생으로

Creative Coding 독학 제171일 2024년09월14일(토)

추석연휴가 시작되었습니다~~^^*

이동의 피곤함을 충분히 가셔내고 천천히 앉은 책상 맡입니다~^^* 귿모닝~~^^*

명절을 맞으면, 그 날을 기점으로 한 4 계절이 마음 속에서 한 바퀴 도는 것 같아요.

2023 가을 – 2024 겨울 – 2024 봄 – 2024 여름

지난 365일을 천천히 되감으며 사계절를 거꾸로 걸어가는 연휴의 아침의 여유~^^*

이 여유가 4 계절은 왜 생기는 것일까? 새삼 궁금해 지도록 만드네요~^^*

사계절은 우리에게 서로 다른 감성을 선물하고~^^*

사계의 만만치않음을 깊이 있게 느끼게 하고~^^*

또다른 4계절이 시작됨을 마음 준비한 우리는, 옷장 속으로 들어가 가을의 문을 엽니다.

이제 우리가 들어서고 있는 가을 세계를 찬찬히 눈으로 만지며, 연휴의 아침을 누려볼까요~^^*

저는 그 동안 오늘의 코드 공부를 하고 다시 돌아올게요~^^* 푹 쉬고 계셔요~~^^*

우리 곧 또 다시 만나요~~^^*

네~^^* 돌아왔습니다~~^^*

편안한 아침 보내셨나요~~^^*

연의 실을 그리는 프로그램 기억하고 계시나요^^*

우리는 이제 p5.js the nature of code 강의 시리즈의 부록 프로그램까지 공부를 다 마쳤어요~^^*

그래서, 오늘은 연의 실 프로그램을 마무리 해 보면 어떨까요~^^*

p5.js 공부 포럼에 이 문제를 질문했었는데요~^^* 친절한 답변이 왔었거든요~^^*

   // Count positions
    let total = 0;
    for (let path of this.paths) {
      total += path.length;
    }

    if (total > 100) {
      this.paths[0].shift();
      if (this.paths[0].length === 0) {
        this.paths.shift();
      }
    }
First, the question "When does the length of an item of an array become zero". On line 123 there's a this.paths[0].shift(). This removes the first element from the paths[0] array. This is done so that the line doesn't grow forever.

Next, if the paths[0] array is empty (.length === 0), remove it from the array paths. This is a simple optimization. Technically you can leave the empty array there, but it'll cause the sketch to slowdown eventually - JS will still have to loop over the array, even if just to skip it.

(1) 연의 실 배열의 요소의 총합을 100 이하로 유지하기 위해, 총합이 100을 넘어서면, 연의 실 배열의 첫번째 구성요소를 제거를 하고 : 구성 요소 제거

(2) 연의 실 배열이 비어있을 경우에는, 이 연의 실 배열을 전체 연의 실 타래 배열에서 제거한다: 배열 제거

** 작업 지시문 목적: 프로그램의 성능 최적화: 비어있는 배열을 괜히 점검하느라 시간을 소비하지 말자~

그럼, 연의 실 프로그램을 오래간만에 대하는 것이니, 기억을 되살릴 겸 복습 삼아 전체 코드를 저랑 함께 보실까요~^^*

<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.min.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css">
    <meta charset="utf-8" />

  </head>
  <body>
    <script src="vehicle.js"></script>
    <script src="sketch.js"></script>
  </body>
</html>
class Vehicle {
  constructor(x, y) {
    this.pos = createVector(x, y);
    this.vel = createVector(1, 0);
    this.acc = createVector(0, 0);
    this.maxSpeed = 4;
    this.maxForce = 0.2;
    this.r = 16;
    this.wanderTheta = PI/3;
    
    this.currentPath = [];
    this.paths = [this.currentPath];
    //캔버스 안에서 활동할 동안의 vehicle의 위치좌표를 모으는 배열this.currentPath
    //배열 this.currentPath들을 모으는 배열 this.paths
  }
  
  wander() {
    let wanderPoint = this.vel.copy();
    wanderPoint.setMag(100);
    wanderPoint.add(this.pos);
    fill(255, 0, 0);
    noStroke();
    circle(wanderPoint.x, wanderPoint.y, 16);

    let wanderRadius = 50;
    noFill();
    stroke(255);
    circle(wanderPoint.x, wanderPoint.y, wanderRadius * 2);
    line(this.pos.x, this.pos.y, wanderPoint.x, wanderPoint.y);

    let theta = this.wanderTheta + this.vel.heading();

    let x = wanderRadius * cos(theta);
    let y = wanderRadius * sin(theta);
    wanderPoint.add(x, y);
    fill(0, 0, 255);
    noStroke();
    circle(wanderPoint.x, wanderPoint.y, 16);

    stroke(255);
    line(this.pos.x, this.pos.y, wanderPoint.x, wanderPoint.y);

    let steer = wanderPoint.sub(this.pos);
    steer.setMag(this.maxForce);
    this.applyForce(steer);

    let displaceRange = 0.3;
    this.wanderTheta += random(-displaceRange, displaceRange);
  }

  applyForce(force) {
    this.acc.add(force);
  }

  update() {
    this.vel.add(this.acc);
    this.vel.limit(this.maxSpeed);
    this.pos.add(this.vel);
    this.acc.set(0, 0);
    
    this.currentPath.push(this.pos.copy());
    //vehicle의 위치좌표를 수집합니다.
    
    // 꼬리 길이를 100로 제한하겠습니다. 
    let total = 0;
    for (let path of this.paths) {
      total += path.length;
    }

    if (total > 100) {
      this.paths[0].shift();
      //꼬리가 100보다 길어지면 
      //배열의 첫 번째 구성요소를 제거합니다.
      if (this.paths[0].length === 0) {
        this.paths.shift();
      //배열이 비어있으면, 전체 배열에서 제거합니다.   
      }
    }
 }

  show() {
    stroke(255);
    strokeWeight(2);
    fill(255);
    push();
    translate(this.pos.x, this.pos.y);
    rotate(this.vel.heading());
    triangle(-this.r, -this.r / 2, -this.r, this.r / 2, this.r, 0);
    pop();
    
    for (let path of this.paths) {
    beginShape();
    noFill();
    for ( let v of path) {
      vertex(v.x, v.y);
    }
    endShape(); 
    } 
    //화면 안 움직임만을 모은 path들이 점들을 연결합니다.
  }

  edges() {
    let hitEdge = false;
    if (this.pos.x > width + this.r) {
      this.pos.x = -this.r;
      hitEdge = true;
    } else if (this.pos.x < -this.r) {
      this.pos.x = width + this.r;
      hitEdge = true;
    }
    if (this.pos.y > height + this.r) {
      this.pos.y = -this.r;
      hitEdge = true;
    } else if (this.pos.y < -this.r) {
      this.pos.y = height + this.r;
      hitEdge = true;
    }
    //vehicle이 화면 밖을 나가면 좌<->우 상<->하 이동하여 화면 안에 다시 들어올 준비를 합니다. 
    //화면 밖으로 나간다는 token hitEdge를 활성화시킵니다. 
    
    if(hitEdge) {
      this.currentPath = [];
      this.paths.push(this.currentPath);
    }
    //vehicle이 화면 밖으로 나가면, 화면 안 움직임을 기록하는 currentPath를 새로 만듭니다.
    //currentPath들을 모으는 배열 path의 끝에 넣습니다. 
  }
}
let vehicle;

function setup() {
  createCanvas(400, 400);
  vehicle = new Vehicle(100, 100);
}

function draw() {
  background(0);

  vehicle.wander();
  
  vehicle.update();
  vehicle.show();
  vehicle.edges();
}

길이도 적당하고, 컴퓨팅 최적화도 이루어 낸 우리들의 연의 실을 바라보러 가을 언덕으로 오늘 저녁 우리 함께 올라가 볼까요~~^^* 노을이 깔려진 하늘 위로 연의 실이 산들산들~~춤을 추네요~~^^*

네~~^^*

오늘로서, p5.js the nature of code 강의 시리즈는 마무리가 되었습니다~^^*

그동안 저와 함께 코딩 공부를 해주셔서 정말 감사드려요~~^^*

앞으로의 4계절 동안, 우리 또 매일 아침 코딩 공부 함께 하면 좋겠어요~~^^*

다양한 주제와 새로운 도전들이 우리를 기다리고 있어요~^^*

옷장을 덮고 있는 흰 천을 젖힐 준비가 되셨나요~~^^*

네~^^* 그럼 우리 내일 또 새로운 세계에서 다시 만나요~~^^*

오늘도 즐거운 오후! 편안한 저녁과 깊은 밤! 보내셔요!

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

댓글 남기기