Silverback9

#야생으로

Creative Coding 독학 제205일 2024년10월18일(금)

오늘은~~^^*

언덕을 쌓는 <우리의 알갱이>들을 더욱 어여쁘게 개선해 보겠습니다~~^^*

나름의 꿈을 안고 나름으로 열심히 사는 존재는 모두다 어여쁜 것 같아요~~^^*

<우리의 알갱이>도 언덕을 쌓기 위해 열심히 내려와서 안착하고 있으니까, 지금 이대로도 그 어여쁨이 잘 느껴지고 있지요~~^^*?

열심히 살기에 이미 어여쁜 <우리의 알갱이>에게 더욱 어여쁜 색깔을 살짝 입혀보도록 할게요~^^*

예쁜 삶 예쁜 마음 예쁜 모습 더욱 빛나게~~^^*

팔레트를 꺼내어서~~ 예쁜 물감들을 짜서~~ 고운 붓으로~~ 이미 어여쁜 <우리의 알갱이>들에게 더욱 어여쁜 색을 입혀 주면 어떨까요~~^^*

네~~!!

오늘은 우리가 메이컵 아티스트~~^^*

어머!

이미 어여쁜 <우리의 알갱이>가 “네 꿈을 마음껏 펼쳐 봐~”

이미 우리를 믿어주는 다정한 목소리와 편안한 얼굴로~^^*

두 눈을 가만히 감고 고개를 살며시 들고 기다리고 있네요~^^*

믿어 주어 고마워요, 이미 어여쁜 <우리의 알갱이>님!

더욱 어여쁜 꿈을 <우리의 알갱이>님 얼굴 위에 펼쳐 볼게요!

먼저, 이미 어여쁜 <우리의 알갱이>님의 자태를 좀더 자연스럽게 다듬어 보겠습니다.

변화가 없고 꼿꼿한데, 얼굴에 색조를 화려하게 넣으면, 마네킨 느낌이 나서 오히려 그로테스크하게 느껴질 수 있을 것 같아요…

내려오는 행동 모습이 좀더 자연스럽도록 개선해 보겠습니다!

한 스쿱 또는 한 스푼에서 쏟아지는 <우리의 알갱이>의 수가 항상 동일하지 않으면, 좀더 자연스러운 흘러내림의 모습이 표현될 것 같아요~^^*

우리가 지정한 크기의 한 스쿱 matrix 행열 배열 안에 알갱이를 모두 채우지 말고,

임의적으로 군데군데 알갱이를 채워서,

내려오는 <우리의 알갱이>의 수가 시시때때 달라져서,

흘러내림의 모습이 좀더 자연스러울 수 있도록 만들어 보면 어떨까요?

 let matrix = 2;
  let extent = floor( matrix / 2); 
  for (let i = -extent ; i <= extent ; i++) {
    for (let j = -extent ; j <= extent ; j++) {
       if(random(1) < 0.75) {
         let col = mouseCol + i;
         let row = mouseRow + j; 
         if(col >= 0 && col <= cols-1 && row >= 0 && row <= rows-1) {
           grid[col][row] = 1;
         }
       }
    }
  }

어때요? 좀더 자연스러운 모습으로 시원하게 흘러 내리나요~~^^*

네^^* 자연스럽고 시원하게 움직이는 자태 표현이 준비가 되었네요. 그럼 이제 우리, 색조 표현을 시작해 볼까요~^^*

색칠을 위해 함수 colorMode()를 사용해 보겠습니다~^^*

그리고 색 지정은 HSB ( Hue색상, Saturation 채도, Brightness 명도 )를 사용해 보겠습니다.

RGB & HSB Colour Values – Disc (lightcolourvision.org)

HSB의 hue 색상환을 360도 돌아가며 색을 써보겠습니다. 채도와 명도는 최대치로 설정해 놓겠습니다.

let hueValue = 0;

colorMode(HSB, 360, 255, 255); 

알갱이가 있다 없다 판별하는 조건문의 조건도 미리 변경을 해 놓아야 할 것 같아요.

이전에는, grid[][]의 값이 “0”이면 “없다”, “1”이면 “있다”로 상태를 판별했었는데요.

이제, grid[][]의 값이 0 ~ 360 사이니까, 값이 “0”이면 여전히 “없다”이지만 값이 “0보다 크다”이면 “있다”로 상태를 판별해야 할 것 같아요.

