Fallstudie: Google-Doodle zu Ehren von Stanisław Lem

Marcin Wichary
Marcin Wichary

Hallo, (eigentümliche) Welt

Die Google-Startseite ist eine interessante Umgebung für das Programmieren. Dabei gibt es viele schwierige Einschränkungen: ein besonderer Fokus auf Geschwindigkeit und Latenz, die Möglichkeit, alle Arten von Browsern zu bedienen und unter verschiedenen Bedingungen zu funktionieren, und ... ja, Überraschung und Freude.

Ich meine Google-Doodles, die speziellen Illustrationen, die gelegentlich unser Logo ersetzen. Und obwohl meine Beziehung zu Stiften und Pinseln seit Langem den charakteristischen Eindruck einer einschränkten Anordnung hat, trage ich oft zu den interaktiven bei.

Alle interaktiven Doodles, die ich programmiert habe (Pac-Man, Jules Verne, Weltausstellung), und vielen, an denen ich mitgewirkt habe, waren zu gleichen Teilen futuristisch und anachronistisch: großartige Gelegenheiten für innovative Web-Apps und den sinnlosen Pragmatismus der browserübergreifenden Kompatibilität.

Aus jedem interaktiven Doodle lernen wir viel. Das neue Stanisław Lem-Minispiel war da keine Ausnahme: Es hat mit seinen 17.000 Zeilen JavaScript-Code zum ersten Mal in der Geschichte der Doodles viel ausprobiert. Heute möchte ich Ihnen etwas Interessantes vorstellen oder meine Fehler aufzeigen.

Stanisław Lem-Doodle-Code ansehen »

Beachten Sie, dass die Startseite von Google kein Ort für technische Demos ist. Mit unseren Doodles möchten wir bestimmte Menschen und Ereignisse feiern, und das mit der besten Kunst und den besten Technologien, die wir beschwören können. Wir feiern aber niemals die Technologie um der Technologie willen. Sie müssen also genau prüfen, welcher Teil von allgemein verstandenem HTML5-Code verfügbar ist, und ob wir die Doodles verbessern können, ohne sie zu stören oder zu übersehen.

Sehen wir uns also einige moderne Webtechnologien an, die im Stanisław Lem-Doodle ihren Platz gefunden haben – und einige nicht.

Grafiken über DOM und Canvas

Canvas ist äußerst leistungsstark und wurde genau für die Dinge entwickelt, die wir mit diesem Doodle erreichen wollten. Einige der älteren Browser, um die es uns ging, haben diese Funktion jedoch nicht unterstützt – und obwohl ich ein Büro mit der Person teile, die ein ansonsten ausgezeichnetes Excanvas erstellt hat, entschied ich mich für einen anderen Weg.

Ich habe eine Grafik-Engine zusammengestellt, die grafische Primitive, die sogenannten „rects“, abstrahiert und sie dann mit einem der Canvas-Elemente oder des DOM rendert, wenn Canvas nicht verfügbar ist.

Dieser Ansatz bringt einige interessante Herausforderungen mit sich. Beispielsweise hat das Verschieben oder Ändern eines Objekts im DOM unmittelbare Folgen, während bei Canvas ein bestimmter Moment auftreten kann, in dem alles gleichzeitig gezeichnet wird. (Ich beschloss, nur einen Canvas zu verwenden, lösche diesen und zeichne mit jedem Frame von Grund auf neu. Zu viele, im wahrsten Sinne des Wortes bewegende Teile auf einer Seite – und auf der anderen nicht so komplex, dass eine Aufteilung in mehrere sich überschneidende Canvases und selektiv aktualisiertes erforderlich ist.)

Leider ist der Wechsel zum Canvas nicht so einfach wie das Spiegeln von CSS-Hintergründen mit drawImage(): Ihnen gehen einige Elemente verloren, die beim Zusammenfügen über DOM kostenlos zur Verfügung stehen. Das ist vor allem das Überlagern mit Z-Indexen und Mausereignissen.

