< P5.JS > 중간창작
프로그램적 오류가 만들어 내는 일상의 반복
#01 : 지난 과제 회고하기_이해가 높아진 부분
[회고_과정]
|
update() { this.mouse = createVector(mouseX, mouseY); this.dir = this.mouse.sub(this.pos); this.dir.normalize(); // 왜 벡터 정규화를 시키는 것일까? this.dir.mult(0.5); // 왜 정규화를 시킨 값에 0.5를 곱할까? } |
이 예제의 원리는 ‘( 현재 마우스 위치 값 ) - ( 현재 파티클의 위치 값 ) = 두 거리의 차이 값’을 구하여 가속도 벡터에 넣어 그 값만큼 객체가 움직이게 하는 것.
왜 벡터 정규화를 시키는 것일까? -> ‘normalize()’ 함수는 벡터 값을 0~1 의 값으로 수치를 고정시키는 역할을 한다.
이 정규화 함수를 사용하지 않는다면, 차이 값을 그대로 가속도벡터에 넣기 때문에 움직이는 객체의 모습이 부자연스럽고 매우 빠르게 다가온다.
예제에서는 안정적인 움직임을 표현하기 위해 차이 값을 정규화 함수를 통해 0~1 사이의 값으로 치환한다.
왜 정규화를 시킨 값에 0.5를 곱할까? -> 정확한 차이 값에 0.5를 곱하면 차이 값의 범위가 넓어지기 때문에, 움직이는 객체가 바로 마우스의 위치로 움직이지 않고 넓은 반경을 그리며 다가온다.
정규화의 이유가 항상 궁금했는데, 이처럼 객체의 움직임을 표현하는 것이나, 값의 안정화를 주는 데에 사용되는 것으로도 표현이 된다!
#02 : 지난 과제 회고하기_궁금증에 대한 공부
[회고_과정]
- Static Method 가 무엇인지, 왜 사용하는 것인지 / 수업시간에 나왔지만, 추가적으로 공부가 필요할 것 같아서.. 학습방법 : 구글링, 유튜브 참고주소 : [자바의 정석 - 기초편] ch6-26~29 static메서드와 인스턴스 메서드 - 자바 강의이지만, 기초 개념을 쉽게 잡을 수 있다. : https://mygumi.tistory.com/253 : https://itmining.tistory.com/22?category=640985 - static 장점, 단점 |
클래스의 메소드는 2가지 형태 - 인스턴스 메소드, static 메소드
static 메소드는 무엇인가?
- 클래스의 객체 생성 없이 사용할 수 있는 메소드.
- 유틸리티 함수를 만드는데에 유용하다. -> 밑에서 더 알아보자.
* 유틸리티 함수란?
- p5.vector 의 add, mult 처럼 계산을 간단하게 하기 위해 미리 만들어져있는 라이브러리 함수.
- 인스턴스 메소드 예시 / 수업시간에 자주 사용한 형태
보여지는 모습 : 인스턴스 메소드는 참조변수를 선언하고 참조변수에 인스턴스를 생성하여 ‘참조변수.메소드()’ 형태로 사용한다.
즉, 인스턴스 메소드는 ‘객체를 생성해야 사용 할 수 있는 메소드’ 이다.
- static 메소드 예시
보여지는 모습 : static 메소드는 ‘클래스이름.메소드()’ 의 형태로 호출하여 사용한다.
그리고 정적 메소드를 선언 할 때에도 메소드 앞에 ‘static’ 키워드를 붙인다.
그럼 static 은 언제 붙이는 것일까?
- 정적 메서드는 어떤 특정한 객체가 아닌 클래스에 속한 함수를 구현하고자 할 때 주로 사용된다. -> 이게 유틸리티 함수를 구현할 때 사용하는 것 같아 보인다!
만약 static 메소드가 없었다면,, 여러 계산식이 필요할 때 매번 일일이 인스턴스를 생성하고,
계산식을 만들고,, 매우 불편하지 않았을까..? 생각이 든다..
즉, 정리해보면 static 메소드는 ‘객체 생성없이 사용할 수 있는 메소드’ 이며, 인스턴스를 새로 생성하지 않기 때문에 메모리를 효율적으로 사용 할 수 있게 되어, 유틸리티 함수를 만들 때 유용한 것으로 보인다.
#03 Poetic Movement : 시적인 움직임
[과정_1] 작업의 시작점, 방향성
- 시적 사전적 정의
- 시의 정취(정서)를 가진 것.
- 내가 생각하는 시적이란 무엇일까?
- 일상적인 삶 속에서 작가의 시점으로 발견하는 모든 것들?
- 시는 작가의 상황과 시점에서 발견하는 것을 표현하는 것이라고 생각한다. 그럼 시적이란, 우리가 경험하고 느끼는 것들이 다르기 때문에 각각의 개인에 따라 다른 우리 삶 속에서 나타내는 모든 것들을 시적 이라고 할 수 있지 않을까?
- 내가 요즘 시적이라 생각하는 것 ?
- 우리 삶의 근원을 나타내는 것이 가장 시적이라고 생각하였고, 두 객체 사이에 서로 자극을 주고 받으며 영향을 받는 공진화와 같은 관계들이 현재의 우리 삶의 근원을 나타내는 것들이지 않을까 생각한다.
요즈음 우리 인간에게 가장 큰 영향을 끼치고 있는 것중 하나인 코로나 바이러스를 살펴보면, 인간은 코로나바이러스로부터 스스로를 지키기 위해 백신과 치료제 같은 것을 연구하고, 바이러스는 그것에 대응하여 숙주의 대상인 인간을 잃지 않으려 자가 복제 과정과 스스로 더 강력한 돌연변이의 형태로 만들어 내듯이 두 관계가 밀접하게 영향을 주고 받으며 진화하는 과정을 보여준다.
또 예술과 기술의 관계를 보았을 때에도 기술은 예술의 원천이 되고 예술은 기술에 영감을 준다는 말이 있듯이, 서로 상호작용 하며 끊임없이 진화하는 형태를 띄우고 있다.
이처럼 우리는 과거부터 서로 끊임없이 주고 받는 영향 속에서 도태되지 않기 위해 발전해왔고, 이것의 연속이었기 때문에 주고 받는 관계성이 인간의 삶을 이루고 있는 근원이 되지 않을까? 라는 생각을 했다.
그래서 서로 영향을 주고 받는 두 객체의 떨어질래야 떨어질 수 없는 유기적인 관계성을 시각적 단조로움 으로 나타낸다면, 어떻게 단순하게 나타낼 수 있을까 라는 궁금증에서 작업이 시작되었다.
[과정_2] 시각적 아이디어 스케치
- 기존 아이디어 스케치
작업은 두 객체의 관계성을 표현한다. 정중앙의 원은 나라고 볼 수 있다. 파티클들이 원안에 있을 때에는 느려지다가, 원 밖에 있으면 가속도가 더해진다.
- 작업의 중요한 전환 포인트로 인해 바뀐 새로운 아이디어 스케치
표현하고자 하는 것은 동일하다. 다만, 프로그램 계산 오류가 발생하는 이미지가 의도를 더 잘 표현한다. 파티클들은 정중앙에서 사방으로 퍼져나간다. 하지만, 원을 빠져나가지 못하는 파티클들이 존재하고 아무리 오랜시간이 걸려도 관계의 얽매여 원을 헤매게 된다.
[과정_3] 움직임 1, 2, 3 작업이 내포하는 의미
- 움직임_1 : 벡터로 표현되는 위치 / 속도 / 가속도의 변화
- 위 ‘[과정_1] 작업의 시작점, 방향성’ 에서 밝힌 것처럼, 우리는 하나의 객체인 존재로서 다른 객체와 서로 영향을 주고 받으며 관계를 이루고 있다. 그리고 우리를 이루고 있는 삶은 이 떨어질래야 떨어질 수 없는 상호작용적인 관계의 연속이라 생각하였다.
- 움직임1의 작업에서는 유기적인 관계성을 표현한다. 프로그램의 시작과 동시에 파티클들은 정중앙에서 사방으로 퍼져나간다. 명확하게 명시하지 않은 오류에 의하여 몇개의 파티클은 원을 빠져나가지만, 대부분의 파티클은 원을 빠져나가지 못하고 아무리 오랜시간을 지나도 빠져나가지 못한 파티클들은 관계에 얽매여 원을 헤매게 된다.
- 움직임_2 : 화면의 경계(벽)와 상호작용하며 만들어지는 변화
- 바이러스를 예로 들자면, covid19 바이러스가 앞으로 완전히 종식 되기보다는 독감과 같은 질병이 될 것이라는 예측이 있듯이, 움직임2의 작업에서는 떨어지려고하는 관계여도, 결국에 떨어지지 못하고 주변을 배회하는 강한 관계성을 표현한다.
- 가장 나와 근접한 원이라는 공간을 빠져나간 파티클들이 벽에 부딪혀 다시 그 주변을 맴돌거나, 되돌아오는 모습이 희미하게 보인다.
- 움직임_3 : 마우스, 키보드와 같은 입력장치에 의해 만들어지는 변화
- 움직임3는 색상 값의 움직임이라 볼 수 있다. 마우스를 누르기 전까지 밖에서 맴도는 파티클이 거의 안보이지만, 마우스를 누르면 배경색과 회색 원의 색상이 바뀌는 대비되는 모습을 통해 타인에게는 드러나지 않는 관계임을 나타내기도 한다.
[과정_4] 프로그램 세분화_움직임1_벡터로 표현되는 위치 / 속도 / 가속도의 변화
chk() { let d = dist(this.pos.x, gray_ball.pos.x, this.pos.y, gray_ball.pos.y); if( d >= 175 ) { // 프로그램의 오류로 생각되어지는 부분이다. this.vel.mult(-1); }else{ this.acc.mult(-1); } } |
- 파티클들이 원안에서만 머물게하기 위한 코드로 이루어진 Ball 클래스의 메소드다.
두 점사이의 거리를 측정 할 수 있는 dist 함수를 사용한다. 이 함수를 사용하여 배열로 이루어진 개별의 파티클과 회색 원의 거리가 회색 원의 반지름보다 커질 경우 속도 벡터에 -1을 곱하여, 원을 벗어나지 못하게 한다.
움직임1_결과물
[과정_5] 프로그램 세분화_움직임2_화면의 경계(벽)와 상호작용하며 만들어지는 변화
chkEdge() { if(this.pos.y > height) { this.vel.y *= -1; this.pos.y = height; } if(this.pos.y < 0) { this.vel.y *= -1; this.pos.y = 0; } if(this.pos.x > width) { this.vel.x *= -1; this.pos.x = width; } if(this.pos.x < 0) { this.vel.x *= -1; this.pos.x = 0; } } |
- chkEdge 메소드다. 벽에 닿았을 경우, 방향을 바꾸기 위해 -1 씩 곱한다.
움직임2_결과물
[과정_6] 프로그램 세분화_움직임3_마우스, 키보드와 같은 입력장치에 의해 만들어지는 변화
function mouseClicked() { gray_ball.update(); if(toggle == 0) { toggle = 1; }else if(toggle == 1) { toggle = 0; } } ------------------------------------------------------------- if(toggle==0) { fill(4, 11, 60, 60); }else if(toggle==1) { fill(255); } |
- 토글 변수( flag )를 활용하여 배경색과 회색 원의 색이 변하게 한다.
움직임3_결과물
[과정_7] 작업의 기술적 구현 탐구와 실험 (작업의 중요한 전환 포인트)
- 움직이는 객체가 특정한 영역안에 들어왔을 때 속도, 가속도의 변화를 주고 싶다면 어떻게 해야할까?
- 바탕색과 인식할 영역의 색이 다르니, 색의 인식으로 변화를 줄 수 있을까?
- 움직이는 객체와 특정한 영역의 거리를 측정하면 변화를 줄 수 있을까?
- 거리를 측정하는 함수는 dist 와 mag 함수 두개를 발견했다. dist는 인자 값이 4개, mag함수는 인자값이 2개 mag함수가 더 간편해보인다.
let d = dist(gray_ball.pos.x, ball.pos.x, gray_ball.pos.y, ball.pos.y); |
dist 함수를 이용하여 인식할 영역의 위치 값과 객체의 위치 값의 거리를 계산하였다.
이제 영역 안에서의 객체는 속도가 느려지게 할 것이다.
하지만, 현재 구현하려는 것은 이미 예제 속에 나와있지 않을까..? 라는 생각에 p5.js 사이트를 찾아보니 역시나,, 쉽게 찾아 볼 수 있었다.. (예제)
이상한 오기가 생겨 작업의 방향을 바꾸어 새로운 것으로 작업의도를 담아내고 싶었다. 그래서 여러가지 시도를 해본 결과.. 내가 의도하고자 하는 것을 더 잘 표현해낼 수 있는 시각적 이미지가 나왔다!
의도하지 않은 프로그램 계산 오류가 만들어 내는 이미지이다.
if( d >= 175 ) { this.vel.mult(-1); }else{ this.acc.mult(-1); } |
최종 결과물_
#04 Poetic Movement_with Github ( 추가된 내용 )
[작업_과정_8] 마우스의 입력으로 회색 원의 색이 바뀌는 것을 부드럽게하기.
- 마우스 입력이 들어올 때 반복문을 활용하여, 매 프레임마다 점진적으로 색 변화를 주면 되지 않을까?
- 첫번째 시도
if(toggle_2 == 0) { for(let i=0;i<200;i++) { fill(i); } }else if(toggle_2==1) { for(let i=200;i>0;i--) { fill(i); } } |
for반복문을 활용하여, 매 프레임마다 fill 값이 1씩 증가하게 하였다. 하지만, 구현하고자 하는 모습은 안나온다. fill 값에 투명도를 추가하면 원하는 모습에 근접하지 않을까?
- 두번째 시도
if(toggle_2 == 0) { for(let i=0;i<255;i++) { fill(200, i); } }else if(toggle_2==1) { for(let i=0;i<255;i++) { fill(0, i); } } |
실행은 된다. 하지만, 눈에 띄게 큰 변화는 없다. 아마 첫번째, 두번째 시도 모두 반복문이 수행될 때 너무 빠른 속도이기 때문에 변화가 안보이는 듯 싶다. 이 고민을 해결하기 위해 아두이노 스케치의 ‘delay’ 함수처럼, 잠시 멈추는 함수를 찾아보았지만 image를 지연시키는 함수만 보여진다.
[작업_과정_9] 여러 관계들 속에서 포착하는 마찰들
- 사람과 바이러스, 사람과 자연 등 다양한 관계 속 부딪힘으로 인해 새로운 관계를 형성해나가는 모습을 담아보려한다. 이 부딪힘의 순간들을 어떻게 하면 더 잘 보이게 표현 할까?
- 첫번째 시도
if( d >= 175 ) { fill(255); textSize(15); text('OH_NO', this.pos.x, this.pos.y); this.vel.mult(-1); }else{ this.acc.mult(-1); } |
클래스 볼의 메소드 중 거리를 계산하여 속도를 변화시키는 메소드에 부딪히는 순간 텍스트를 생성하게 하였다. 이것도 좋지만, 좀 더 번뜩이는 듯한 모습을 표현하고 싶다.
다른 시도
if( d >= 175 ) { fill(255); rect(this.pos.x, this.pos.y, 15, 15); this.vel.mult(-1); }else{ this.acc.mult(-1); } |
부딪힐 때마다 흰색 사각형을 생성해주는 것이 내가 표현하고자 하는 부딪힘의 순간들을 잘 표현하는 것 같다.
[작업_과정_10] 마우스에 입력에 따른 작용에 대해 사운드 추가하기
- 부딪히는 모습이 시각적으로만 보이기 때문에, 실제로 부딪힌다는 느낌이 덜할 것 같다. 사운드 요소를 추가하여 보다 더 몰입 할 수 있는 작업이 되었으면 한다.
- 첫번째 시도
if( d >= 175 ) { fill(random(this.colors_2)); // fill(random(200,255)); this.pos_2.x = this.pos.x; this.pos_2.y = this.pos.y; rect(this.pos_2.x, this.pos_2.y, 20, 20); soundFile.setVolume(0.5); soundFile.play(); this.colors = random(255); this.vel.mult(-1); } |
- 실패다.. 부딪힐 때마다 소리를 재생하기 때문에, 매우 지저분한 사운드가 된다.
다른 방법을 생각해보자.
- 다른 시도
function mouseClicked() { soundFile.setVolume(5); soundFile.play(); gray_ball.update(); if(toggle == 0) { toggle = 1; }else if(toggle == 1) { toggle = 0; } } |
공들이 튕기는 순간마다 소리를 재생하는게 아닌, 이번에는 마우스 입력 값이 있을 때만, 한번씩 mp3 파일을 재생하도록했다. 이건 확실히 한번씩 들려주기 때문에 잘 작동한다.
음악 전공을 해왔기에 공튀기는 소리같은 디테일이 필요한 작업을 코드상으로 어떻게 표현해야하는지 더 공부해봐야겠다..
[작업_과정_11] 파티클의 그레이스케일 색변수 추가하기
- 다양한 객체가 모두 동일선상의 관계가 아니기에 파티클의 색 변화를 통해 나타내려한다.
fill 값에 직접 random하게 색을 지정해주어도 되겠지만, 색 변수를 추가하는 것이 직관적이고 계산을 하기에도 효율적이라고 생각했다. 이전에도 책에서 상수를 제외한 수는 변수를 선언해주는 것이 나중에 헷갈리지 않을거라고 본 기억이 난다.
this.colors = 5; if( d >= 175 ) { this.colors = random(255); } |
파티클이 원 중앙과의 거리와 175 이상일 때, 0~255까지의 랜덤한 그레이스케일 값을 가지게 하였다.
[작업_과정_12] rect 색과 벡터 추가하기
- rect 색상도 색상 변수를 새로 선언하고 정의하였다. 색상은 hex color code 7개의 색상으로 지정했다.
- 기존의 rect 는 파티클의 위치 값 vector 을 그대로 사용하였다. 때문에 나중에 rect 에 위치, 속도, 가속도를 변화시키기에 어려움이 있을 것 같았고
이 문제를 해결하기 위해, rect 객체만 사용하는 벡터변수를 새로 선언하고 새 벡터 변수에 파티클의 위치 벡터를 대입하는 방법으로 나중을 위해 생성해놓았다.
if( d >= 175 ) { fill(random(this.colors_2)); this.pos_2.x = this.pos.x; this.pos_2.y = this.pos.y; rect(this.pos_2.x, this.pos_2.y, 20, 20); } |
#05 Github_알게된점
- 생성한 저장소에 파일들이 쌓여 지저분한 것을 정리하고자, ReadMe 파일과 프로젝트 파일을 분리시키기 위해 프로젝트 파일 폴더를 따로 생성한다면, page를 만들 때에도 경로를 프로젝트 파일 폴더로 지정해줘야 한다.
ex) https://ted050505.github.io/Everything-that-makes-up-Life/ProjectFile/
- 이번에 작업을 해보며, 분산버전관리시스템이 왜 필요한지 직접 깨닫게 되었다.. 이것저것 옮기다가 파일이 잘못되거나, 코드가 잘못되었는데 어느부분이 잘못된지 모를 때 깃허브의 이전 버전 기록으로 다시 돌아가 클론해서 복구했다.. 다 사라지는 줄 알았다..
Github_저장소_주소 : https://github.com/ted050505/Everything-that-makes-up-Life
호스팅한 페이지 : https://ted050505.github.io/Everything-that-makes-up-Life/ProjectFile