Cześć, świecie
Strona główna Google to fascynujące środowisko do kodowania. Wymaga to spełnienia wielu trudnych wymagań: szczególnego skupienia się na szybkości i opóźnieniach, dostosowania do wszystkich przeglądarek i działania w różnych okolicznościach, a także – tak, właśnie – zaskoczenia i zadowolenia.
Chodzi mi o doodle Google, czyli specjalne ilustracje, które od czasu do czasu zastępują nasze logo. Chociaż moje relacje z pisakami i pędzlami od dawna mają ten charakterystyczny charakter zakazu zbliżania się, często przyczyniam się do interakcji.
Każda interaktywna grafika Doodle, którą zaprogramowałem (Pac-Man, Jules Verne, World’s Fair) – a także wiele tych, przy których pomagałem – była w równym stopniu futurystyczna i anachroniczna: wspaniałe możliwości zastosowania najnowocześniejszych funkcji internetowych… i pragmatyzm w kwestii zgodności z różnymi przeglądarkami.
Każda interaktywna gra Doodle przynosi nam wiele nauki, a niedawno opublikowana minigra poświęcona Stanisławowi Lememu nie była wyjątkiem. Jej 17 tys. wierszy kodu JavaScriptu zawierało wiele nowych elementów, które po raz pierwszy pojawiły się w historii Doodle. Dzisiaj chcę się z Wami podzielić tym kodem. Być może znajdziesz w nim coś interesującego lub zauważysz moje błędy.
Wyświetl kod doodle Stanisława Lema »
Warto pamiętać, że strona główna Google nie jest miejscem na prezentacje technologii. Chcemy, aby nasze doodle upamiętniały konkretne osoby i wydarzenia, a do tego używać najlepszych grafik i najlepszych technologii, z których korzystamy. Nie chcemy jednak chwalić technologii dla samej technologii. Oznacza to, że należy dokładnie sprawdzić, jakie elementy HTML5 są dostępne i czy mogą pomóc w ulepszeniu doodle, nie odwracając od niego uwagi ani nie przyćmiewając go.
Przyjrzyjmy się niektórym nowoczesnym technologiom internetowym, które znalazły zastosowanie w doodle Stanisława Lema, a niektóre nie.
Grafiki za pomocą DOM i płótna
Canvas jest potężnym narzędziem stworzonym z myślą o dokładnie takich zastosowaniach jak w tym przypadku. Jednak niektóre starsze przeglądarki, na których nam zależało, nie obsługiwały tej funkcji. Mimo że dosłownie dzielę biuro z osobą, która stworzyła świetne narzędzie excanvas, zdecydowałem się na inną drogę.
Stworzyłem silnik graficzny, który abstrakcyjnie traktuje prymitywy graficzne zwane „prostokątami”, a potem renderuje je za pomocą canvasa lub DOM, jeśli canvas jest niedostępny.
Takie podejście wiąże się z niektórymi ciekawymi wyzwaniami – na przykład przeniesienie lub zmiana obiektu w DOM ma natychmiastowe konsekwencje, podczas gdy w przypadku płótna jest określony moment, w którym wszystko jest rysowane w tym samym czasie. (Postanowiłam mieć tylko 1 płótno, które czyszczę i rysuję od początku w każdej klatce. Z jednej strony zbyt wiele elementów, które się poruszają, a z drugiej – zbyt mała złożoność, aby podzielić je na kilka nakładających się na siebie kanw i aktualizować je selektywnie.
Niestety przejście na canvas nie jest tak proste, jak zduplikowanie tła CSS za pomocą drawImage()
: tracisz wtedy wiele rzeczy, które są dostępne bezpłatnie, gdy łączysz elementy za pomocą DOM – przede wszystkim warstw z indeksem z- i zdarzeń myszy.
Z-index został już zastąpiony przez koncepcję „płaszczyzn”. Doodle zdefiniował liczbę płaszczyzn – od nieba daleko za nimi po wskaźnik myszy przed wszystkim – i każdy aktor w doodle musiał zdecydować, do której z nich należy (małe korekty plus/minus w płaszczyźnie były możliwe dzięki użyciu planeCorrection
).
Podczas renderowania w DOM płaszczyzny są po prostu przekształcane w indeks Z. Jeśli jednak renderujemy za pomocą obrazu, przed narysowaniem prostokątów musimy je posortować według płaszczyzn. Ponieważ jest to kosztowne, kolejność jest przeliczana tylko wtedy, gdy dodasz element lub przeniesiesz go do innego poziomu.
W przypadku zdarzeń myszy też to zaimplementowałem… w pewnym sensie. Zarówno w przypadku DOM, jak i płótna użyłem dodatkowych, całkowicie przezroczystych, unoszących się elementów DOM o wysokiej kolejności nakładania elementów, których zadaniem jest tylko reagowanie na najeżdżanie i wychodzenie kursora myszy oraz kliknięcia i dotknięcia.
W tym przypadku chcieliśmy spróbować przełamać czwartą ścianę. Pozwoliło nam to połączyć aktorów działających na poziomie canvasa z aktorami działającymi na poziomie DOM. Na przykład eksplozje w finale znajdują się zarówno na kanwie dla obiektów w uniwersum, jak i w DOM dla reszty strony głównej Google. Ptak, który zwykle lata i jest przycinany przez naszą maskę z nierównymi krawędziami jak każdy inny aktor, decyduje się nie angażować w problemy podczas kręcenia sceny i siada na przycisku „Mam szczęście”. Ptak opuszcza płótno i staje się elementem DOM (i na odwrót), co powinno być całkowicie niezauważalne dla użytkowników.
Liczba klatek
Znajomość bieżącej częstotliwości klatek i reakcja na zbyt wolne (i zbyt szybkie!) tempo były ważną częścią naszego silnika. Ponieważ przeglądarki nie raportują częstotliwości wyświetlania klatek, musimy ją obliczyć samodzielnie.
Na początku używałem metody requestAnimationFrame, a gdy była niedostępna, wracałem do przestarzałej metody setTimeout
.
requestAnimationFrame
sprytnie oszczędza procesor w niektórych sytuacjach (chociaż część z tych działań wykonujemy sami, jak wyjaśnimy poniżej), ale też pozwala nam uzyskać większą liczbę klatek na sekundę niż w przypadku setTimeout
.
Obliczanie bieżącej liczby klatek na sekundę jest proste, ale może ulec gwałtownym zmianom – na przykład może szybko spaść, gdy inna aplikacja przez jakiś czas zajmuje komputer. Dlatego obliczamy „przesuwającą się” (średnią) liczbę klatek tylko co 100 fizycznych odświeżeń i na tej podstawie podejmujemy decyzje.
Jakich?
Jeśli liczba klatek na sekundę jest większa niż 60, ograniczamy ją. Obecnie w niektórych wersjach Firefoksa
requestAnimationFrame
nie ma górnego limitu częstotliwości klatek, więc nie ma sensu marnować mocy procesora. Pamiętaj, że ograniczamy liczbę klatek do 65 FPS, ponieważ błędy zaokrągleń powodują, że w innych przeglądarkach liczba klatek jest nieco wyższa niż 60 FPS. Nie chcemy ograniczać liczby klatek przez pomyłkę.Jeśli liczba klatek na sekundę jest niższa niż 10 FPS, po prostu zwalniamy silnik zamiast pomijać klatki. To propozycja, która nie przyniesie korzyści, ale wydawało mi się, że pomijanie zbyt dużej liczby klatek będzie bardziej mylące niż po prostu wolniejsze (ale nadal spójne) działanie gry. Ma to jeszcze inny przyjemny efekt uboczny: jeśli system na chwilę zwolni, użytkownik nie zauważy dziwnego przeskoku, gdy silnik będzie się desperacko starał nadrobić zaległości. (W przypadku Pac-Mana zrobiłem to nieco inaczej, ale minimalna liczba klatek na sekundę jest lepszym rozwiązaniem).
Na koniec warto rozważyć uproszczenie grafiki, gdy częstotliwość klatek jest niebezpiecznie niska. Nie zrobiliśmy tego w przypadku rysunku z Lemem, z wyjątkiem wskaźnika myszy (więcej na ten temat poniżej), ale teoretycznie moglibyśmy usunąć niektóre z niepotrzebnych animacji, aby rysunek był płynny nawet na wolniejszych komputerach.
Mamy też pojęcie fizycznego i logicznego zaznaczenia. Pierwsza wartość pochodzi z requestAnimationFrame
/setTimeout
. W przypadku normalnej rozgrywki stosunek wynosi 1:1, ale w przypadku przewijania do przodu po prostu dodajemy więcej logicznych odświeżeń na fizyczne odświeżenie (do 1:5). Dzięki temu możemy wykonać wszystkie niezbędne obliczenia dla każdego logicznego kroku, ale tylko ostatni z nich będzie aktualizować elementy na ekranie.
Analiza porównawcza
Można założyć (i tak było na początku), że canvas będzie szybszy niż DOM, gdy tylko będzie dostępny. Nie zawsze tak jest. Podczas testowania okazało się, że Opera 10.0–10.1 na Macu i Firefox na Linuksie są szybsze podczas przenoszenia elementów DOM.
W idealnym świecie animacja pokazywałaby różne techniki graficzne – elementy DOM przemieszczane za pomocą funkcji style.left
i style.top
, rysowanie na płótnie, a nawet przemieszczanie elementów DOM za pomocą przekształceń CSS3.
– a następnie przełącz się na ten, który zapewnia najwyższą liczbę klatek na sekundę. Zacząłem pisać kod, ale okazało się, że moje podejście do porównywania było dość niepewne i wymagające sporo czasu. Czas, którego nie mamy na stronie głównej – zależy nam na szybkości, dlatego chcemy, aby animacja wyświetlała się natychmiast, a gra zaczynała się od razu po kliknięciu lub dotknięciu.
W końcu tworzenie stron internetowych sprowadza się do robienia tego, co trzeba. Spojrzałem za siebie, żeby sprawdzić, czy nikt nie patrzy, a potem po prostu zakodowałem Opera 10 i Firefox w pliku canvas. W następnym życiu wrócę jako tag <marquee>
.
Oszczędzanie procesora
Znasz takiego znajomego, który przychodzi do Ciebie do domu, ogląda finał sezonu Breaking Bad, psuje Ci niespodziankę, a potem jeszcze usuwa go z Twojego DVR? Nie chcesz być takim typem, prawda?
To najgorsze porównanie na świecie. Nie chcemy jednak, aby nasza animacja była tak irytująca – fakt, że możemy wyświetlić się w karcie przeglądarki użytkownika, jest przywilejem, a zajmowanie zasobów procesora czy rozpraszanie użytkownika sprawiłoby, że stalibyśmy się nieprzyjemnym gościem. Dlatego jeśli nikt nie korzysta z doodle (brak dotknięć, kliknięć myszką, ruchów myszką ani naciśnięć klawiszy), chcemy, aby w ostateczności zasnęło.
Kiedy?
- po 18 sekundach na stronie głównej (w przypadku gier zręcznościowych jest to tryb przyciągający uwagę);
- po 180 sekundach, jeśli karta jest aktywna
- po 30 sekundach, jeśli karta nie jest aktywna (np.użytkownik przełączył się na inne okno, ale nadal oglądał doodle na nieaktywnej karcie).
- natychmiast, jeśli karta staje się niewidoczna (np. użytkownik przełączył się na inną kartę w tym samym oknie – nie ma sensu marnować cykli, jeśli nie możemy być widoczni);
Skąd wiemy, że karta jest aktualnie aktywna? Dołączamy się do window.focus
i window.blur
. Jak możemy wiedzieć, że karta jest widoczna? Korzystamy z nowego interfejsu Page Visibility API i reagujemy na odpowiednie zdarzenie.
Czasy oczekiwania są dłuższe niż zwykle. Zmodyfikowałem je do tego konkretnego doodle, który zawiera wiele animacji otoczenia (głównie nieba i ptaka). W idealnej sytuacji czas oczekiwania byłby ograniczony do interakcji w grze (np. zaraz po wylądowaniu ptak mógłby poinformować doodle, że może już zasnąć), ale ostatecznie nie wdrożyłem tego.
Ponieważ niebo jest zawsze w ruchu, podczas zasypiania i budzenia doodle nie tylko się zatrzymuje lub włącza – najpierw zwalnia, a potem wznawia działanie, zwiększając lub zmniejszając liczbę logicznych odcinków na fizyczny odcinek w miarę potrzeby.
Przejścia, przekształcenia, zdarzenia
Jedną z zalet HTML jest to, że możesz go ulepszać samodzielnie: jeśli coś nie jest wystarczająco dobre w standardowym portfolio HTML i CSS, możesz użyć JavaScript, aby to rozszerzyć. Niestety często oznacza to konieczność rozpoczęcia od zera. Przejścia CSS3 są świetne, ale nie możesz dodawać nowego typu przejścia ani używać przejść do niczego innego niż stylizowanie elementów. Inny przykład: przekształcenia CSS3 świetnie sprawdzają się w przypadku DOM, ale gdy przejdziesz do tworzenia na płótnie, nagle zostajesz sam.
Z tego powodu Lem doodle ma własny mechanizm przekształcania i przechodzenia. Wiem, że to lata 2000, a możliwości, które udało mi się stworzyć, nie są tak zaawansowane jak w CSS3, ale cokolwiek robi silnik, robi to konsekwentnie i daje nam znacznie większą kontrolę.
Zacząłem od prostego systemu działań (zdarzeń) – osi czasu, która uruchamia zdarzenia w przyszłości bez użycia setTimeout
, ponieważ w dowolnym momencie czas animacji może się odłączyć od czasu fizycznego, przyspieszając (przewijanie do przodu), zwalniając (niska częstotliwość klatek lub uśpienie w celu oszczędzania procesora) lub całkowicie się zatrzymać (czekanie na zakończenie wczytywania obrazów).
Przejścia to tylko inny typ działań. Oprócz podstawowych ruchów i obrotów obsługujemy też ruchy względne (np. przesuwanie obiektu o 10 pikseli w prawo), niestandardowe działania, takie jak drżenie, a także animacje klatek kluczowych.
Wspomnieliśmy o obrotach. Są one również wykonywane ręcznie: mamy sprite’y na różne kąty dla obiektów, które trzeba obrócić. Głównym powodem było to, że zarówno CSS3, jak i obrócenia na płótnie powodowały artefakty wizualne, które uznaliśmy za nie do przyjęcia. Co więcej, te artefakty różniły się w zależności od platformy.
Niektóre obiekty, które się obracają, są przyczepione do innych obracających się obiektów. Przykładem jest ręka robota połączona z dolną częścią ramienia, która jest przyczepiona do obracającego się górnego ramienia. Oznacza to, że musiałem też utworzyć ubogą wersję transform-origin w postaci pivotów.
To sporo pracy, która ostatecznie obejmuje obszar już objęty przez HTML5, ale czasami obsługa natywnej przeglądarki nie jest wystarczająca i trzeba wymyślić coś nowego.
Praca z obrazami i układami
Silnik nie służy tylko do uruchamiania rysunku – można też w nim pracować. Udostępniłem Ci kilka parametrów debugowania. Pozostałe znajdziesz na stronie engine.readDebugParams
.
Pliki sprite to znana technika, której również używamy do tworzenia rysunków. Pozwala nam to oszczędzać bajty i skracać czas wczytywania, a także ułatwia wstępne wczytywanie.
Utrudnia to jednak tworzenie aplikacji – każda zmiana w obrazach wymagałaby ponownego skompilowania (w dużej mierze zautomatyzowanego, ale i tak kłopotliwego). Dlatego silnik obsługuje uruchamianie na surowych obrazach na potrzeby programowania oraz sprite’ów na potrzeby produkcji za pomocą engine.useSprites
– oba są zawarte w źródłowym kodzie.

Obsługujemy też wstępny załadunek obrazów, aby zatrzymać animację, jeśli obrazy nie wczytały się na czas. Do tego dochodzi jeszcze fałszywa pasek postępu. (Faux because, unfortunately, not even HTML5 can tell us how much of an image file has already been loaded.)

W niektórych scenach używamy więcej niż 1 sprite’a, nie tyle po to, aby przyspieszyć wczytywanie za pomocą połączeń równoległych, ale po prostu ze względu na ograniczenie obrazu na iOS do 3 lub 5 milionów pikseli.
Jakie miejsce zajmuje HTML5 w całym tym systemie? Nie ma tu zbyt wielu informacji, ale narzędzie, które napisałem do dzielenia i przycinania, było całkowicie nową technologią internetową: canvas, blobs, a[download]. Jedną z ciekawych cech HTML jest to, że stopniowo obejmuje ono funkcje, które wcześniej trzeba było realizować poza przeglądarką. Jedynym elementem, którego musieliśmy dokonać, było zoptymalizowanie plików PNG.
Zapisywanie stanu w przerwie między grami
Światy Lema zawsze wydawały się duże, żywe i realistyczne. Jego historie zazwyczaj zaczynały się bez zbyt wielu wyjaśnień, pierwsza strona zaczynała się od środka, a czytelnik musiał sam odnaleźć właściwą drogę.
Dzień Cyberiad nie był wyjątkiem, dlatego chcieliśmy odtworzyć to uczucie w doodle. Na początku staramy się nie przesadzać z tłumaczeniem historii. Kolejnym ważnym elementem jest losowość, która naszym zdaniem pasuje do mechanicznej natury wszechświata w książce. Mamy wiele funkcji pomocniczych związanych z losowością, które wykorzystujemy w wielu miejscach.
Chcieliśmy też zwiększyć możliwość wielokrotnego grania w inne sposoby. Aby to zrobić, musieliśmy sprawdzić, ile razy wcześniej została ukończona. Historycznie poprawnym rozwiązaniem technologicznym jest plik cookie, ale nie sprawdza się ono w przypadku strony głównej Google – każdy plik cookie zwiększa ilość danych na stronie, a nam zależy na szybkości i opóźnieniu.
Na szczęście HTML5 udostępnia nam Web Storage, który jest łatwy w użyciu. Umożliwia zapisywanie i odczytywanie ogólnej liczby odtworzeń oraz ostatniej sceny odtworzonej przez użytkownika – z wiele większą elastycznością niż w przypadku plików cookie.
Co robimy z tymi informacjami?
- wyświetlamy przycisk szybkiego przewijania, który umożliwia pominięcie przerywników, które użytkownik już widział;
- podczas finału wyświetlamy różne N elementy
- nieznacznie zwiększyliśmy poziom trudności poziomu strzelania.
- po trzeciej i kolejnych odsłonach gry wyświetla się smok z innej historii, który jest ukrytym żartem.
Istnieje kilka parametrów debugowania, które kontrolują to działanie:
?doodle-debug&doodle-first-run
– udawaj, że to pierwsze uruchomienie?doodle-debug&doodle-second-run
– udawaj, że to drugi test?doodle-debug&doodle-old-run
– udawaj, że to stary przebieg
Urządzenia z ekranami dotykowymi
Chcieliśmy, aby Doodle dobrze działało na urządzeniach dotykowych. Najnowocześniejsze z nich są wystarczająco wydajne, aby Doodle działało naprawdę dobrze, a granie w tę grę przez dotykanie jest o wiele ciekawsze niż przez klikanie.
Konieczne były pewne wstępne zmiany w środowisku użytkowników. Pierwotnie wskaźnik myszy był jedynym elementem, który wskazywał, że trwa scena przerywająca lub nieinteraktywna. Później dodaliśmy mały wskaźnik w prawym dolnym rogu, aby nie trzeba było polegać tylko na wskaźniku myszy (ponieważ nie ma ich na urządzeniach dotykowych).
Normalny | Zajęty | Klikalny | Kliknięto | |
---|---|---|---|---|
Praca w toku | ![]() |
![]() |
![]() |
![]() |
Finał | ![]() |
![]() |
![]() |
![]() |
Większość rzeczy działała od razu. Jednak szybkie, spontaniczne testy użyteczności interfejsu dotykowego wykazały 2 problemy: niektóre cele były zbyt trudne do naciśnięcia, a szybkie dotknięcia były ignorowane, ponieważ po prostu zastąpiliśmy zdarzenia kliknięcia myszką.
Pomocne okazało się tutaj posiadanie oddzielnych przezroczystych elementów DOM, które można kliknąć, ponieważ mogłem zmieniać ich rozmiar niezależnie od grafiki. Wprowadziłem dodatkowy margines 15 pikseli na potrzeby urządzeń dotykowych i użyłem go w przypadku elementów klikalnych. (Dodałem też 5 pikseli marginesu dla środowiska myszy, aby zadowolić pana Fittsa).
Jeśli chodzi o drugi problem, dołączyłem i przetestowałem odpowiednie uchwyty dotykowe do rozpoczęcia i zakończenia, zamiast polegać na klikaniu myszką.
Korzystamy też z bardziej nowoczesnych właściwości stylów, aby usunąć niektóre funkcje dotykowe, które przeglądarki WebKit dodają domyślnie (podświetlenie dotknięcia, objaśnienie dotknięcia).
Jak wykryć, czy dane urządzenie z doodle obsługuje dotyk? Niedbale. Zamiast ustalać to a priori, wykorzystaliśmy nasze połączone wartości IQ, aby wywnioskować, że urządzenie obsługuje dotyk... po otrzymaniu pierwszego zdarzenia rozpoczęcia dotyku.
Dostosowywanie wskaźnika myszy
Nie wszystko jednak działa na dotyk. Jedną z naszych zasad było umieszczenie w doodle jak największej liczby elementów. interfejs małego paska bocznego (przewijanie do przodu, znak zapytania), tekst podpowiedzi, a nawet wskaźnik myszy;
Jak dostosować wskaźnik myszy? Niektóre przeglądarki umożliwiają zmianę kursora myszy przez połączenie go z prywatnym plikiem graficznym. Nie jest to jednak dobrze obsługiwane rozwiązanie i jest ono też dość restrykcyjne.
Jeśli nie to, to co? Dlaczego nie zrobić z wskaźnika myszy kolejnego czynnika w doodle? To działa, ale wiąże się z kilkoma zastrzeżeniami:
- musisz mieć możliwość usunięcia domyślnego wskaźnika myszy;
- musisz dość dobrze synchronizować kursor myszy z „prawdziwym” kursorem;
Pierwsza z nich jest trudna. CSS3 umożliwia użycie cursor: none
, ale ta funkcja również nie jest obsługiwana w niektórych przeglądarkach. Musieliśmy zastosować pewne sztuczki: używać pustego pliku .cur
jako pliku zapasowego, określać konkretne zachowanie w przypadku niektórych przeglądarek, a nawet zakodować sztywno inne przeglądarki, aby nie były uwzględniane w ogóle.
Drugi jest pozornie trywialny, ale ponieważ kursor myszy jest tylko częścią wszechświata rysunku, odziedziczy też wszystkie jego problemy. Największy? Jeśli liczba klatek na sekundę rysunku jest niska, liczba klatek na sekundę wskaźnika myszy też będzie niska. Może to mieć przykre konsekwencje, ponieważ wskaźnik myszy jest naturalnym przedłużeniem ręki i musi być zawsze responsywny. (osoby, które korzystały z komputera Commodore Amiga, kiwają teraz energicznie głowami)
Jednym z trochę bardziej skomplikowanych rozwiązań tego problemu jest odłączenie wskaźnika myszy od zwykłej pętli aktualizacji. Udało się to – w alternatywnym wszechświecie, w którym nie muszę spać. Czy istnieje prostsze rozwiązanie? W przypadku spadku średniej liczby klatek poniżej 20 kl./s kursor myszy wraca do domyślnego stanu. (Właśnie w takich sytuacjach przydaje się zmienna częstotliwość klatek). Jeśli zareagowalibyśmy na bieżącą liczbę klatek na sekundę i gdyby ta liczba wahała się wokół 20 FPS, użytkownik widziałby niestandardowy wskaźnik myszy, który cały czas się pojawia i znika. Oto, co to oznacza:
Zakres liczby klatek | Zachowanie |
---|---|
>10 kl./s | Zwolnij grę, aby nie tracić więcej klatek. |
10–20 FPS | Zamiast niestandardowego wskaźnika myszy użyj domyślnego. |
20–60 FPS | Normalna praca. |
>60 kl./s | Ogranicz tak, aby częstotliwość klatek nie przekraczała tej wartości. |
A tak, kursor myszy jest ciemny na Macu, ale biały na PC. Dlaczego? Ponieważ wojny platform potrzebują paliwa nawet w fikcyjnych światach.
Podsumowanie
Nie jest to idealny silnik, ale nie próbuje być taki. Został on opracowany w ramach projektu Doodle poświęconego Lemowi i jest bardzo ściśle związany z tą postacią. To nie problem. „Przedwczesne optymalizowanie jest źródłem wszelkiego zła” – jak słusznie zauważył Don Knuth. Nie uważam, że pisanie silnika w izolacji, a potem dopiero jego stosowanie ma sens. Praktyka tworzy teorię, a teoria tworzy praktykę. W moim przypadku kod został wyrzucony, niektóre części były przepisywane wielokrotnie, a wiele wspólnych elementów zostało dodanych w postu, a nie przed jego opublikowaniem. Ostatecznie jednak udało nam się zrealizować nasz cel – uczcić karierę Stanisława Lema i rysunki Daniela Mrozówa w najlepszy możliwy sposób.
Mam nadzieję, że powyższe informacje rzucają nieco światła na niektóre decyzje projektowe i wyrzeczenia, na które musieliśmy się zdecydować, oraz na sposób wykorzystania HTML5 w konkretnym, rzeczywistym scenariuszu. Teraz możesz pobawić się kodem źródłowym, przetestować go i przekazać nam swoją opinię.
Zrobiliśmy to sami – w ostatnich dniach wyświetlaliśmy te informacje, które odliczały czas do 23 listopada 2011 r. w Rosji, czyli pierwszej strefie czasowej, w której wyświetlono doodle poświęcone Lemowi. Może to głupie, ale tak jak w przypadku rysunków, rzeczy, które wydają się nieistotne, czasami mają głębsze znaczenie. Ten licznik był naprawdę dobrym „testem obciążeniowym” dla silnika.

To jeden ze sposobów na spojrzenie na życie Google Doodle – miesiące pracy, tygodnie testów, 48 godzin na gotowanie, a wszystko po to, aby ludzie grali przez 5 minut. Każda z tych tysięcy linii kodu JavaScript ma nadzieję, że te 5 minut będzie dobrze wykorzystanych. Miłego korzystania.