Ich habe den Z-Index bereits mit einem Konzept namens „Ebenen“ abstrahiert. Das Doodle definiert eine Reihe von Ebenen – vom Himmel weit dahinter bis zum Mauszeiger vor allem. Jeder Akteur in dem Doodle musste entscheiden, zu welcher es gehörte (kleine Plus-/Minuskorrekturen innerhalb einer Ebene waren mit planeCorrection möglich).

Beim Rendern über DOM werden die Ebenen einfach in den Z-Index übersetzt. Wenn wir jedoch über das Canvas-Element rendern, müssen wir die Rekts vor dem Zeichnen anhand ihrer Ebenen sortieren. Da dies jedes Mal teuer ist, wird die Reihenfolge nur dann neu berechnet, wenn ein Akteur hinzugefügt wird oder wenn er zu einer anderen Ebene wechselt.

Für Mausereignisse habe ich das auch abstrahiert... sozusagen. Sowohl für DOM als auch für Canvas habe ich zusätzliche vollständig transparente Floating-DOM-Elemente mit hohem Z-Index verwendet, die nur auf Mouse-Over/Out, Klicks und Tippen reagieren sollen.

Mit diesem Doodle wollten wir unter anderem die vierte Wand durchbrechen. Mithilfe der oben genannten Engine konnten wir Canvas- und DOM-basierte Akteure kombinieren. Die Explosionen im Finale befinden sich beispielsweise sowohl im Canvas für In-Universal-Objekte als auch im DOM für den Rest der Google-Startseite. Der Vogel, der normalerweise umherfliegt und wie jeder andere Schauspieler von unserer gezackten Maske abgeschnitten hat, beschließt, während des Drehlevels keine Probleme zu vermeiden, und setzt sich auf die Schaltfläche "Auf gut Glück". So verlässt der Vogel den Canvas und wird zu einem DOM-Element (und umgekehrt). Ich hatte gehofft, für unsere Besucher vollständig transparent zu sein.

Framerate

Die Kenntnis der aktuellen Framerate und die Reaktion darauf waren zu langsam – und zu schnell! – ein wichtiger Teil unserer Engine. Da die Browser die Framerate nicht zurückgeben, müssen wir sie selbst berechnen.

Zuerst habe ich requestAnimationFrame verwendet. Sollte die frühere Version nicht verfügbar sein, verwende ich setTimeout. requestAnimationFrame spart in einigen Situationen die CPU auf intelligente Weise – obwohl wir einige davon selbst erledigen, wie unten erläutert wird –, ermöglicht aber auch einfach eine höhere Framerate als setTimeout.

Die Berechnung der aktuellen Framerate ist einfach, unterliegt aber drastischen Änderungen. So kann sie schnell sinken, wenn eine andere Anwendung den Computer eine Zeit lang nicht verwendet. Daher berechnen wir eine „rollende“ (gemittelte) Framerate nur für jeweils 100 physische Ticks und treffen darauf basierende Entscheidungen.

Welche Art von Entscheidungen?

  • Wenn die Framerate höher als 60 fps ist, wird sie gedrosselt. Derzeit hat requestAnimationFrame in einigen Firefox-Versionen keine Obergrenze für die Framerate und es macht keinen Sinn, die CPU zu verschwenden. Aufgrund der Rundungsfehler, die dazu führen, dass die Framerate in anderen Browsern etwas höher ist als 60 fps, möchten wir nicht versehentlich eine Drosselung vornehmen.

  • Wenn die Framerate unter 10 fps liegt, verlangsamen wir einfach die Engine, anstatt Frames ausgelassen zu bekommen. Es ist ein Loser-Verlieren-Vorschlag, aber ich fand, dass es verwirrender wäre, zu viel Frames zu überspringen, als ein langsameres (aber dennoch kohärentes) Spiel. Dies hat einen weiteren positiven Nebeneffekt: Wenn das System vorübergehend langsam wird, gibt es keinen seltsamen Sprung vorwärts, da der Motor verzweifelt aufholt. Für Pac-Man machte ich es etwas anders, aber mit der Mindest-Framerate wäre es besser.

  • Wir können auch Grafiken vereinfachen, wenn die Framerate gefährlich niedrig ist. Wir machen das nicht für das Lem-Doodle, mit Ausnahme des Mauszeigers (mehr dazu weiter unten), aber hypothetisch könnten wir einige überflüssige Animationen verlieren, nur damit sich das Doodle selbst auf langsameren Computern flüssig anfühlt.

