Silverback9

#야생으로

Creative Coding 독학 제108일 2024년07월13일(토)

오늘은 드디어~~네! 드디어~~와우!

화염을 만들어 보~겠~습~니~다~~~^^*

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

어제 우리는~~^^*,

일전에 코드로 만들어 놓았던 동그라미 입자 이미지를 (32*32) 크기로 줄여서, 빗방울 입자 이미지로 사용을 했었지요~^^*

let this.lifetime = 255;

tint(255, this.lifetime);

this.lifetime -= 5;

로 코드를 짜서, 흰색 255 +불투명도 255로 초기 설정을 하여, 시간이 지남에 따라, 불투명도 this.lifetime을 줄여 나갔어요~

오늘 우리는~~^^*,

let this.lifetime = 255;

tint(255, 5, 5, this.lifetime);

this.lifetime -= 5;

로 코드를 짜서, 붉은 느낌이 강한 색(255, 5, 5) + 불투명도 255로 초기 설정을 하여, 불투명도 this.lifetime을 줄여 나갈게요~

아 네 네!!!

음~~왜 그냥 붉은 색(255, 0, 0)을 사용하지 않고 붉은 느낌의 색 (255, 5, 5)사용하는 지 궁금하시다고요?

어머 그러네요…. 흠…왜 그럴까요….???

참! 그런데요~~!!!

불꽃은 안쪽 부분이 많이 밝아 보이잖아요~~^^*

그 느낌을 만들기 위해,

함수 blendMode(ADD);

를 사용해 보겠습니다~^^*

ADD는 여러 가지 색상의 빛을 합치는 것을 의미해요~^^*

빛은 다양한 색상의 빛을 섞으면 섞을 수록 밝아져서 점점 희어지는데요~

그 원리를 사용해 보겠습니다~!!

아 네 네!!!

네…. 그렇죠….!!! 역시….예리하시군요!!!

순한 붉은 색이면 (150, 0, 0)을 하면 될텐데…왜 순하게 붉은 느낌의 색(150, 40, 80)를 사용하는지 궁금했었는데…blendMode(ADD); 보니 이제 이해가 되신다구요…!!!

그러네요!!!! 오오!!!

(150, 0, 0)은 빛 색상의 더하기 blendMode(ADD)의 효과가 없을 것 같아요. Red 빛 하나만 존재하니까요.

(150, 40, 80)는 Green 빛과 BLue 빛이 약하게나마 존재하고 있어서, 화염 입자들이 여러 개 겹칠 수록, blendMode(ADD)의 효과가 점점 커질 것 같아요~

신기하네요~~^^*

그리고요~~^^*

이전 프레임의 이미지 색상이 남아있어서 blendMode(ADD)에 중복합산되지 않도록~,

함수 clear()를 사용하여~, 이전 프레임 화면을 깨끗하게 지우겠습니다~~^^*

그래서, 오늘의 핵심 코드는~~~~

clear();

blendMode(ADD);

let this.lifetime = 255;

tint(150, 40, 80, this.lifetime);

this.lifetime -= 10;

입니다~~^^*

그럼 이제 화염을 표현한 프로그램의 파일별 코드 내용을 함께 살펴 볼까요~^^*

<!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="particle.js"></script>
      <script src="emitter.js"></script>
      <script src="sketch.js"></script>
  </body>
</html>

class Particle {
  constructor(x, y) {
    this.pos = createVector(x, y);
    this.vel = p5.Vector.random2D();
    this.vel.mult(random(0.5, 3));
    this.acc = createVector(0, 0);
    this.r = 32;
    this.lifetime = 255;
  }

  finished() {
    return this.lifetime < 0;
  }
  //화염 입자가 일생을 잘 마무리 하였다면 True 값을 반환합니다.

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

  edges() {
    if (this.pos.y >= height - this.r) {
      this.pos.y = height - this.r;
      this.vel.y *= -1;
    }
   
    if (this.pos.x >= width - this.r) {
      this.pos.x = width - this.r;
      this.vel.x *= -1;
    } else if (this.pos.x <= this.r) {
      this.pos.x = this.r;
      this.vel.x *= -1;
    }
    //붉은 화염이, 단단한 바닥이나 벽에 닿으면 움직임의 방향을 바꾸도록 하겠습니다. 
  }

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

