Silverback9

#야생으로

Creative Coding 독학 제102일 2024년07월07일(일)

오늘은 상속 inheritance와 다형성 polymorphism을 복습하며, 빗방울과 우박이 함께 내리는 우박비를 표현하는 프로그램을 만들어 보겠습니다~~~^^*

하나. 클래스 빗방울 Rain은 클래스 p5.Vector의 자녀입니다~^^*

둘. 클래스 우박 Hail은 클래스 빗방울 Rain의 자녀입니다~^^*

셋. 우박비를 생성하는 것은 클래스 Emitter입니다~^^*.

넷. 빗방울 50% 우박 50%로 구성된 우박비를 생성하겠습니다~^^*.

다섯. 마우스/손가락으로 화면 위 우박비를 내리게 할 수 있습니다~^^*.

지난 삼 일 동안 배운 내용이 모두 함께 모여 있는 것 같은데요!!!

아래 동영상을 클릭하시면 오늘 공부 내용을 보실 수 있어요~~~^^*

중요한 내용들은 이미 다 배운 것들이라서, 보다 자세한 내용은 코드 안 주석을 살펴 보셔도 좋을 것 같습니다~~^^*

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

  </head>
  <body>
    <main>
    </main>
     <script src="rain.js"></script>
     <script src="hail.js"></script>
     <script src="emitter.js"></script>
     <script src="sketch.js"></script>
  </body>
</html>

class Rain extends p5.Vector {
  constructor(x, y) {
    super(x, y);
    this.vel = p5.Vector.random2D();
    this.vel.mult(random(0.5, 2));
    this.acc = createVector(0, 0);
    this.r = 8;
    this.lifetime = 255;
  }

  finished() {
    return this.lifetime < 0;
  }
  //물방울이 완전히 투명하다면 True 값을 반환합니다.

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

  edges() {
    if (this.y >= height - this.r) {
      this.y = height - this.r;
      this.vel.y *= -1;
    }

    if (this.x >= width - this.r) {
      this.x = width - this.r;
      this.vel.x *= -1;
    } else if (this.x <= this.r) {
      this.x = this.r;
      this.vel.x *= -1;
    }
  }

  update() {
    this.vel.add(this.acc);
    this.add(this.vel);
    this.acc.set(0, 0);

    this.lifetime -= 5;
  }

  show() {
    stroke(255, this.lifetime);
    strokeWeight(2);
    fill(255, this.lifetime);
    //소낙비는 한꺼번에 쏟아져서 마치 우유가 쏟아지는 듯 하지요~^^*
    //바닥에 닿으면, 맑은 방울로 보이구요~^^*
    //그래서~ 빗방울을 처음엔 하얗고, 시간이 지나면 점점 투명해 지도록 만들어 볼게요~~^^*

    ellipse(this.x, this.y, this.r * 2);
  }
}

//클래스 RainDrop은 클래스 p5.Vector의 자녀입니다. 
//클래스 p5.Vector의 구성요소와 행동양식을 그대로 상속받습니다. 
//그래서, 클래스 RainDrop 자체가 vector object입니다.
//그러므로, this.position.x 문구를 쓰지 않고, this.x라고 표현합니다.
class Hail extends Rain {
  constructor(x, y) {
    super(x, y);
    this.angle = random(TWO_PI);
    //0 ~ 2파이 사이의 회전각을 갖습니다. 
  }

  show() {
    noStroke();
    fill(100, 200, 255, this.lifetime);
    //우박은 단단해서, 하늘색으로 표현해 보겠습니다.

    push();
    
    translate(this.x, this.y);
    //우박위치좌표를 중심좌표로 하는 상대좌표가 생성됩니다.
    rotate(this.angle);
    //상대좌표 위에서 회전각만큼 회전합니다.
    square(0, 0, this.r * 2);
    //그래서, 다양한 각도로 회전된 상태의 사각형이 생성됩니다. 
    
    pop();
  }
}