Wir haben auch das Konzept eines physischen und eines logischen Teilstrichs. Ersteres stammt aus requestAnimationFrame/setTimeout. Das Verhältnis beim normalen Gameplay beträgt 1:1, aber zum Vorspulen fügen wir einfach weitere logische Ticks pro physischem Tick hinzu (bis zu 1:5). Auf diese Weise können wir alle erforderlichen Berechnungen für jeden logischen Tick durchführen, aber nur das letzte als dasjenige festlegen, das die Elemente auf dem Bildschirm aktualisiert.

Benchmarking

Es kann davon ausgegangen werden, dass Canvas schneller verfügbar ist als DOM, und das sogar schon zu Beginn. Das stimmt nicht immer. Beim Testen haben wir festgestellt, dass Opera 10.0–10.1 auf einem Mac und Firefox unter Linux beim Verschieben von DOM-Elementen in Wirklichkeit schneller sind.

Im Idealfall würde das Doodle im Hintergrund verschiedene Grafiktechniken vergleichen: DOM-Elemente, die mit style.left und style.top verschoben wurden, Zeichnungen auf Canvas, und vielleicht sogar DOM-Elemente, die mit CSS3-Transformationen verschoben wurden.

und dann zu derjenigen mit der höchsten Framerate wechseln. Ich begann, Code dafür zu schreiben, stellte aber fest, dass meine Art des Benchmarking zumindest ziemlich unzuverlässig war und viel Zeit erforderte. Zeit, die uns nicht auf unserer Startseite zur Verfügung steht – Geschwindigkeit ist uns sehr wichtig. Das Doodle soll sofort angezeigt werden und das Gameplay kann beginnen, sobald man darauf klickt oder tippt.

Letztendlich geht es bei der Webentwicklung manchmal darum, das zu tun, was man tun muss. Ich schaute hinter meine Schulter, um sicherzustellen, dass niemand hinsieht, und dann habe ich Opera 10 und Firefox aus dem Canvas hartcodiert. Im nächsten Leben werde ich wieder als <marquee>-Tag zurückkommen.

CPU schonen

Kennst du einen Freund, der zu dir nach Hause kommt, sich das Staffelfinale von Breaking Bad ansieht, es für dich verwöhnt und es dann von deinem digitalen Videorekorder löscht? Dieser Typ willst du doch nicht sein, oder?

Also, ja, die schlimmste Analogie aller Zeiten. Aber unser Doodle wollen wir auch nicht. Die Tatsache, dass wir den Browser-Tab eines Nutzers aufrufen dürfen, ist ein Privileg. Das Anhäufen von CPU-Zyklen oder das Ablenken des Nutzers würden uns zu einem unangenehmen Gast machen. Wenn also niemand mit dem Doodle spielt (keine Tippen, Mausklicks, Mausbewegungen oder Tastenbetätigungen), soll es irgendwann in den Ruhemodus wechseln.

Wann?

  • Nach 18 Sekunden auf der Startseite (Arcade-Spiele werden als Attract-Modus bezeichnet)
  • nach 180 Sekunden, wenn der Tab im Fokus ist
  • nach 30 Sekunden, wenn der Tab nicht im Fokus ist (z.B. wenn der Nutzer zu einem anderen Fenster gewechselt ist, aber sich das Doodle möglicherweise noch in einem inaktiven Tab ansieht)
  • sofort, wenn der Tab unsichtbar wird (z. B. wenn der Nutzer zu einem anderen Tab im selben Fenster gewechselt ist – keine unnötigen Zyklen, wenn wir nicht sichtbar sind).

Woher wissen wir, dass der Tab derzeit im Fokus ist? Wir verknüpfen window.focus und window.blur. Woher wissen wir, dass der Tab sichtbar ist? Wir verwenden die neue Page Sichtbarkeit API und reagieren auf das entsprechende Ereignis.

