콘웨이 게임이라고 불리기도하는 인생 게임(Life game)을 아시나요?
1970년 <사이언티픽 아메리칸>에 처음 소개된 게임인데요. 수학자 '존 호튼 콘웨이'가 고안해낸 게임이기에 '콘웨이의 인생 게임'이라고도 부릅니다.
콘웨이의 인생 게임
이 게임의 규칙 간단합니다. 바둑판 같은 수많은 칸이 있고, 칸에 색이 칠해져있다면 살아있는 세포(Cell)이며 색이 없다면 죽은 세포입니다. 게임을 시작하면 처음 임의 칸 몇 개가 검은색으로 칠해져있고 이 1세대 세포가 규칙에 따라 다음 세대 세포로 태어나거나 죽습니다. 이 과정에서 세포는 전혀 예상치 못한 결과로 이어지기도하며 일정한 패턴을 만들기도 합니다. 자세한 규칙은 생략하고 어떤 게임인지 영상을 첨부하도록 하겠습니다.
콘웨이 게임에서 찾은 의미
콘웨이 게임은 단순간 게임을 넘어 다양한 의미로 해석되는데요. 자아복제, 삶과 죽음, 인공지능, 불완전성 원리 등과 이어지기도 합니다. 저는 그 중에서도 인류 또는 우주의 시뮬레이션과 유사하다고 느꼈습니다. 처음 게임이 시작될 때 세포가 빠르게 번식하며 화면을 모두 채울 듯이 많아졌다가 갑자기 개체 수가 줄어들다가 소멸하기도 하며 번식을 중단하고 일정 패턴만 반복하기도 합니다. 이 과정을 지켜보고 있자면 짧은 시간에 이 작은 세계의 흥망성쇠가 반복된다는 느낌을 받을 수 있습니다. 그래서 과장해서 빗대어 게임 한 번에 인류의 탄생부터 종말까지의 시뮬레이션이지 않나 싶었습니다.
급 궁금해진, 콘웨이 게임이 만들어 내는 소리
혼자 이런 망상을 하다가 그렇다면 이 인류의 탄생과 종말이 내는 소리는 어떠할지 너무 궁금해졌습니다. 그래서 다음과 같이 조금 구상해봤습니다.
1. Cell에 각각 번호를 부여한다.
2. Cell에 색이 칠해진다면(세포가 살아난다면) 해당 Cell의 번호의 헤르츠(hz)를 오디오로 출력한다.
개발 시작
1. 콘웨이 게임 공수
우선 콘웨이 게임을 깃허브에 검색해서 자바스크립트로 구성된 프로젝트를 하나 clone 받았습니다. 참고로 아래 링크인데 여러 언어로 콘웨이 게임을 만든 것을 보고 감탄했습니다.
https://github.com/conwaysgame
2. Audio 객체 생성
찾아보니 window 기능에 오디오 기능을 사용할 수 있는 API가 있었습니다.
const audioContext = new window.AudioContext()
이 API에는 파형 타입, 볼륨 설정, 주파수 설정, 소리 재생과 같은 기능을 제공하더라고요. 딱 제가 필요한 기능들로 구성되어있었습니다.
export function playSounds(frequency, duration) {
const oscillator = audioContext.createOscillator();
oscillator.type = "sine"; //파형 설정
oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime); // 주파수 설정
// 초기 볼륨 설정, 혹시 몰라 0.01 굉장히 작게 설정했음.
const gainNode = audioContext.createGain();
gainNode.gain.setValueAtTime(0.01, audioContext.currentTime);
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
// 소리 재생 시작
oscillator.start();
// 소리 재생 중지
setTimeout(() => {
oscillator.stop();
}, duration);
}
3. 각 Cell 번호 부여
하나의 Cell 컴포넌트가 반복문으로 구현되었기 때문에 간단하게 id에 props로 넘겨받은 index 값을 매겨주었습니다.
4. Cell에 색이 칠해질 때 Audio 함수 실행
Cell에 색이 칠해지는 원리는 'background color: black' css 속성을 가진 class 명(아래 사진에서는 'populated')을 동적받는 것입니다. 이 class 명은 부모 컴포넌트로 부터 props로 받습니다. 그래서 간단하게 조건문으로 props를 받을 때 Audio 함수를 실행했습니다.
// 검은색이 칠해질 때 함수 발동, 소리가 정말 많이 겹치기 때문에 0.1초 아주 짧게 소리가 나도록 설정했음
if (props.populated) {
playSounds(props.num, 100);
}
1차 결과물
아주 기괴한 소리를 냅니다..ㅋㅋㅋ
5. 문제점 & 디벨롭
오디오 객체 생성 문제
처음 오디오를 입히고 실행했을 때 엄청난 과부하가 일어나서 CPU가 미친 듯이 뛰었습니다. 알고보니 소리 재생 함수가 실행될 때마다 Audio 객체를 생성했기 때문이었습니다. 당장 새로운 조건문을 추가한 오디오 생성하는 함수를 따로 만들었습니다.
function createAudioContext() {
if (!window.AudioContext) {
throw new Error("not supported in this browser");
}
//오디오 콘텍스트가 없을 때만 생성
if (!audioContext) {
audioContext = new window.AudioContext();
}
}
더 다이내믹한 음역대(?)를 위해 주파수 간격 up
주파수 대역은 2만대까지도 사용할 수 있는데 Cell 개수는 400개였기 0~400hz만 출력하는 부분이 너무 아쉬웠습니다. 그래서 hz에 곱셈을 추가해 더 다이내믹한 주파수 출력을 구현했습니다.
playSounds(this.props.num * 2, 100);
파형 Change 기능 추가
window.AudioContext 에는 파형 타입을 설정할 수 있는 부분이 있더라고요. 아 이거 재밌겠다 싶어서 파형을 바꾸는 기능을 추가했습니다.
// 총 4가지 종류의 파형
this.soundType = ["sine", "square", "sawtooth", "triangle"];
changeSoundType() {
this.currentIndex = (this.currentIndex + 1) % this.soundType.length;
this.currentSound = this.soundType[this.currentIndex];
}
최종본
아 이게 인생 시뮬레이션, 세포 분열의 소리구나~ 하고 들으면 신비롭습니다. ㅋㅋ
간만에 재밌는 작업이었습니다.
프로젝트 github 주소
https://github.com/MadHeo/conway-sounds
참고 자료
책
- 행복한 프로그래밍, 임백준
유튜브
- 당신이 수학을 모르는 이유.(feat.불완전성의 원리)
- Inventing Game of Life(John Conway) - Numberphil
블로그
- https://curryyou.tistory.com/453
'프로그래밍⚡️ > 기타 등등' 카테고리의 다른 글
커서(Cursor) IDE 사용기 (0) | 2024.09.25 |
---|---|
npm 라이브러리 등록하기, 오픈소스에 기여해 봤습니다 (2) | 2024.05.25 |
피그마 variables 활용 및 토큰화 하기 (0) | 2024.04.27 |
오픈소스는 과연 혁명일까? 오픈소스의 역사와 평가 (0) | 2023.04.26 |
효율적인 업무 분배를 위한 Jira 태스크 관리 (1) | 2023.03.22 |