우수사례 - 스타니스와프 렘 Google 기념일 로고 제작

Marcin Wichary
Marcin Wichary

안녕, 이상한 세상

Google 홈페이지는 코딩을 할 수 있는 매력적인 환경입니다. 여기에는 많은 까다로운 제한사항이 수반됩니다. 특히 속도와 지연 시간에 초점을 맞추고 모든 종류의 브라우저를 지원하고 다양한 상황에서 작동해야 하며 놀라움과 즐거움을 선사해야 합니다.

지금은 Google 로고를 대체하는 특별한 삽화인 Google 기념일 로고를 소개합니다. 펜과 붓과 맺은 관계는 저속 명령이라는 독특한 맛을 오랫동안 가지고 있었지만, 나는 종종 상호 작용에 기여합니다.

제가 코딩한 상호작용형 기념일 로고 (팩맨, 쥘 베른, 세계 박람회)와 제가 도운 많은 작품은 모두 미래 지향적이고 역동적이었습니다. 최첨단 웹 기능을 하늘에 담을 수 있는 애플리케이션도 있고, 브라우저 간 호환성의 실용성도 엿볼 수 있죠.

우리는 각각의 인터랙티브 기념일 로고에서 많은 것을 배웁니다. 최근 스타니스와프 렘 미니 게임도 예외가 아니었습니다. 기념일 로고 역사상 처음으로 17,000줄의 JavaScript 코드로 많은 시도를 해왔습니다. 오늘 이 코드를 여러분과 공유하고자 합니다. 흥미로운 내용을 찾거나 제 실수를 지적할 수 있을 것입니다.

스타니스와프 렘 기념일 로고 코드 보기 »

Google의 홈페이지는 기술 데모를 위한 공간이 아니라는 점을 명심할 필요가 있습니다. Google은 기념일 로고를 통해 특정 인물과 사건을 기념하고 최고의 예술과 최고의 기술을 사용하여 이를 기념하고자 합니다. 그러나 기술만을 위해 기술을 찬양해서는 안 됩니다. 즉, 널리 알려진 HTML5에서 사용 가능한 부분이 무엇이든 신중히 살펴보고, 주의를 분산시키거나 덮지 않고 기념일 로고를 더 잘 만드는 데 도움이 되는지 확인해야 합니다.

이제 스타니스와프 렘 기념일 로고에서 그 자리를 찾은 최신 웹 기술 몇 가지와 그렇지 못한 기술 몇 가지를 살펴보겠습니다.

DOM 및 캔버스를 통한 그래픽

캔버스는 우리가 이 기념일 로고에서 하고 싶었던 그런 작업을 할 수 있도록 강력하게 만들어졌습니다. 하지만 우리가 중요하게 여기는 일부 이전 브라우저는 이를 지원하지 않습니다. 저는 말 그대로 뛰어난 추출성을 만들어낸 사람과 사무실을 공유하고 있지만, 다른 방법을 선택하기로 했습니다.

'rects'라고 하는 그래픽 프리미티브를 추상화하는 그래픽 엔진을 만든 다음 캔버스를 사용할 수 없는 경우 DOM을 사용하여 렌더링합니다.

이 접근 방식에는 몇 가지 흥미로운 어려움이 있습니다. 예를 들어 DOM에서 객체를 이동하거나 변경하면 즉각적인 결과가 발생하는 반면, 캔버스의 경우 모든 것이 동시에 그려지는 특정한 순간이 있습니다. 캔버스를 하나만 사용하고 지우고 프레임마다 처음부터 그립니다. 한 손으로는 말 그대로 움직이는 부품이 너무 많고, 다른 한편으로는 겹치는 여러 캔버스로 분할하고 선택적으로 업데이트할 만큼 복잡성이 충분하지 않습니다.)

안타깝게도 캔버스로 전환하는 것은 drawImage()로 CSS 배경을 미러링하는 것만큼 간단하지 않습니다. 가장 중요한 것은 Z-색인 및 마우스 이벤트의 레이어링, DOM을 통해 항목을 조합할 때 무료로 제공되는 많은 기능을 잃게 됩니다.

