Roll It 만들기

Justin Gitlin
Justin Gitlin

Roll It은 휴대전화와 컴퓨터의 브라우저만 사용하여 기존의 보드게임을 재해석한 Chrome 실험입니다. 휴대전화의 브라우저를 사용하면 손목을 튕겨 공을 조준하고 굴릴 수 있으며, 컴퓨터의 브라우저는 WebGL 및 Canvas로 Roll It 레인의 실시간 그래픽을 렌더링합니다. 두 기기는 WebSocket을 통해 통신합니다. 앱 없음 다운로드 항목이 없습니다. 토큰이 없습니다. 최신 브라우저만 있으면 됩니다.

Legwork는 Google Creative Lab의 지시에 따라 사용자 환경, 인터페이스, 게임 환경을 개발한 후 개발 파트너인 Mode Set과 협력하여 Roll It을 빌드했습니다. 프로젝트 기간 동안 여러 가지 고유한 문제가 있었습니다. 이 도움말에서는 Roll It을 완성하는 과정에서 사용한 기법, 발견한 트릭, 얻은 교훈을 살펴봅니다.

3D 워크플로

처음에 가장 어려웠던 점은 소프트웨어의 3D 모델을 웹 지원 파일 형식으로 가져오는 가장 좋은 방법을 찾는 것이었습니다. Cinema 4D 내에서 애셋을 만든 후 모델을 단순화하고 저폴리곤 메시로 변환했습니다. 각 메시에 특정 다각형 선택 태그가 지정되어 색상 지정 및 텍스처링을 위해 객체의 부분을 구분했습니다. 그런 다음 Collada 1.5 (.dae) 파일로 내보내고 오픈소스 3D 프로그램인 Blender로 가져와 three.js와 호환되는 파일을 만들 수 있었습니다. 모델이 올바르게 가져온 것을 확인한 후 메시를 JSON 파일로 내보내고 코드를 사용하여 조명을 적용했습니다. 취한 조치에 대해 자세히 알아보려면 다음을 참고하세요.

C4D 내에서 객체를 모델링합니다. 메시 노멀이 바깥쪽을 향해야 합니다.
C4D 내에서 객체를 모델링합니다. 메시 노멀이 바깥쪽을 향해야 합니다.
다각형 선택 도구를 사용하여 텍스처링할 특정 영역의 선택 태그를 만듭니다. 각 선택 태그에 자료 적용
다각형 선택 도구를 사용하여 텍스처링할 특정 영역의 선택 태그를 만듭니다. 각 선택 태그에 자료 적용
메시를 COLLADA 1.5 .dae 파일로 내보냅니다.
메시를 COLLADA 1.5 .dae 파일로 내보냅니다.
'2D 도형 내보내기'가 선택되어 있는지 확인합니다. 삼각형 내보내기는 일반적으로 코드 측의 3D 환경에서 더 광범위하게 지원되지만 다각형 수가 두 배로 늘어나는 단점이 있습니다. 다각형 수가 많을수록 모델이 컴퓨터의 프로세서에 더 많은 부하를 줍니다. 따라서 성능이 느린 경우 이 체크박스를 선택한 상태로 둡니다.
'2D 도형 내보내기'가 선택되어 있는지 확인합니다. 삼각형 내보내기는 일반적으로 코드 측의 3D 환경에서 더 광범위하게 지원되지만 다각형 수가 두 배로 늘어나는 단점이 있습니다. 다각형 수가 많을수록 모델이 컴퓨터의 프로세서에 더 많은 부하를 줍니다. 따라서 성능이 느린 경우 이 옵션을 선택한 상태로 둡니다.
Collada 파일을 Blender로 가져옵니다.
Collada 파일을 Blender로 가져옵니다.
블렌더로 가져오면 재료와 선택 태그도 함께 가져옵니다.
Blender로 가져오면 재료 및 선택 태그도 함께 가져옵니다.
객체를 선택하고 원하는 대로 객체의 재료를 조정합니다.
객체를 선택하고 원하는 대로 객체의 재료를 조정합니다.
파일을 three.js 파일로 내보냅니다.
웹GL 호환성을 위해 파일을 three.js 파일로 내보냅니다.