Die oben genannten Zeitüberschreitungen sind für uns verzeihlicher als üblich. Ich habe sie an dieses spezielle Doodle angepasst, das viele Ambient-Animationen enthält (vor allem der Himmel und der Vogel). Idealerweise würden die Timeouts durch Interaktionen im Spiel gesteuert werden – z.B. könnte der Vogel direkt nach der Landung der Doodles melden, dass er jetzt einschlafen kann – aber ich habe das am Ende nicht implementiert.

Da der Himmel immer in Bewegung ist, hört die Zeichnung beim Einschlafen und Aufwachen nicht nur auf oder fängt an – sie verlangsamt sich vor dem Anhalten und umgekehrt, wenn Sie die Anzeige fortsetzen, erhöhen oder verringern oder die Anzahl der logischen Zecken pro physischer Zicke erhöhen oder verringern.

Übergänge, Transformationen, Ereignisse

Eine der Stärken von HTML besteht seit jeher darin, dass man es selbst verbessern kann: Wenn etwas im regulären HTML- und CSS-Portfolio nicht gut genug ist, kann man JavaScript zur Erweiterung verwenden. Leider bedeutet es oft, bei null anzufangen. CSS3-Übergänge sind toll, aber es ist nicht möglich, einen neuen Übergangstyp hinzuzufügen oder Übergänge für andere Elemente als Stilelemente zu verwenden. Ein weiteres Beispiel: CSS3-Transformationen eignen sich hervorragend für DOM. Wenn Sie jedoch zum Canvas wechseln, sind Sie plötzlich auf sich allein gestellt.

Aus diesen und weiteren Gründen hat Lem-Doodle eine eigene Übergangs- und Transformations-Engine. Die 2000er nennen usw. Die Funktionen, die ich integriert habe, sind nirgends so leistungsstark wie CSS3, aber was immer die Engine tut, sie funktioniert konsequent und gibt uns viel mehr Kontrolle.

Ich habe mit einem einfachen Aktionssystem (Ereignis) begonnen – einer Zeitachse, die Ereignisse in der Zukunft ohne setTimeout auslöst, da sich die Doodle-Zeit zu einem bestimmten Zeitpunkt von der physischen Zeit unterscheiden kann, wenn sie schneller (vorwärts) oder langsamer wird (niedrige Framerate oder das Einschlafen zur Schonung der CPU) oder ganz gestoppt (Warten auf das vollständige Laden von Bildern).

Übergänge sind nur eine weitere Art von Aktionen. Neben den grundlegenden Bewegungen und Drehungen unterstützen wir auch relative Bewegungen (z.B. eine Verschiebung von etwas 10 Pixel nach rechts), benutzerdefinierte Aktionen wie Zittern und auch Keyframe-Bildanimationen.

Drehungen, die ich bereits erwähnt habe, werden auch manuell ausgeführt: Es gibt Sprites für verschiedene Winkel bei den Objekten, die gedreht werden müssen. Der Hauptgrund besteht darin, dass sowohl bei CSS3- als auch bei Canvas-Rotationen visuelle Artefakte eingeführt wurden, die wir für inakzeptabel fanden. Außerdem variierten diese Artefakte je nach Plattform.

Da einige Objekte, die sich drehen, an andere rotierende Objekte angebracht sind – zum Beispiel die Hand eines Roboters, die an einem rotierenden Oberarm befestigt ist – musste ich auch den Ursprung der Transformation in Form von Drehpunkten erstellen.

All dies ist eine solide Arbeit, die sich letztendlich auf den Grundsatz von HTML5 auswirkt. Manchmal reicht die native Unterstützung jedoch nicht aus und es ist an der Zeit, das Rad neu zu erfinden.

Mit Bildern und Sprites umgehen

Ein Motor dient nicht nur zum Laufen des Doodles, sondern auch zum Arbeiten. Ich habe Ihnen oben einige Debug-Parameter gezeigt. Den Rest finden Sie unter engine.readDebugParams.

Das Spriting ist eine bekannte Technik, die auch für Zeichnungen verwendet wird. Es ermöglicht uns, Byte zu sparen, die Ladezeiten zu verkürzen und das Vorabladen zu vereinfachen. Dies erschwert jedoch auch die Entwicklung – jede Änderung an Bildern erfordert ein weitgehend automatisiertes, aber umständliches Bild. Daher unterstützt die Engine die Ausführung mit Roh-Images zur Entwicklung sowie mit Sprites für die Produktion über engine.useSprites – beide sind im Quellcode enthalten.