저는 이미 '비행기'라는 개념으로 Z-색인을 추출했습니다. 기념일 로고는 여러 개의 평면을 정의했습니다. 기념일 로고는 먼 하늘에서부터 모든 사물 앞에 있는 마우스 포인터까지 여러 개의 평면을 정의했으며, 기념일 로고의 모든 배우는 자신이 비행기 중 어느 것에 속하는지 결정해야 했습니다 (평면 내에서의 미세한 플러스/마이너스 수정은 planeCorrection를 사용하여 가능함).

DOM을 통해 렌더링되기 때문에 평면은 단순히 Z-색인으로 변환됩니다. 하지만 캔버스를 통해 렌더링하는 경우 그리기 전에 평면을 기준으로 직사각형을 정렬해야 합니다. 매번 이 작업을 수행하려면 비용이 많이 들기 때문에 배우가 추가되거나 다른 평면으로 이동할 때만 순서가 다시 계산됩니다.

마우스 이벤트의 경우 이것도 추상화했습니다. 일종의 DOM과 캔버스 모두 Z-색인이 높은 완전히 투명한 플로팅 DOM 요소를 추가로 사용했습니다. 이 요소는 마우스 오버/아웃, 클릭 및 탭에만 반응하는 기능입니다.

이 기념일 로고에서 시도하고자 했던 것 중 하나는 제4의 벽을 허무는 것이었습니다. 위의 엔진을 사용하여 캔버스 기반 액터와 DOM 기반 액터를 결합할 수 있었습니다. 예를 들어 피날레에서 폭발 장면은 우주 객체의 경우 캔버스에, 나머지 Google 홈페이지의 경우 DOM에 있습니다. 보통 다른 배우처럼 들쭉날쭉한 가면으로 날아다니는 이 새는 촬영 단계에서 문제가 생기지 않도록 하기로 하고 I’m Feeling Lucky 버튼에 앉습니다. 이렇게 하면 새가 캔버스를 떠나 DOM 요소가 되고 나중에는 DOM 요소가 됩니다. 방문자에게 완전히 투명하게 공개되기를 바랐습니다.

프레임 속도

현재 프레임 속도를 파악하고 속도가 너무 느릴 때 (너무 빠를 때) 대응하는 것도 엔진의 중요한 부분이었습니다. 브라우저는 프레임 속도를 다시 보고하지 않으므로 Google에서 직접 계산해야 합니다.

처음에는 requestAnimationFrame을 사용했으며, 전자를 사용할 수 없다면 구식 setTimeout로 대체합니다. requestAnimationFrame는 경우에 따라 CPU를 교묘하게 절약합니다. 일부 작업은 아래 설명과 같이 직접 실행하지만, setTimeout보다 높은 프레임 속도를 얻을 수도 있습니다.

현재 프레임 속도 계산은 간단하지만 급격한 변화가 있을 수 있습니다. 예를 들어 다른 애플리케이션이 한동안 컴퓨터를 차지하면 속도가 빠르게 떨어질 수 있습니다. 따라서 100개의 실제 틱에서만 '롤링'(평균) 프레임 속도를 계산하고 이를 기반으로 결정을 내립니다.

어떤 종류의 결정일까요?

  • 프레임 속도가 60fps보다 높으면 속도를 제한합니다. 현재 일부 Firefox 버전의 requestAnimationFrame에는 프레임 속도의 상한이 없으므로 CPU를 낭비할 필요가 없습니다. 다른 브라우저에서는 프레임 속도가 60fps보다 약간 더 높아지게 하는 반올림 오차가 있기 때문에 실제로는 65fps로 제한한다는 점에 유의하세요. 실수로 제한을 시작하는 일이 있어서는 안 됩니다.

  • 프레임 속도가 10fps보다 낮으면 프레임을 드롭하는 대신 엔진 속도가 느려집니다. 손실을 끼치는 제안이기는 하지만 프레임을 과도하게 건너뛰는 것이 그저 느리면서도 일관성 있는 게임을 하는 것보다 더 혼란스러울 것이라고 생각했습니다. 거기에 또 다른 부작용이 있습니다. 시스템이 일시적으로 느려지는 경우 엔진이 급하게 따라잡을 때 사용자가 이상하게 앞으로 뛰지 않게 된다는 것입니다. (팩맨에서 약간 다르게 실행했지만 최소 프레임 속도가 더 나은 접근 방식입니다.)

  • 마지막으로 프레임 속도가 위험하게 낮아지면 그래픽을 단순화하는 것을 생각할 수 있습니다. 마우스 포인터를 제외하고 Lem 기념일 로고에 이 작업을 하지는 않지만, 느린 컴퓨터에서도 기념일 로고가 유동적으로 느껴지도록 일부 불필요한 애니메이션을 잃을 수 있다는 가설이 있습니다.