코드 작성

Roll It은 오픈소스 라이브러리로 개발되었으며 최신 브라우저에서 기본적으로 실행됩니다. WebGL 및 WebSockets와 같은 기술을 통해 웹이 콘솔 수준의 게임 및 멀티미디어 환경에 점점 가까워지고 있습니다. HTML 개발에 더 많은 최신 도구가 사용 가능해짐에 따라 개발자가 이러한 환경을 쉽고 편하게 빌드할 수 있게 되었습니다.

개발 환경

Roll It의 원본 코드 대부분은 깔끔하고 간결한 언어인 CoffeeScript로 작성되었습니다. 이 언어는 올바른 형식의 린트 처리된 JavaScript로 변환됩니다. CoffeeScript는 뛰어난 상속 모델과 더 깔끔한 범위 처리로 OOP 개발에 적합합니다. CSS는 SASS 프레임워크로 작성되었으며, 이 프레임워크는 개발자에게 프로젝트의 스타일시트를 개선하고 관리하는 데 유용한 여러 도구를 제공합니다. 빌드 프로세스에 이러한 시스템을 추가하려면 설정하는 데 약간의 시간이 걸리지만, 특히 Roll It과 같은 대규모 프로젝트의 경우 그만한 가치가 있습니다. 개발 중에 애셋을 자동으로 컴파일하도록 Ruby on Rails 서버를 설정하여 이러한 모든 컴파일 단계가 투명해졌습니다.

Google은 간소화되고 편안한 코딩 환경을 만드는 것 외에도 사이트를 더 빠르게 로드하기 위해 요청을 최소화하도록 애셋을 수동으로 최적화했습니다. 모든 이미지를 ImageOptimImageAlpha라는 두 가지 압축 프로그램을 통해 실행했습니다. 각 프로그램은 무손실 및 손실이 있는 방식으로 이미지를 최적화합니다. 적절한 설정 조합을 사용하면 이미지의 파일 크기를 크게 줄일 수 있습니다. 이렇게 하면 외부 이미지를 로드할 때 대역폭이 절약될 뿐만 아니라 이미지가 최적화되면 HTML, CSS, JavaScript에 인라인으로 삽입하기 위해 훨씬 더 작은 base64 인코딩된 문자열로 변환됩니다. base64 인코딩에 관해 말하자면, 이 기술을 사용하여 Open Sans WOFF 및 SVG 글꼴 파일을 CSS에 직접 삽입하여 총 요청 수를 줄였습니다.

물리학 지원 3D 장면

THREE.js는 웹용으로 어디서나 사용할 수 있는 3D JavaScript 라이브러리입니다. 하위 수준 3D 수학 및 하드웨어 기반 WebGL 최적화를 래핑하여 평범한 사용자가 맞춤 셰이더를 작성하거나 수동 행렬 변환을 실행하지 않고도 조명이 잘 들어오고 아름다운 대화형 3D 장면을 쉽게 만들 수 있습니다. Physijs는 JavaScript로 변환된 인기 있는 C++ 물리 라이브러리의 THREE.js 전용 래퍼입니다. 이 라이브러리를 활용하여 공이 3D로 목적지 쪽으로 굴러가고, 점프하고, 튀는 것을 시뮬레이션했습니다.

처음부터 볼을 굴리는 실제 경험을 사실적으로 느끼게 할 뿐만 아니라 게임의 객체가 실제처럼 느껴지도록 했습니다. 이를 위해 Physijs 장면의 전반적인 중력, 플레이어의 던지기에서 굴러가는 공의 속도, 레인의 점프 경사, 공과 레인 재료의 마찰 및 회복 (탄력) 속성을 여러 번 조정해야 했습니다. 중력과 속도를 높여 더욱 실감나는 게임 환경을 제공했습니다.