Pac-Man-Doodle
Sprites für das Pac-Man-Doodle.

Außerdem haben wir die Möglichkeit, Bilder vorab zu laden und das Doodle anzuhalten, wenn die Bilder nicht rechtzeitig geladen wurden. Und mit einer falschen Fortschrittsanzeige. (Falsch, da nicht einmal HTML5 uns sagen kann, wie viel von einer Bilddatei bereits geladen ist.)

Screenshot der Ladegrafik mit manipulierter Fortschrittsanzeige
Screenshot der Ladegrafik mit manipulierter Fortschrittsanzeige.

Für einige Szenen verwenden wir mehr als ein Sprite, um das Laden über parallele Verbindungen zu beschleunigen, sondern nur aufgrund der Begrenzung von 3/5 Millionen Pixeln für Bilder unter iOS.

Wie kann HTML5 hier eingesetzt werden? Oben finden Sie nicht viel davon, aber das Tool, das ich zum Spriting/Zuschneiden geschrieben habe, war eine ganz neue Webtechnologie: Canvas, Blobs und ein [Download]. Eines der interessanten Dinge an HTML ist, dass es nach und nach Dinge umfasst, die zuvor außerhalb des Browsers erledigt werden mussten. Der einzige Teil, den wir brauchten, war die Optimierung von PNG-Dateien.

Status zwischen Spielen wird gespeichert

Lems Welten fühlten sich immer groß, lebendig und realistisch an. Seine Geschichten begannen in der Regel ohne viel Erklärungen. Die erste Seite begann in Medien-Res, wobei der Leser nach ihr oder ihrem Weg suchen musste.

Die Cyberiad bildeten keine Ausnahme und wir wollten dieses Gefühl für das Doodle wiederholen. Wir beginnen damit, die Geschichte nicht zu erklären. Ein weiterer großer Teil ist die Randomisierung, die unserer Ansicht nach dem mechanischen Charakter des Buchuniversums gepasst hat. Wir haben eine Reihe von Hilfsfunktionen, die mit Zufälligkeit umgehen und die wir an vielen Stellen verwenden.

Außerdem wollten wir die Wiederholbarkeit auf andere Weise verbessern. Dazu mussten wir wissen, wie oft das Doodle fertig war. Die historisch korrekte technologische Lösung hierfür ist ein Cookie, das jedoch nicht für die Google-Startseite funktioniert. Jedes Cookie erhöht die Nutzlast jeder Seite, und auch hier ist Geschwindigkeit und Latenz sehr wichtig.

Glücklicherweise erhalten wir mit HTML5 einen einfachen Webspeicher, der die allgemeine Anzahl der Wiedergaben und die letzte vom Nutzer abgespielte Szene speichern und abrufen kann – mit viel mehr Qualität, als Cookies jemals zulassen würden.

Was machen wir mit diesen Informationen?

  • zeigen wir eine Schaltfläche zum Vorspulen, mit der der Nutzer durch die Zwischensequenzen springen kann, die er bereits gesehen hat.
  • werden im Finale verschiedene N-Elemente
  • erhöhen wir den Schwierigkeitsgrad des Schießlevels
  • In deinem dritten und weiteren Spiel zeigen wir einen kleinen Easter Egg-Drachen aus einer anderen Geschichte

Dies wird von einer Reihe von Debug-Parametern gesteuert:

  • ?doodle-debug&doodle-first-run – tu so, als wäre es ein erster Lauf
  • ?doodle-debug&doodle-second-run – tu so, als wäre es ein zweiter Run
  • ?doodle-debug&doodle-old-run – tu für einen alten Lauf

Geräte mit Touchscreen

Wir wollten, dass sich das Doodle auf Touchgeräten wie zu Hause anfühlt. Die modernsten sind leistungsfähig genug, sodass das Doodle wirklich gut läuft. Außerdem macht es viel mehr Spaß, das Spiel durch Tippen zu erleben als durch Klicken.