물리적 틱과 논리적 틱이라는 개념도 있습니다. 전자는 requestAnimationFrame/setTimeout에서 비롯됩니다. 일반 게임플레이의 비율은 1:1이지만 빨리 감기의 경우 물리적 틱당 논리적 틱을 더 많이 추가합니다 (최대 1:5). 이렇게 하면 모든 논리적 틱에 필요한 모든 계산을 실행할 수 있지만 마지막 틱만 화면의 항목을 업데이트하는 것으로 지정합니다.

벤치마킹

캔버스를 사용할 수 있을 때마다 캔버스가 DOM보다 빠르다고 가정할 수 있습니다 (실제로 초기에는 가능함). 항상 그렇지는 않습니다. 테스트하는 동안 DOM 요소를 이동할 때 실제로 Mac의 Opera 10.0~10.1과 Linux의 Firefox가 더 빠른 것으로 확인되었습니다.

완벽한 환경에서는 DOM 요소가 style.leftstyle.top를 사용하여 이동하고 캔버스에 그려지고 DOM 요소가 CSS3 변환을 사용하여 이동하는 등 다양한 그래픽 기법을 조용히 벤치마킹합니다.

가장 높은 프레임 속도를 제공하는 것으로 전환할 수 있습니다. 이를 위한 코드를 작성하기 시작했지만, 적어도 벤치마킹 방식은 상당히 신뢰할 수 없고 많은 시간이 필요하다는 것을 알게 되었습니다. 시간이 없습니다. Google은 속도에 매우 중점을 두며, 사용자가 클릭하거나 탭하면 바로 기념일 로고가 나타나기를 원합니다.

결국 웹 개발은 때로는 해야 할 일을 해야 하는 문제로 귀결될 때가 있습니다. 저는 아무도 보지 않는지 확인하기 위해 어깨 뒤를 돌아본 다음 Opera 10과 Firefox를 캔버스에서 하드코딩했습니다. 다음 시간에는 <marquee> 태그로 돌아올 것입니다.

CPU 절약

집에 찾아온 친구가 브레이킹 배드의 시즌 피날레를 보고 망치고 DVR에서 삭제한다는 사실을 아시나요? 그런 녀석이 되고 싶지 않지, 안 그래?

네, 사상 최악의 비유입니다. 하지만 우리의 낙서도 그런 사람이 되기를 바라서는 안 됩니다. 다른 사람의 브라우저 탭에 들어갈 수 있는 사실은 권한이며, CPU 사이클을 축적하거나 사용자의 주의를 산만하게 하는 것은 우리를 불쾌한 손님으로 만들 수 있습니다. 따라서 탭, 마우스 클릭, 마우스 움직임, 키 누름 없이 기념일 로고를 사용하는 사람이 없다면 결국에는 절전 모드로 전환해야 합니다.

시기

  • 홈페이지에서 18초 후 (아케이드 게임을 어텐션 모드라고 함)
  • 탭에 포커스가 있는 경우 180초 후
  • 탭에 포커스가 없는 경우 30초 후 (예: 사용자가 다른 창으로 전환했지만 아직 비활성 탭에서 기념일 로고를 보고 있는 경우)
  • 즉시 탭이 보이지 않게 되면 (예: 사용자가 같은 창에서 다른 탭으로 전환한 경우 – 볼 수 없더라도 사이클을 낭비할 필요가 없음)

현재 탭에 포커스가 있는지 어떻게 알 수 있나요? window.focuswindow.blur에 연결합니다. 탭이 표시되는지 어떻게 알 수 있을까요? 새로운 Page Visibility API를 사용하여 적절한 이벤트에 반응합니다.

