오늘은~~^^*
언덕을 쌓는 <우리의 알갱이>들을 더욱 어여쁘게 개선해 보겠습니다~~^^*
나름의 꿈을 안고 나름으로 열심히 사는 존재는 모두다 어여쁜 것 같아요~~^^*
<우리의 알갱이>도 언덕을 쌓기 위해 열심히 내려와서 안착하고 있으니까, 지금 이대로도 그 어여쁨이 잘 느껴지고 있지요~~^^*?
열심히 살기에 이미 어여쁜 <우리의 알갱이>에게 더욱 어여쁜 색깔을 살짝 입혀보도록 할게요~^^*
예쁜 삶 예쁜 마음 예쁜 모습 더욱 빛나게~~^^*
팔레트를 꺼내어서~~ 예쁜 물감들을 짜서~~ 고운 붓으로~~ 이미 어여쁜 <우리의 알갱이>들에게 더욱 어여쁜 색을 입혀 주면 어떨까요~~^^*
네~~!!
오늘은 우리가 메이컵 아티스트~~^^*
어머!
이미 어여쁜 <우리의 알갱이>가 “네 꿈을 마음껏 펼쳐 봐~”
이미 우리를 믿어주는 다정한 목소리와 편안한 얼굴로~^^*
두 눈을 가만히 감고 고개를 살며시 들고 기다리고 있네요~^^*
믿어 주어 고마워요, 이미 어여쁜 <우리의 알갱이>님!
더욱 어여쁜 꿈을 <우리의 알갱이>님 얼굴 위에 펼쳐 볼게요!
먼저, 이미 어여쁜 <우리의 알갱이>님의 자태를 좀더 자연스럽게 다듬어 보겠습니다.
변화가 없고 꼿꼿한데, 얼굴에 색조를 화려하게 넣으면, 마네킨 느낌이 나서 오히려 그로테스크하게 느껴질 수 있을 것 같아요…
내려오는 행동 모습이 좀더 자연스럽도록 개선해 보겠습니다!
한 스쿱 또는 한 스푼에서 쏟아지는 <우리의 알갱이>의 수가 항상 동일하지 않으면, 좀더 자연스러운 흘러내림의 모습이 표현될 것 같아요~^^*
우리가 지정한 크기의 한 스쿱 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 체계를 공부한 이른 아침이었기에 보람찬 마음 감사한 마음이예요~~^^*
남은 아침 시간 멋지게 보내시고요! 멋진 하루 보내시고요!
우리 내일 또 만나요~~^^*
네~~^^* 꿈은 이루어 집니다~~^^*
댓글 남기기