    this.lifetime -= 10;
  }

  show() {
    
    tint(150,40,80, this.lifetime);
    //픽셀 이미지 데이터 Red, Green, Blue, Alpha를 관장하는 함수입니다. 처음엔 순한 붉은 느낌의 색(R 150 G 40 B 80)의 불투명(this.lifetime 255)이지만, 시간이 지나면서, this.lifetime이 -10씩 변화되면서, 점점 투명해 집니다.   
    
    imageMode(CENTER);
    //이미지의 위치좌표점을 가운데에 놓겠습니다.
    
    image(img, this.pos.x, this.pos.y, this.r);
    //이미지파일을, 붉은 화염 위치 좌표 (this.x, this.y)에 지정된 크기 this.r 사이즈로 보여줍니다.
    
  }
}
class Emitter {
  constructor(x, y) {
    this.position = createVector(x, y);
    this.particles = [];
  }
  //화염 스팟은 각각 지정된 좌표에, 입자 배열을 생성하여꽃불꽃을 뿜습니다~

  emit(num) {
    for (let i = 0; i < num; i++) {
      this.particles.push(new Particle(this.position.x, this.position.y));
    }
  }
  //지정된 갯수의 화염 입자를 한 번에 만들어 입자 배열에 담습니다~. 

  update() {
    for (let particle of this.particles) {
      let gravity = createVector(0, 0.01);
      particle.applyForce(gravity);
      //중력의 작용을 받도록 하겠습니다~^^*
      
      let dirX = map(mouseX, 0, width, -0.3, 0.3);
      let dirY = map(mouseY, 0, height, -0.3, 0.3);
      let yourControl = createVector(dirX, dirY);
      particle.applyForce(yourControl);
      //마우스 움직임에 따라 바람의 방향이 변화합니다~^^*
      
      particle.update();
      particle.edges();
    }
    

    for (let i = this.particles.length - 1; i >= 0; i--) {
      if (this.particles[i].finished()) {
        this.particles.splice(i, 1);
      }
    }
    //화염 입자 배열의 맨뒤에서 앞으로 나아가며, 화염 입자 수명을 점검하여, 일생을 잘 마무리 하였다면, 화염 입자 배열에서 풀어주어 검은 밤 공기 속에 몸을 시원하게 담그고 쉬도록 배려합니다. 컴퓨터 복지도 배려합니다^^*
  }

  show() {
    for (let particle of this.particles) {
      particle.show();
    }
  }
  //화염을 보여 줍니다~^^*
}
let emitters = [];
//깜깜한 밤을 밝혀줄 화톳불을 담을 배열입니다~^^*
//오늘은 화력 좋은 화톳불 하나만 지피도록 하겠습니다~^^*

let img;
//직접 만들었던 입자 이미지 파일의 크기를 줄인 (32*32) 이미지 파일을 저장할 변수입니다~^^


function preload(){
  img = loadImage('smallone.png');
  //기존의 동그라미 입자 이미지 파일을 (32*32픽셀)로 크기를 줄인 이미지 파일을 로드하여 변수 img에 저장하겠습니다~^^* 
}

function setup() {
  createCanvas(400, 400);
  emitters.push(new Emitter(200, 350));  
 
}

function draw() {
  
  clear();
  //이전 프레임에서 그려놓은 불꽃 이미지를 지웁니다~
  //이전 프레임의 이미지 색상이 영구적으로 남겨져 BlendMode(ADD)에 중복합산되지 않도록 하기 위한 장치인 것 같아요~^^* 
  
  background(0);
  //깜깜한 밤이예요..!
  //하지만 걱정 마세요~!!
  //우리에겐 붉은 화톳불이 있으니까요!!!
  
  blendMode(ADD);
  //가슴 속 밝고 하얀 순수한 마음을 가진 열정 불꽃을 그려 봅시다~~!! 


  for (let emitter of emitters) {
    emitter.emit(3);
    //화력 좋은 화톳불입니다!!
    emitter.show();
    emitter.update();
  }
}

넵, 화력 좋은 화톳불로 캄캄한 밤 공기에 빛과 열기를 더해 볼까요~^^* 마우스/손가락을 움직여 바람의 방향을 변화시켜 보셔도 재미있겠지요~~~^^* 캠프파이어 고고~~~^^*

열심히 살아온 이번 한 주 끝, 토요일 저녁입니다~

불멍하셔요~~^^*

와우!!! 입자에 대한 모든 것을 마무리 한 오늘이네요~^^*

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

하나의 챕터를 마무리 하였으니…^^*

새로운 챕터가 또 우리를 기다리고 있겠네요~~^^*

네~~!! 우리 내일 또 만나서 함께 코딩공부해요~~~^^*

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

댓글 남기기