위의 타임아웃은 평소보다 더 관대합니다. 저는 주로 하늘과 새처럼 잔잔한 애니메이션이 많이 적용된 이 특정 기념일 로고에 맞춰 애니메이션을 적용했습니다. 이상적으로는 타임아웃이 게임 내 상호작용에 따라 제한되는 것입니다. 예를 들어 새가 착륙 직후에 이제 잠들 수 있다고 다시 기념일 로고에 보고할 수 있지만, 나는 결국 그것을 구현하지 않았습니다.

하늘은 항상 움직이기 때문에 잠에 들고 잠에서 깨면 낙서가 멈추거나 시작되는 것이 아니라 잠시 멈추기 전에 속도가 느려지며, 필요에 따라 물리적 틱당 논리 틱의 수를 다시 시작, 증가 또는 줄이는 경우에도 마찬가지입니다.

전환, 변환, 이벤트

HTML의 강점 중 하나는 개발자가 스스로 더 잘 만들 수 있다는 사실입니다. 일반적인 HTML 및 CSS 포트폴리오에 문제가 있으면 자바스크립트를 랭글링하여 이를 확장할 수 있습니다. 하지만 안타깝게도 처음부터 다시 시작해야 하는 경우도 있습니다. CSS3 전환은 매우 유용하지만, 새 전환 유형을 추가하거나 전환을 사용하여 요소 스타일 지정 이외의 다른 작업을 할 수는 없습니다. 또 다른 예: CSS3 변환은 DOM에 적합하지만, 캔버스로 이동하면 갑자기 직접 작업을 수행하게 됩니다.

이러한 문제를 비롯한 여러 가지 이유로 Lem Doodle에 자체 전환 및 변환 엔진이 있습니다. 네, 2000년대에 개발된 기능은 CSS3만큼 강력하지 않습니다. 하지만 엔진이 어떤 작업을 하든 일관성 있게 작동하고 훨씬 더 많은 제어 기능을 제공합니다.

간단한 작업(이벤트) 시스템부터 시작했습니다. 이 타임라인은 setTimeout를 사용하지 않고 향후에 이벤트를 실행하는 타임라인입니다. 어느 시점에서든 그리기 시간이 더 빨라지거나 (빨리 감거나), 느려지거나(낮은 프레임 속도 또는 CPU를 절약하기 위해 절전 모드로 전환됨) 완전히 중지됨(이미지 로드가 완료될 때까지 대기)에 따라 물리적 시간과 분리될 수 있기 때문입니다.

전환은 단지 또 다른 유형의 작업입니다. 기본적인 이동 및 회전 외에도 상대적 이동 (예: 오른쪽으로 10픽셀 이동), 흔들림과 같은 맞춤 기능은 물론 키프레임 이미지 애니메이션도 지원합니다.

회전을 언급했는데 수동으로 해야 한다는 것입니다. 회전해야 하는 객체에 대해 다양한 각도의 스프라이트가 있습니다. 주된 이유는 CSS3와 캔버스 회전 모두 허용되지 않는 시각적 아티팩트를 도입했기 때문입니다. 게다가 이러한 아티팩트는 플랫폼마다 달랐습니다.

회전하는 물체가 다른 회전하는 물체에 부착되어 있다는 점을 감안하면 로봇의 손이 아래팔에 연결되어 있고, 로봇의 손은 회전하는 상완에 부착되어 있으므로, 가난한 사람의 변환 원점을 피벗 형태로 만들어야 했습니다.

이 모든 작업은 궁극적으로 HTML5를 통해 처리되고 있는 토대를 궁극적으로 처리하는 견고한 작업입니다. 하지만 기본 지원만으로는 충분하지 않은 경우가 있습니다. 이제 필요한 부분을 재창조할 때입니다.

이미지 및 스프라이트 처리

엔진은 기념일 로고를 실행하는 데서 그치지 않고 작업용이기도 합니다. 위에서 몇 가지 디버그 매개변수를 공유했습니다. 나머지는 engine.readDebugParams에서 확인할 수 있습니다.