Es waren einige Änderungen an der User Experience erforderlich. Ursprünglich war unser Mauszeiger der einzige Ort, an dem kommuniziert wurde, dass ein Teil der Zwischensequenzen bzw. der nicht interaktive Teil stattfindet. Später haben wir einen kleinen Indikator in der rechten unteren Ecke hinzugefügt, sodass wir uns nicht nur auf den Mauszeiger verlassen mussten (da es diese auf Touch-Geräten nicht gibt).

Normal Stark besucht Anklickbar Angeklickt
In Arbeit
Normaler Zeiger „In Bearbeitung“
Hinweis zu laufenden Aufgaben
klickbarer Zeiger „In Arbeit“
Klick-Mauszeiger „In Arbeit“
Endgültige Fassung
Letzter normaler Zeigerv
Letzter Hinweis auf Beschäftigt
Letzter anklickbarer Zeiger
Zuletzt angeklickter Zeiger
Mauszeiger während der Entwicklung und endgültige Entsprechungen.

Die meisten Dinge haben sofort funktioniert. Schnelle spontane Tests zur Nutzungsfreundlichkeit unserer Touchbedienung ergaben jedoch zwei Probleme: Einige der Ziele waren zu schwer zu drücken und schnelles Tippen wurden ignoriert, da wir Mausklickereignisse gerade überschrieben haben.

Hier war die Verwendung separater anklickbarer transparenter DOM-Elemente sehr hilfreich, weil ich ihre Größe unabhängig von den visuellen Elementen anpassen konnte. Ich habe einen zusätzlichen Abstand von 15 Pixeln für Geräte mit Touchscreen eingeführt und immer dann verwendet, wenn anklickbare Elemente erstellt werden. (Ich habe auch 5-Pixel-Padding für Mausumgebungen hinzugefügt, um Mr. Fitts zufriedenzustellen.)

Für das andere Problem habe ich lediglich darauf geachtet, die richtigen Start- und End-Handler für Berührungen anzuhängen und zu testen, anstatt auf einen Mausklick zu verzichten.

Wir verwenden auch modernere Stileigenschaften, um einige Touchfunktionen zu entfernen, die von WebKit-Browsern standardmäßig hinzugefügt werden (tippe auf „Hervorheben“ und dann auf „Callout“).

Und wie wird ermittelt, ob ein bestimmtes Gerät, auf dem das Doodle läuft, Touch-Gesten unterstützt? Faulheit. Anstatt es vorab herauszufinden, haben wir einfach unsere kombinierten IQs verwendet, um abzuleiten, dass das Gerät Berührungen unterstützt... nachdem wir das erste Touch-Start-Ereignis erhalten haben.

Mauszeiger anpassen

Aber nicht alles ist berührungsbasiert. Einer unserer Leitprinzipien ist, so viele Dinge wie möglich in das Doodle-Universum zu stecken. Die kleine Seitenleisten-UI (Vorspulen, Fragezeichen), die Kurzinfo und, ja, der Mauszeiger.

Wie passe ich einen Mauszeiger an? Einige Browser ermöglichen das Ändern des Mauszeigers durch Verknüpfung mit einer individuellen Bilddatei. Dies wird jedoch nicht gut unterstützt und ist auch etwas restriktiv.

Wenn nicht, was dann? Warum machen wir einen Mauszeiger nicht einfach einen anderen Schauspieler im Doodle? Das funktioniert, hat aber eine Reihe von Vorbehalten, im Wesentlichen:

  • müssen Sie den nativen Mauszeiger entfernen können,
  • Sie müssen Ihren Mauszeiger ziemlich gut mit dem echten Zeiger synchron halten,

Ersteres ist kompliziert. CSS3 lässt cursor: none zu, wird aber auch in einigen Browsern nicht unterstützt. Wir mussten auf etwas Gymnastik zurückgreifen: die leere .cur-Datei als Fallback, die Angabe eines konkreten Verhaltens für einige Browser und sogar hartcodieren andere ohne jegliche Erfahrung.