//Confetti는 Particle의 자녀입니다. 
//Particle는 P5.Vector의 자녀입니다.
//Confetti는 조부모인 P5.Vector의 구성요소와 행동양식도 상속받습니다. 
//그래서, Confetti 자신이 바로 vector object입니다. 
//그러므로, this.position.x 가 아니라 this.x로 표기합니다. 
class Emitter {
  constructor(x, y) {
    this.position = createVector(x, y);
    this.hailRain = [];
  }
  //국지성 우박비 스팟은 각각 지정된 좌표에, 물방울/우박을 생성하여 우박비를 내립니다~
  //Emitter는 P5.Vector를 부모로 상속받지 않습니다.
  //그래서, this.position 문구를 사용하는 것이지요~^^*

  emit(num) {
    for (let i = 0; i < num; i++) {
      if (random(1) < 0.5) {
        this.hailRain.push(new Rain(this.position.x, this.position.y));
      } else {
        this.hailRain.push(new Hail(this.position.x, this.position.y));
      }
    }
  }

  //지정된 갯수의 배열 요소 중 50%는 빗방울을 50%는 우박을 만들어 우박비 배열에 담습니다. 

  update(){
    for (let h of this.hailRain) {
      let gravity = createVector(0, 0.2);
      h.applyForce(gravity);
      h.update();
      h.edges();
    }
    //빗방울/우박은 중력의 작용을 받고, 벽이나 바닥에 부딪히면 튑니다~

    for (let i = (this.hailRain.length - 1); i >= 0; i--) {
      if (this.hailRain[i].finished()) {
        this.hailRain.splice(i, 1);
      }
    }
    //우박비 배열의 맨뒤에서 앞으로 나아가며, 빗방울/우박 투명도를 점검하여, 완전히 투명하다면, 우박비 배열에서 삭제합니다. 컴퓨터 복지 향상을 위하여~~~^^*
  }

  show(){
    for (let h of this.hailRain) {
      h.show();
    }
  }
  //빗방울/우박을 보여 줍니다~^^*
}
let emitters = [];
//국지성 우박비가 내릴 곳들의 배열입니다~^^*

function mousePressed() {
  emitters.push(new Emitter(mouseX, mouseY));
//마우스/손가락 클릭하는/누르는 곳이 바로 국지성 우박비 스팟입니다~
}

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(200);
  //흐린 하늘에 우박비가 내려요...어머...
  for (let emitter of emitters) {
    emitter.emit(1);
    //한 번에 물방울/우박 하나를 만들어 내리는 우박비입니다...어머..
    emitter.show();
    emitter.update();
  }
}
//사각형 우박이 다양한 각도로 회전된 상태로 생성되는 것이 보이시나요?
//우박이 사각형이다보니 다양한 각도로 회전된 모습이 자연스러워 보이네요~^^*

우박비 참 드문 현상인데요. 봄에는 가끔 내릴 때가 있다고 해요…7월의 우박비 한 번 만들어 보실래요? 마우스/손가락 클릭클릭~~^^* 뭔가… 8월의 크리스마스처럼 생경하면서도 아스라한 어떤 기억이 되살아 나는 느낌이 드시나요? 우박비 언제 겪어 보셨어요? 음.. 저는 초등학교 때 한 번 겪어 봤어요. 그래서…우박비하면…아동기 시절로 돌아가는 느낌이예요…^^* 언제적 기억이 떠오르시나요?

요즘 엄청 큰 우박비 소식을 해외 뉴스로 접할 때가 있는데요…기후변화와 맞물린 현상일까 궁금해 지기도 해요…

어떤 큰 환경 변화가 있을 때, 가장 먼저 떠오르는 존재는…

역시…사랑하는 가족…사랑하는 사람들…인 것 같아요.

아름다운 자연현상을 목격할 때에도 떠오르는 존재는…역시….

그래서, 우리는 아름다운 환경을 지키기 위해 서로 함께 마음을 모으게 되는 것 같아요.

지켜주고픈 사랑하는 존재들을 위하여~^^*

오늘은 따뜻한 여름 비가 간간이 내렸어요~^^*

따뜻하면서도 시원한 샤워 후 사각거리는 여름 잠옷을 입고~ 몸 보송 기분 촉촉한 일요일 밤 보내셔요~~^^*

오늘도 함께 코딩 공부해 주셔서 감사합니다~^^*

우리 내일은 함께 음악 들을까요~~~~^^*

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

댓글 남기기