스프라이트는 잘 알려진 기법으로, 기념일 로고에도 사용합니다. 이를 통해 바이트를 절약하고 로드 시간을 줄일 수 있으며 미리 로드하기가 더 쉬워집니다. 하지만 이로 인해 개발이 어려워질 수도 있습니다. 이미지를 변경할 때마다 재스프라이트를 수행해야 합니다 (대체로 자동화되었지만 여전히 번거롭기 때문). 따라서 엔진은 개발을 위한 원시 이미지와 engine.useSprites를 통한 프로덕션을 위한 스프라이트에서 실행을 지원합니다. 둘 다 소스 코드에 포함됩니다.

팩맨 기념일 로고
팩맨 기념일 로고에서 사용하는 스프라이트

또한 진행 과정에서 이미지를 미리 로드하고 이미지가 제때 로드되지 않으면 낙서가 중지되도록 하는 기능도 지원합니다. 이때 가짜 진행률 표시줄을 사용하세요. 안타깝지만 HTML5도 이미 로드된 이미지 파일의 양을 알려줄 수 없기 때문입니다.

고정된 진행률 표시줄이 있는 그래픽 로드 스크린샷
진행률 표시줄이 표시된 로드 그래픽의 스크린샷

일부 장면에서는 병렬 연결을 사용하여 로드 속도를 높이기 위해 두 개 이상의 스프라이트를 사용하지만 단순히 iOS 이미지의 경우 3/5백만 픽셀 제한 때문입니다.

HTML5를 어떻게 활용할 수 있을까요? 위에서 그 내용은 많지 않지만 스프라이트/자르기를 위해 작성한 도구는 캔버스, blob, a[다운로드] 등 완전히 새로운 웹 기술입니다. HTML의 한 가지 흥미로운 점 중 하나는 이전에 브라우저 외부에서 실행해야 했던 작업을 천천히 포함한다는 점입니다. 여기서 필요한 부분은 PNG 파일을 최적화하는 것이었습니다.

게임 사이에 상태 저장

Lem의 세상은 항상 크고 생동감 있고 사실적이었습니다. 그의 이야기는 일반적으로 설명의 측면에서 별다른 내용 없이 시작되었으며, 첫 번째 페이지는 미디어에서 시작하는데, 독자가 페이지를 찾아야 했습니다.

Cyberiad도 예외는 아니었고, Google은 기념일 로고에서도 그 느낌을 그대로 재현하고자 했습니다. 먼저 스토리를 과도하게 설명하지 않도록 노력해야 합니다. 또 다른 중요한 부분은 도서 우주의 역학적 특성에 적합한 무작위 순서 지정입니다. 여기에는 수많은 위치에서 사용하는 임의성을 처리하는 도우미 함수가 많이 있습니다.

또한 다른 방식으로도 리플레이 가능성을 높이고자 했습니다. 그러기 위해서는 기념일 로고가 이전에 몇 번이나 완성되었는지 알아야 했습니다. 지금까지 올바른 기술 솔루션은 쿠키이지만 Google 홈페이지에서는 작동하지 않습니다. 모든 쿠키는 모든 페이지의 페이로드를 증가시키며, Google은 속도와 지연 시간에 많은 관심을 가집니다.

다행히 HTML5는 사용이 간편한 웹 저장소를 제공하므로 일반적인 재생 횟수와 사용자가 재생한 마지막 장면을 저장하고 회수할 수 있습니다. 또한 쿠키가 허용하는 것보다 훨씬 더 세련되었습니다.

이 정보는 어디에 사용되나요?

  • 사용자가 이전에 본 컷신을 건너뛸 수 있는 빨리 감기 버튼을 표시합니다.
  • 피날레에서는 서로 다른 N 항목이 표시됩니다.
  • 슈팅 난이도를 약간 높이고
  • 세 번째 및 후속 희곡에 다른 이야기의 이스터 에그 드래곤이 나옵니다.

이를 제어하는 여러 디버그 매개변수가 있습니다.

  • ?doodle-debug&doodle-first-run – 처음 실행하는 것으로 가장합니다.
  • ?doodle-debug&doodle-second-run – 두 번째 실행이라고 가정해 보겠습니다.
  • ?doodle-debug&doodle-old-run – 오래된 실행이라고 가정해 보겠습니다.