부드럽게 처리

대부분의 최신 브라우저와 비디오 카드 조합은 WebGL 환경에서 기본 하드웨어 기반의 안티앨리어싱을 활용해야 하지만 일부는 제대로 작동하지 않습니다. 안티앨리어싱이 기본적으로 작동하지 않는 경우 THREE.js 장면에서 대비가 강한 날카로운 가장자리가 보기에 좋지 않게 들쭉날쭉해집니다.

다행히 해결 방법이 있습니다. 코드 스니펫을 통해 플랫폼에서 안티앨리어싱을 기본적으로 지원하는지 감지할 수 있습니다. 작동하면 좋습니다. 작동하지 않으면 THREE.js와 함께 제공되는 일련의 후처리 셰이더를 사용하면 됩니다. FXAA 앤티앨리어싱 필터가 여기에 해당합니다. 이 셰이더로 렌더링된 장면을 프레임마다 다시 그리면 일반적으로 선과 가장자리가 훨씬 더 부드럽게 보입니다. 아래 데모를 참고하세요.

// Check for native platform antialias support via the THREE renderer
// from: http://codeflow.org/entries/2013/feb/22/how-to-write-portable-webgl/#antialiasing
var nativeAntialiasSupport = (renderer.context.getParameter(renderer.context.SAMPLES) == 0) ? false : true;

가속도계 기반 게임 컨트롤

Roll It의 매력은 플레이어가 휴대전화로 실행하는 공 굴리기 동작에서 비롯됩니다. 휴대기기는 오래전부터 브라우저 내에서 가속도계에 액세스할 수 있었지만 업계에서는 이제야 웹에서 모션 기반 동작 인식을 모색하기 시작했습니다. 휴대전화의 가속도계에서 제공하는 데이터에 다소 제한이 있지만 약간의 창의력만 있으면 멋진 새로운 환경을 만들 수 있습니다.

Roll It의 기본 '롤' 동작 감지는 창의 deviceorientation 이벤트에서 발생하는 가장 최근의 10개 가속도계 업데이트를 추적하는 것으로 시작됩니다. 이전 기울기 값에서 현재 기울기 값을 빼면 이벤트 간의 각도 변화가 저장됩니다. 그런 다음 마지막 10개의 각도 변화를 지속적으로 합산하여 휴대전화가 공간을 이동할 때 연속 회전을 감지할 수 있습니다. 휴대전화가 스윕 각도 변경의 임곗값을 지나면 롤이 트리거됩니다. 그런 다음 이 스윕에서 가장 큰 단일 기울기 변화량을 찾아 공의 속도를 추정할 수 있습니다. Roll It에서는 각 가속도계 업데이트에 연결된 타임스탬프를 사용하여 이 속도가 표준화됩니다. 이렇게 하면 가속도계 업데이트가 여러 기기의 브라우저로 스트리밍되는 속도의 변동이 완화됩니다.

WebSocket 통신

플레이어가 휴대전화로 공을 굴리면 휴대전화에서 노트북으로 공을 발사하라는 메시지가 전송됩니다. 이 '롤' 메시지는 두 머신 간의 WebSocket 연결을 통해 JSON 데이터 객체를 통해 전송됩니다. JSON 데이터는 작으며 주로 메시지 유형, 던지기 속도, 조준 방향으로 구성됩니다.

{
  "type": "device:ball-thrown",
  "speed": 0.5,
  "aim": 0.1
}