Das andere ist auf dem Kopf relativ trivial, aber da der Mauszeiger nur ein weiterer Teil des Doodle-Universums ist, übernimmt er auch alle seine Probleme. Die größte? Wenn die Framerate des Doodles niedrig ist, ist auch die Framerate des Mauszeigers niedrig – und das hat schwerwiegende Konsequenzen, da der Mauszeiger, der eine natürliche Erweiterung Ihrer Hand ist, in jedem Fall reaktionsschnell sein muss. (Menschen, die früher Commodore Amiga verwendet haben, nicken jetzt energisch.)

Eine ziemlich komplexe Lösung für dieses Problem besteht darin, den Mauszeiger von der regulären Aktualisierungsschleife zu entkoppeln. Genau das haben wir gemacht – in einem alternativen Universum, in dem ich nicht schlafen muss. Eine einfachere Lösung dafür? Nur zum nativen Mauszeiger zurückkehren, wenn die gleitende Framerate unter 20 fps fällt. Hier kommt die rollierende Frame-Rate ins Spiel. Wenn wir auf die aktuelle Framerate reagieren würden und diese um etwa 20 fps schwingt, wird der benutzerdefinierte Mauszeiger immer ausgeblendet und angezeigt.) Damit kommen wir zu Folgendem:

Framerate-Bereich Verhalten
>10fps Verlangsamen Sie das Spiel, damit keine weiteren Frames verloren gehen.
10–20fps Verwenden Sie den nativen statt eines benutzerdefinierten Mauszeigers.
20–60fps Normaler Betrieb.
>60fps Drosseln Sie den Wert, damit die Framerate diesen Wert nicht überschreitet.
Zusammenfassung des von der Framerate abhängigen Verhaltens.

Oh, und der Mauszeiger ist auf einem Mac dunkel, auf einem PC weiß. Woran liegt das? Denn Plattformkriege brauchen selbst in fiktiven Universen Treibstoff.

Fazit

Dies ist keine perfekte Suchmaschine, aber es versucht nicht, eine zu sein. Es wurde parallel zum Lem-Doodle entwickelt und ist sehr spezifisch. Das ist in Ordnung. "Eine vorzeitige Optimierung ist die Wurzel allen Übels", wie Don Knuth bekannt sagte, und ich glaube nicht, dass es sinnvoll ist, eine Suchmaschine zuerst isoliert zu schreiben und diese erst später anzuwenden. Die Praxis bildet die Grundlage für die Theorie ebenso wie die Theorie die Praxis. In meinem Fall wurde Code weggeworfen, mehrere Teile wurden immer wieder neu geschrieben und viele gängige Inhalte wurden eher als „Ante Faktum“ gepostet. Aber letzten Endes konnten wir durch das, was wir hier haben, tun, was wir wollten: die Karriere von Stanisław Lem und die Zeichnungen von Daniel Mróz so, wie wir es uns vorstellen konnten.

Ich hoffe, dass wir Ihnen mit diesen Informationen einige der Designentscheidungen und Kompromisse aufgezeigt haben, die wir treffen mussten, und darüber, wie wir HTML5 in einem bestimmten realen Szenario verwendet haben. Probieren Sie nun den Quellcode aus und teilen Sie uns Ihre Meinung mit.

Das habe ich selbst gemacht. Das unten ging in den letzten Tagen bis in die frühen Morgenstunden des 23. November 2011 in Russland zurück. Das war die erste Zeitzone, in der das Lem-Doodle zu sehen war. Vielleicht etwas albern, aber genau wie Doodles haben Dinge, die unbedeutend erscheinen, manchmal eine tiefere Bedeutung. Dieser Zähler war ein wirklich guter "Stresstest" für die Maschine.

Screenshot der Countdown-Uhr für Lem-Doodle im Universum
Screenshot der Countdown-Uhr des Lem-Doodles im Universum

Und so kann man sich das Leben eines Google-Doodles vorstellen: Monate an Arbeit, wochenlanges Testen, 48 Stunden Backen – und all das für etwas, das die Leute fünf Minuten spielen. Jede einzelne dieser tausend JavaScript-Zeilen hofft, dass diese 5 Minuten sinnvoll genutzt werden. Viel Spaß.