터치 기기

우리는 터치 기기에서도 편안함을 느낄 수 있는 기념일 로고를 만들고자 했습니다. 가장 현대적인 기념일 로고는 매우 강력해서, 기념일 로고도 정말 잘 실행될 수 있으며, 탭하여 게임을 경험하는 것이 클릭하는 것보다 훨씬 더 재미있습니다.

사용자 환경을 미리 변경해야 했습니다. 원래 마우스 포인터는 컷신과 비대화형 부분이 진행되고 있음을 전달한 유일한 장소였습니다. 나중에 오른쪽 하단에 작은 표시기를 추가했기 때문에 (터치 기기에 없는) 마우스 포인터에만 의존할 필요가 없었습니다.

일반 붐빔 클릭 가능 클릭함
작업 진행 중
진행 중인 일반 포인터
진행 중인 작업 중 포인터
작업 진행 중인 클릭 가능한 포인터
진행 중인 작업 클릭 포인터
최종
최종 일반 포인터v
최종 통화 중 포인터
최종 클릭 가능한 포인터
마지막으로 클릭된 포인터
개발 중 마우스 포인터 및 최종적으로 상응하는 항목입니다.

대부분의 작업은 상자에서 나왔습니다. 그러나 터치 환경의 빠른 즉석 사용성 테스트에서는 두 가지 문제가 나타났습니다. 즉, 일부 타겟을 누르기가 너무 어렵고 마우스 클릭 이벤트를 재정의했기 때문에 빠른 탭은 무시되었습니다.

클릭 가능한 투명 DOM 요소가 별도로 있는 것이 이 작업에 큰 도움이 되었습니다. 시각적 요소에 관계없이 크기를 조절할 수 있기 때문입니다. 터치 기기를 위한 추가 15픽셀 패딩을 도입하여 클릭 가능한 요소가 생성될 때마다 사용했습니다. (단, 피츠 선생님이 만족할 수 있도록 마우스 환경을 위한 5픽셀 패딩을 추가했습니다.)

다른 문제의 경우 마우스 클릭에 의존하지 않고 적절한 터치 시작 및 종료 핸들러를 연결하고 테스트했습니다.

또한 WebKit 브라우저가 기본적으로 추가하는 일부 터치 기능 (강조표시 탭, 콜아웃 탭)을 삭제하기 위해 더 현대적인 스타일의 속성을 사용하고 있습니다.

기념일 로고를 실행하는 특정 기기가 터치를 지원하는지 어떻게 감지하나요? 천천히. 우선 순위를 파악하는 대신 통합 IQ를 사용하여 기기가 터치를 지원한다는 점을 공제했습니다... 첫 번째 터치 시작 이벤트를 얻은 후입니다.

마우스 포인터 맞춤설정

하지만 모든 것이 터치 기반인 것은 아닙니다. Google의 기본 원칙 중 하나는 기념일 로고의 세계 내에서 가능한 한 많은 것을 넣는 것이었습니다. 작은 사이드바 UI (빨리 감기, 물음표), 도움말, 마우스 포인터 등이 있습니다.

마우스 포인터를 맞춤설정하는 방법 일부 브라우저에서는 맞춤형 이미지 파일에 연결하여 마우스 커서를 변경할 수 있습니다. 하지만 이는 제대로 지원되지 않으며 다소 제한적이기도 합니다.

그렇지 않다면 어떻게 해야 할까요? 마우스 포인터를 기념일 로고의 다른 배우로 만들어 보는 건 어떨까요? 이는 효과적이지만 몇 가지 주의할 사항이 있습니다. 주로 다음과 같습니다.

  • 기본 마우스 포인터를 삭제하고
  • 마우스 포인터를 '실제' 포인터와 동기화할 수 있어야 합니다.

전자는 까다롭습니다. CSS3는 cursor: none를 허용하지만 일부 브라우저에서는 지원되지 않습니다. 여기서는 빈 .cur 파일을 대체로 사용하거나, 일부 브라우저의 구체적인 동작을 지정하거나, 경험에서 다른 브라우저를 하드 코딩하는 등 몇 가지 체조를 활용해야 했습니다.