노트북과 휴대전화 간의 모든 통신은 이와 같은 작은 JSON 메시지를 통해 이루어집니다. 게임이 데스크톱에서 상태를 업데이트하거나 사용자가 휴대전화에서 버튼을 기울이거나 탭할 때마다 WebSocket 메시지가 머신 간에 전송됩니다. 이 통신을 간단하고 쉽게 관리할 수 있도록 WebSockets 메시지는 두 브라우저의 단일 종료 지점을 사용하여 브로드캐스트됩니다. 반대로 수신 브라우저에는 단일 진입점이 있으며, 하나의 WebSocket 객체가 양쪽에서 모든 수신 및 발신 메시지를 처리합니다. WebSocket 메시지가 수신되면 JSON 데이터가 jQuery의 trigger() 메서드를 사용하여 JavaScript 앱 내에서 다시 브로드캐스트됩니다. 이 시점에서 수신 데이터는 다른 맞춤 DOM 이벤트와 마찬가지로 작동하며 애플리케이션의 다른 객체에서 선택하여 처리할 수 있습니다.

var websocket = new WebSocket(serverIPAddress);

// rebroadcast incoming WebSocket messages with a global event via jQuery
websocket.onmessage = function(e) {
  if (e.data) {
    var obj = JSON.parse(e.data);
    $(document).trigger(data.type, obj);
  }
};

// broadcast outgoing WebSocket messages by passing in a native .js object
var broadcast = function(obj) {
  websocket.send(JSON.stringify(obj));
};

Roll It의 WebSocket 서버는 두 기기가 게임 코드와 동기화될 때 즉시 생성됩니다. Roll It의 백엔드는 Go를 사용하여 Google Compute EngineApp Engine 플랫폼에 빌드되었습니다.

메뉴 화면 기울이기

게임플레이 중에 사용되는 이벤트 기반 WebSocket 메시지 외에도 Roll It의 메뉴는 휴대전화를 기울이고 버튼을 탭하여 선택을 확인하는 방식으로 제어됩니다. 이를 위해서는 휴대전화에서 노트북으로 전송되는 기울기 데이터 스트림이 더 일관되어야 합니다. 대역폭을 줄이고 불필요한 업데이트를 전송하지 않기 위해 이러한 메시지는 기기의 기울기가 2도 이상 변경된 경우에만 전송됩니다. 휴대전화가 테이블에 평평하게 놓여 있으면 기울기 데이터 스트림을 전송하는 것은 무의미합니다. 전송 속도도 제한됩니다. 기기가 능동적으로 기울어져 있더라도 Roll It에서는 초당 15개 이하의 WebSocket 메시지가 전송됩니다.

컴퓨터에서 기울기 값을 가져오면 requestAnimationFrame를 사용하여 시간이 지남에 따라 보간하여 부드러운 느낌을 유지합니다. 최종 결과는 회전하는 메뉴와 사용자의 선택을 나타내는 데 도움이 되는 굴러가는 공입니다. 휴대전화에서 기울기 데이터를 전송하면 이러한 DOM 요소는 requestAnimationFrame 루프 내에서 CSS 변환을 다시 계산하여 실시간으로 업데이트됩니다. 메뉴의 컨테이너는 단순히 회전하지만 공은 바닥을 따라 굴러가는 것처럼 보입니다. 이 효과를 얻기 위해 공의 x 좌표를 회전과 연결하는 몇 가지 기본 삼각법을 구현합니다. 간단한 방정식은 다음과 같습니다. 회전수 = x / (직경 * π)

마무리

Roll It은 시대의 흐름을 반영합니다. 개발을 지원하는 오픈소스 프로젝트, 책상과 주머니에 있는 기기의 처리 능력, 플랫폼으로서의 웹의 상태를 고려할 때 지금은 공개 웹에 연결되어 혁신적인 변화를 경험할 수 있는 매우 흥미로운 시기입니다. 불과 몇 년 전만 해도 이러한 기술의 대부분은 독점 시스템에만 존재하여 자유롭게 사용하고 배포할 수 없었습니다. 오늘날에는 매일 새로운 퍼즐 조각을 만들고 공유하면서 더 적은 작업과 더 많은 상상력으로 복잡한 환경을 구현할 수 있습니다. 망설이지 마시고 멋진 것을 만들어 전 세계와 공유하세요.

Roll it 로고