let state = grid[i][j]; //지금 단계 상태 저장~
if (state > 0) { //이 칸이 색칠해져 있다면~~^^*
   let below = grid[i][j+1]; //바로 아래 칸을 찾아서~ 

이제, grid[][]에 HSB 색상 정보를 저장해 보도록 하겠습니다~~^^*

한 스쿱의 <우리의 알갱이>들을 생성할 때 HSB hueValue 색상값을 저장하도록 하겠습니다.

다음 스쿱은 살짝 다른 색상으로 바꾸어 보겠습니다.

그리고 어느 시점에서 hueValue가 360보다 커지면 1로 다시 세팅하겠습니다~


function mouseDragged() {

  let mouseCol = floor(mouseX / resolution);
  let mouseRow = floor(mouseY / resolution);   
 
  let matrix = 2;
  let extent = floor( matrix / 2); 
  for (let i = -extent ; i <= extent ; i++) {
    for (let j = -extent ; j <= extent ; j++) {
      if(random(1) < 0.75) {
       let col = mouseCol + i;
       let row = mouseRow + j; 
       if(col >= 0 && col <= cols-1 && row >= 0 && row <= rows-1) {
         grid[col][row] = hueValue;
       }
      }
     } 
  }
  hueValue += 1;

  if(hueValue > 360) {
    hueValue = 1;
  }
}

이제, <우리의 알갱이> 아래에 있는 알갱이에게 색상을 저장하는 작업을 해보겠습니다~^^*

변수 state에 <우리의 알갱이> grid[i][j]의 색상값이 저장되어 있으니, state를 <아래 알갱이>에 저장하면 될 것 같습니다~

if (below === 0) { //바로 아래 칸이 까맣다면~~^^*
  nextGrid[i][j + 1] = state; //바로 아래 칸을 색칠~^^*
}
else if (belowA === 0) {
//바로 아래 칸은 색칠해져 있지만, 아래A 칸이 까맣다면~~^^*
  nextGrid[i + dir][j+1] = state; //알갱이의 바로 아래A 칸을 색칠~^^*
}
else if (belowB === 0) {
//바로 아래 칸도, 아래A 칸도 색칠해져 있지만, 아래B 칸은 까맣다면~~^^*
  nextGrid[i - dir][j+1] = state; //알갱이의 아래B 칸을 색칠~^^*   
} 
else {
//그렇지 않을 때, 즉, 
//바로 아래 칸도 아래A 칸도 그 아래B 칸도 색칠해져 있거나 
//바로 아래 칸이 존재하지 않을 때 
  nextGrid[i][j] = state; //알갱이의 현재 자리를 색칠~^^*
}

grid[][]에 색을 칠하는 부분도 grid[][]값으로 상태를 판별해서 색칠하는 것으로 살짝 바꾸어 보겠습니다?^^*

이전처럼, grid[][] 상태 판별을 따로 하지 않고, grid[][]의 값에 따라 모두 다 색칠해보니, grid[][]의 값이 “0”인 경우, fill(grid[][], 255, 255);는 fill(0, 255, 255);가 되어 선홍빛 배경이 있는 것처럼 보여요…

background(0); 작업문을 통해 배경을 이미 까맣게 칠하고 시작하기 때문에, grid[][]의 값이 “0”인 경우는 색칠하기 작업을 하지 않아도 검게 보이니까요~~^^*, 우리~~^^* grid[][]의 값이 “0보다 큰” 경우에만 색칠하기로 할까요~~^^*

grid[][]값을 판별해서 “0보다 큰 경우”에만 색칠을 하니 배경이 까맣게 잘 유지되는 것 같아요~~^^*.

 for (let i = 0; i < cols; i++) {
    for (let j = 0; j < rows; j++) {
      let x = i * resolution;
      let y = j * resolution;
      noStroke();
      
      if(grid[i][j] > 0) {
        fill(grid[i][j], 255, 255); 
        square(x, y, resolution);
      }        
    }
  }

오우….준비가 다 된 것 같은데요~~^^*

우리 전체 코드를 살펴 볼까요~~^^*

function make2DArray(cols, rows) {
  let arr = new Array(cols);
  for (let i = 0; i < arr.length; i++) {
    arr[i] = new Array(rows);
    for (let j = 0; j < arr[i].length; j++) {
      arr[i][j] = 0;
    }
  }
  return arr;
  //새까맣게 채워진 모눈 종이를 return합니다. 
}

function mouseDragged() {

  let mouseCol = floor(mouseX / resolution);
  let mouseRow = floor(mouseY / resolution);   
 
  let matrix = 2;
  let extent = floor( matrix / 2); 
  for (let i = -extent ; i <= extent ; i++) {
    for (let j = -extent ; j <= extent ; j++) {
      if(random(1) < 0.75) {
       let col = mouseCol + i;
       let row = mouseRow + j; 
       if(col >= 0 && col <= cols-1 && row >= 0 && row <= rows-1) {
         grid[col][row] = hueValue;
       }
      }
     } 
  }

  hueValue += 1;

  if(hueValue > 360) {
    hueValue = 1;
  }
  
  //마우스가 클릭되면 자동적으로 작동되는 함수입니다~~^^*
  //메인 함수에서 따로 호출할 필요가 없어요~~^^*
  //mouseX, mouseY가 위치하는 화면 위치 좌표를 resoultion으로 나눈 후 그 몫의 정수 부분만 취하면, 해당 위치에 자리한 grid배열의 구성요소를 알 수 있을 것 같아요~^^*
  //마우스의 위치를 중심으로 하는 한스쿱 정사각형 범위 안의, 0.75 확률로 임의적으로 위치좌표들을 찾습니다. 이 x y 위치 좌표들이 화면안에 있는 경우에만, 해당 grid[][] 구성요소에 HSB hulValue를 저장합니다. 
  //메인 함수의 색칠하는 for 구문 안에서 HSB hulValue 색상으로 표현되겠지요~^^* 
  //한 스쿱의 알갱이 색은 동일하고, 다음 스쿱 알갱이 색은 살짝 달라지겠네요~^^*
  //hueValue값이 360보다 커지면 다시 1로 세팅하겠습니다~^^*
} 


let grid;
let cols;
let rows;
let resolution = 10;

let hueValue = 0;

function setup() {
  createCanvas(400, 400);
  colorMode(HSB, 360, 255, 255);
  cols = width / resolution;
  rows = height / resolution;

  grid = make2DArray(cols, rows);
  //지금 단계 까만 모눈 종이 준비~~^^*
  
}

function draw() {
  background(0);
   
  let nextGrid = make2DArray(cols, rows);
  //다음 단계 까만 모눈 종이 준비~~^^*

  for (let i = 0; i < cols; i++){
    for (let j = 0; j < rows; j++) {
      let state = grid[i][j]; //지금 단계 상태 저장~
      if (state > 0) { //이 칸이 색칠해져 있다면~~^^*
        let below = grid[i][j+1]; //바로 아래 칸을 찾아서~
        
        let dir = 1;
        if(random(1) < 0.5) {
          dir *= -1;
        }
        
        let belowA;
        let belowB;
        if ( i + dir >= 0 && i + dir <= cols - 1) {
          belowA = grid[ i + dir ][ j + 1 ];
        }
        if ( i - dir >= 0 && i - dir <= cols - 1) {
          belowB = grid[ i - dir ][ j + 1 ];
        }
        //오른쪽 왼쪽 임의적으로, 위치좌표가 화면 안쪽에 있을 때만, 아래A와 아래B가 grid[][] 구성요소를 저장해요~^^*
        
        
        
        if (below === 0) { //바로 아래 칸이 까맣다면~~^^*
          nextGrid[i][j + 1] = state; //바로 아래 칸 색칠~^^*
        }
        else if (belowA === 0) {
        //바로 아래 칸은 색칠되어 있지만 아래A 칸이 까맣다면~~^^*
          nextGrid[i + dir][j+1] = state; //알갱이의 바로 아래A 칸 색칠~^^*
        }
        else if (belowB === 0) {
        //바로 아래 칸도, 아래A 칸도 색칠되어 있지만, 아래B 칸은 까맣다면~~^^*
         nextGrid[i - dir][j+1] = state; //알갱이의 아래B 칸 색칠~^^*   
        } 
        else {
        //그렇지 않을 때, 즉, 
        //바로 아래 칸도 아래A 칸도 그 아래B 칸도 색칠되어 있거나
        //바래 아래 칸이 존재하지 않을 때 
         nextGrid[i][j] = state; //알갱이의 현재 자리 색칠~^^*
        }
      }
    }
  }
grid = nextGrid; //다음 단계 모눈 종이 상태를 지금 단계 모눈 종이에 저장~

  for (let i = 0; i < cols; i++) {
    for (let j = 0; j < rows; j++) {
      
      let x = i * resolution;
      let y = j * resolution;
      
      noStroke();
      //테두리를 없애겠습니다.
      //컴퓨터의 업무량을 줄여 보겠습니다.
      //컴퓨터의 작업 속도가 빨라지면 좋겠습니다!
      
      if(grid[i][j] > 0) {
      
        fill(grid[i][j], 255, 255); 
        //grid[i][j]에 저장된 Hue 색상값, 채도 최대값, 명도 최대값
      
        square(x, y, resolution);
      }        
    }
  }
  
  //마우스 위치를 중심으로 한 스쿱의 <우리의 알갱이>들이 임의적으로 생성되어 자연스럽고 시원하게 쏟아지나요~^^*
  //빨주노초파남보 예쁜 무지개색 모래 언덕이 쌓이나요~~^^*
}

어여쁜 <우리의 알갱이>들을 더욱 어여쁘게 색칠해 볼까요~~^^* 우리는 메이컵 아티스트~~^^*

오늘 저와 함께 HSB 체계도 공부하고, 어여쁜 <우리의 알갱이>를 빨주노초파남보 일곱빛깔 무지개색으로 더욱 어여쁘게 색칠해 주셔서 감사합니다~~^^*

내일은 <우리의 알갱이>를 좀더 곱게 만들고, 코드도 좀더 다듬어 볼게요~~^^*

와우! 어느새 모래성 쌓기 프로그램의 마무리가 성큼 다가왔네요!

끈기와 호기심과 열정으로 코딩 공부를 함께 해 주셔서 감사합니다~~^^*

아침 시간이 얼마 남지 않았네요…하지만 시간을 충분히 들여 새로운 HSB 체계를 공부한 이른 아침이었기에 보람찬 마음 감사한 마음이예요~~^^*

남은 아침 시간 멋지게 보내시고요! 멋진 하루 보내시고요!

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

네~~^^* 꿈은 이루어 집니다~~^^*

댓글 남기기