다른 하나는 면이 비교적 사소하지만 마우스 포인터가 낙서 세계의 또 다른 부분이므로 모든 문제도 상속됩니다. 가장 큰 것은 무엇입니까? 기념일 로고의 프레임 속도가 낮으면 마우스 포인터의 프레임 속도도 낮아집니다. 이는 손의 자연스러운 연장으로서 마우스 포인터가 어떤 경우에도 반응성을 유지해야 하기 때문에 심각한 결과를 초래합니다. (과거에 Commodore Amiga를 사용했던 사람들은 이제 격렬하게 고개를 끄덕이고 있습니다.)

이 문제에 관한 다소 복잡한 해결책 중 하나는 일반 업데이트 루프에서 마우스 포인터를 분리하는 것입니다. 그저 잠을 자지 않아도 되는 대체 세상에서 그랬죠. 이 문제를 더 간단하게 해결할 수 있을까요? 롤링 프레임 속도가 20fps 아래로 떨어지면 기본 마우스 포인터로 되돌리기만 하면 됩니다. (이럴 때 롤링 프레임 속도가 유용합니다. 현재 프레임 속도에 반응하여 약 20fps로 진동하면 사용자에게 맞춤 마우스 포인터가 항상 숨겨지고 표시됩니다.) 이를 통해 다음을 수행할 수 있습니다.

프레임 속도 범위 동작
>10fps 더 많은 프레임이 삭제되지 않도록 게임 속도를 늦추세요.
10~20fps 맞춤 마우스 포인터 대신 기본 마우스 포인터를 사용합니다.
20~60fps 정상 작동
>60fps 프레임 속도가 이 값을 초과하지 않도록 조절합니다.
프레임 속도에 따른 동작 요약입니다.

마우스 포인터가 Mac에서는 어둡지만 PC에서는 흰색입니다. 이유가 무엇인가요? 플랫폼 전쟁은 가상 세계에서도 에너지가 필요하니까요.

결론

완벽한 엔진은 아니지만 완벽한 엔진이 되려고 하지는 않습니다. 이 아이콘은 Lem 기념일 로고와 함께 개발되었으며 특별히 개발되었습니다. 괜찮습니다. 돈 커누스가 유명하게 말한 것처럼'초기 최적화는 모든 악의 뿌리'입니다. 엔진을 먼저 분리해서 적용하는 것이 합리적이라고 생각하지 않습니다. 이론이 실천하는 것만큼이나 이론에 도움이 됩니다. 제 경우에는 코드가 삭제되었고 여러 부분이 반복해서 재작성되었으며 많은 공통 부분이 사실 이전에 주목되기도 했습니다. 하지만 결국 우리가 원하는 일을 할 수 있었습니다. 스타니스와프 렘의 커리어와 다니엘 므로스의 그림을 우리가 상상할 수 있는 최선의 방식으로 찬양합니다.

위 내용을 통해 디자인 선택과 장단점, 그리고 구체적인 실제 시나리오에서 HTML5를 어떻게 사용했는지 알 수 있기를 바랍니다. 이제 소스 코드를 사용해 보고 사용해 본 후 의견을 알려주세요.

제가 직접 해봤습니다. 아래는 러시아의 렘 기념일 로고를 볼 수 있었던 첫 시간대였던 2011년 11월 23일의 이른 시간을 카운트다운하는 마지막 날이었습니다. 아마도 낙서와 마찬가지로 하찮아 보이는 일도 때로는 더 깊은 의미를 지니게 됩니다. 이 카운터는 엔진에 정말 좋은 '스트레스 테스트'였습니다.

렘 기념일 로고 카운트다운 시계의 스크린샷
렘 기념일 로고 카운트다운 시계 스크린샷

이는 Google 기념일 로고의 수명을 바라볼 수 있는 한 가지 방법입니다. 몇 달 동안 작업하고 몇 주 동안 테스트하고, 48시간 동안 구워 먹으면 사람들이 5분 동안 플레이할 수 있습니다. 수천 개의 JavaScript 라인에서는 모두 이 5분의 시간이 유익한 시간이 되기를 바라고 있습니다. 즐겁게 사용해 보세요.