Örnek Olay - Stanisław Lem Google doodle'ını oluşturma

Marcin Wichary
Marcin Wichary

Google ana sayfası, kod yazmak için ilgi çekici bir ortamdır. Bu, birçok zorlu kısıtlamayla birlikte gelir: hıza ve gecikmeye özellikle odaklanmak, her tür tarayıcıya hitap etmek ve çeşitli koşullarda çalışmak zorunda kalmak ve... evet, sürpriz ve keyif.

Bazen logomuzun yerini alan özel çizimler olan Google doodle'larından bahsediyorum. Kalem ve fırçalarla ilişkim uzun zamandır uzaklaştırma kararının ayırt edici bir tadı olsa da sık sık etkileşimli olanlara katkıda bulunuyorum.

Kodladığım (Pac-Man, Jules Verne, Dünya Fuarı) ve geliştirilmesine yardımcı olduğum birçok etkileşimli Doodle, hem gelecekçi hem de çağ dışıydı: En son web özelliklerinin hayal ürünü uygulamaları için mükemmel fırsatlar ve tarayıcılar arası uyumluluğun gerçekçi gerçekçiliği.

Her etkileşimli doodle'dan çok şey öğreniyoruz. Yakın zamanda yayınladığımız Stanisław Lem mini oyunu da bu kapsamda yer alıyor. 17.000 satırlık JavaScript koduyla doodle tarihinde ilk kez birçok şeyi denediğimiz bu oyundan da çok şey öğrendik. Bugün bu kodu sizinle paylaşmak istiyorum. Belki ilginç bir şey bulursunuz veya hatalarımı belirtirsiniz. Ayrıca bu kod hakkında biraz konuşmak istiyorum.

Stanisław Lem doodle'ının kodunu görüntüleyin »

Google'ın ana sayfasının teknoloji demosu için uygun bir yer olmadığını unutmayın. Doodle'larımızla belirli kişileri ve etkinlikleri kutlamak istiyoruz. Bunu da elimizden gelen en iyi sanat eserlerini ve en iyi teknolojileri kullanarak yapmak istiyoruz. Ancak teknolojiyi teknoloji için kutlamıyoruz. Bu, geniş anlamda anlaşılan HTML5'in hangi bölümünün kullanılabileceğini ve bu bölümün, dikkati dağıtmadan veya gölgelemeden karalamayı daha iyi hale getirip getirmediğini dikkatlice incelemek anlamına gelir.

Şimdi, Stanisław Lem doodle'ında yer alan ve almayan bazı modern web teknolojilerine göz atalım.

DOM ve tuval aracılığıyla grafikler

Tuval, bu karalamada yapmak istediğimiz tam olarak bu tür işlemler için tasarlanmış güçlü bir araçtır. Ancak önemsediğimiz eski tarayıcıların bazıları bunu desteklemiyordu. Ayrıca, mükemmel bir excanvas oluşturan kişiyle aynı ofisi paylaşsam da farklı bir yol seçmeye karar verdim.

"Rects" adlı grafik primitiflerini soyutlayan ve ardından bunları canvas veya canvas kullanılamıyorsa DOM kullanarak oluşturan bir grafik motoru oluşturdum.

Bu yaklaşımın bazı ilginç zorlukları vardır. Örneğin, DOM'da bir nesnenin taşınması veya değiştirilmesi anında sonuç verir. Buna karşılık, kanvasta her şeyin aynı anda çizildiği belirli bir an vardır. (Yalnızca bir kanvas kullanmaya, her karede kanvası temizleyip sıfırdan çizmeye karar verdim. Bir yandan çok fazla hareketli parça var, diğer yandan da örtüşen birden fazla kanvaslara bölünmeyi ve bunları seçerek güncellemeyi gerektirecek kadar karmaşık değil.)

Ne yazık ki kanvas'a geçiş, CSS arka planlarını drawImage() ile yansıtmak kadar basit değildir: DOM aracılığıyla öğeleri bir araya getirirken ücretsiz olarak sunulan bazı özellikleri kaybedersiniz. En önemlisi de z-dizinleri ve fare etkinlikleriyle katman oluşturma özelliğidir.

Z-dizinini "düzlemler" adlı bir kavramla soyutladım. Karalama, uzaktaki gökyüzünden her şeyin önündeki fare işaretçisine kadar bir dizi düzlem tanımladı ve karalamadaki her aktör hangisine ait olduğuna karar vermek zorunda kaldı (planeCorrection kullanılarak bir düzlemde küçük artı/eksi düzeltmeler yapılabiliyordu).

DOM üzerinden oluşturulan düzlemler, z-dizinine çevrilir. Ancak tuval üzerinden oluşturma işlemi yaparsak dikdörtgenleri çizmeden önce düzlemlerine göre sıralamamız gerekir. Bunu her seferinde yapmak maliyetli olduğundan, sıra yalnızca bir aktör eklendiğinde veya başka bir düzleme taşındığında yeniden hesaplanır.

Fare etkinlikleri için de bu işlemi yaptım. Hem DOM hem de tuval için, yalnızca fareyle üzerine gelme/üzerinden geçme, tıklama ve dokunma işlemlerine tepki vermek amacıyla yüksek z-endeksi olan tamamen şeffaf, yüzen ek DOM öğeleri kullandım.

Bu doodle'da dördüncü duvarı yıkmayı denemek istedik. Yukarıdaki motor, tuvale dayalı aktörleri DOM tabanlı aktörlerle birleştirmemize olanak tanıdı. Örneğin, finaldeki patlamalar hem evren içi nesneler için kanvasta hem de Google ana sayfasının geri kalanı için DOM'da yer alır. Normalde etrafta uçan ve diğer tüm aktörler gibi tırtıklı maskemizle kırpılan kuş, çekim aşamasında sorun yaşamamak için Şansımı Dene düğmesine oturur. Bunu yaparken kuşun kanvası terk edip DOM öğesi olmasını (ve daha sonra bunun tam tersini) sağlıyoruz. Ziyaretçilerimiz için bu sürecin tamamen şeffaf olmasını umuyoruz.

Kare hızı

Mevcut kare hızını bilmek ve çok yavaş (ve çok hızlı) olduğunda buna tepki vermek motorumuzun önemli bir parçasıydı. Tarayıcılar kare hızını bildirmediği için bunu kendimiz hesaplamamız gerekir.

requestAnimationFrame kullanmaya başladım. Bu yöntem kullanılamıyorsa eski setTimeout yöntemine geri döndüm. requestAnimationFrame, bazı durumlarda CPU'yu akıllıca korur (Bunun bir kısmını aşağıda açıklanacağı gibi biz de yapıyoruz.) ancak setTimeout'ten daha yüksek bir kare hızı elde etmemizi de sağlar.

Mevcut kare hızını hesaplamak basittir ancak önemli değişikliklere tabidir. Örneğin, bilgisayar bir süre boyunca başka bir uygulama tarafından işgal edildiğinde hızlıca düşebilir. Bu nedenle, yalnızca her 100 fiziksel tik için "geçişli" (ortalama) bir kare hızı hesaplarız ve buna göre kararlar alırız.

Ne tür kararlar?

  • Kare hızı 60 fps'den yüksekse hızı düşürürüz. Şu anda Firefox'un bazı sürümlerindeki requestAnimationFrame için kare hızında üst sınır yoktur ve CPU'yu boşa harcamanın bir anlamı yoktur. Diğer tarayıcılarda kare hızını 60 fps'den biraz daha yüksek yapan yuvarlama hataları nedeniyle aslında 65 fps'de sınırladığımızı unutmayın. Bu sınırı yanlışlıkla düşürmek istemeyiz.

  • Kare hızı saniyede 10 kareden azsa kareleri atlamak yerine motoru yavaşlatırız. Bu, her iki tarafın da kaybedeceği bir durumdur ancak kareleri aşırı derecede atlamanın, daha yavaş (ancak yine de tutarlı) bir oyun oynamaktan daha kafa karıştırıcı olacağını düşündüm. Bunun güzel bir yan etkisi de vardır: Sistem geçici olarak yavaşlarsa motor telafi etmek için çabalarken kullanıcı garip bir şekilde ileri atlamaz. (Pac-Man için bunu biraz farklı yaptım ancak minimum kare hızı daha iyi bir yaklaşımdır.)

  • Son olarak, kare hızı tehlikeli derecede düştüğünde grafikleri basitleştirmeyi düşünebiliriz. Fare işaretçisi hariç olmak üzere Lem doodle'ı için bunu yapmıyoruz (bu konu hakkında daha fazla bilgiyi aşağıda bulabilirsiniz). Ancak, doodle'ın daha yavaş bilgisayarlarda bile akıcı görünmesi için gereksiz animasyonlardan bazılarını kaldırabiliriz.

Ayrıca fiziksel onay ve mantıksal onay kavramlarımız da vardır. Birincisi requestAnimationFrame/setTimeout'ten gelir. Normal oyundaki oran 1:1'dir ancak hızlı ileri sarma için fiziksel tik başına daha fazla mantıksal tik ekleriz (1:5'e kadar). Bu sayede her mantıksal onay işareti için gerekli tüm hesaplamaları yapabiliriz ancak ekrandaki öğeleri güncelleyen yalnızca son onay işaretini belirleyebiliriz.

Karşılaştırma

Kullanılabilir olduğunda kanvasın DOM'dan daha hızlı olacağı varsayılabilir (ve aslında başlangıçta bu varsayılmıştı). Bu her zaman doğru değildir. Testler sırasında, Mac'te Opera 10.0-10.1 ve Linux'ta Firefox'un DOM öğelerini taşıma konusunda daha hızlı olduğunu tespit ettik.

İdeal bir durumda, karalama defteri sessizce farklı grafik tekniklerini karşılaştırır. Örneğin, style.left ve style.top kullanılarak taşınan DOM öğeleri, kanvasta çizim ve hatta CSS3 dönüşümleri kullanılarak taşınan DOM öğeleri.

– ve ardından en yüksek kare hızını verene geçin. Bunun için kod yazmaya başladım ancak en azından karşılaştırma yöntemimin oldukça güvenilir olmadığını ve çok zaman gerektirdiğini fark ettim. Ana sayfamızda bu kadar zamanımız yok. Hız bizim için çok önemli. Doodle'ın anında gösterilmesini ve oyunu tıkladığınızda veya dokunduğunuzda hemen başlamasını istiyoruz.

Web geliştirmenin özü, bazen yapmanız gerekeni yapmaktır. Kimsenin bakmadığından emin olmak için omzunun arkasına baktım ve ardından Opera 10 ile Firefox'u kanvastan kalıcı olarak kaldırdım. Bir sonraki hayatımda <marquee> etiketi olarak döneceğim.

CPU'yu koruma

Evinize gelen, Breaking Bad'in sezon finalini izleyen, sonra da sizin için finali bozan ve DVR'ınızdan silen arkadaşınız var ya? Böyle bir kişi olmak istemezsiniz, değil mi?

Evet, bu dünyanın en kötü analojisi. Ancak doodle'ımızın da bu tür bir kişi olmasını istemeyiz. Bir kullanıcının tarayıcı sekmesine izin veriliyor olması bir ayrıcalıktır. CPU döngülerini işgal etmek veya kullanıcının dikkatini dağıtmak bizi tatsız bir konuk yapar. Bu nedenle, doodle'la kimse oynamıyorsa (dokunma, fare tıklaması, fare hareketi veya tuş basma yoksa) doodle'ın sonunda uykuya geçmesini isteriz.

Ne zaman?

  • Ana sayfada 18 saniye sonra (arcade oyunlarında buna çekici mod denir)
  • Sekme odaktaysa 180 saniye sonra
  • Sekme odakta değilse 30 saniye sonra (ör. kullanıcı başka bir pencereye geçtiyse ancak etkin olmayan bir sekmede karalamayı izlemeye devam ediyorsa)
  • Sekme görünmez hale gelirse hemen (ör. kullanıcı aynı pencerede başka bir sekmeye geçtiyse - görünmüyorsak döngüleri harcamanın bir anlamı yoktur)

Sekmenin şu anda odakta olduğunu nasıl anlarız? window.focus ve window.blur'e bağlanıyoruz. Sekmenin görünür olduğunu nasıl anlarız? Yeni Page Visibility API'yi kullanıyor ve uygun etkinliğe tepki veriyoruz.

Yukarıdaki zaman aşımları, bizim için normalden daha fazla toleranslı. Bu öğeleri, çok sayıda ortam animasyonu (özellikle gökyüzü ve kuş) içeren bu doodle'a uyarladım. İdeal olarak, zaman aşımları oyun içi etkileşime göre belirlenir.Örneğin, kuş indikten hemen sonra doodle'a artık uyuyabileceğini bildirebilir. Ancak bunu uygulamadım.

Gökyüzü her zaman hareket halinde olduğundan, uykuya dalarken ve uyanırken karalama sadece durmaz veya başlamaz. Duraklatmadan önce yavaşlar ve devam ettirirken de tam tersi olur. Gerekirse fiziksel tik başına mantıksal tik sayısını artırır veya azaltır.

Geçişler, dönüştürmeler, etkinlikler

HTML'nin güçlü yönlerinden biri, her zaman kendiniz daha iyi hale getirebilmenizdir: HTML ve CSS'nin normal portföyünde yeterince iyi olmayan bir şey varsa JavaScript'i kullanarak bunu genişletebilirsiniz. Maalesef bu durumda genellikle sıfırdan başlamanız gerekir. CSS3 geçişleri harikadır ancak yeni bir geçiş türü ekleyemez veya öğeleri biçimlendirmekten başka bir şey yapmak için geçişleri kullanamazsınız. Başka bir örnek: CSS3 dönüştürme işlemleri DOM için mükemmeldir ancak kanvas'a geçtiğinizde birdenbire kendi başınıza kalırsınız.

Lem doodle'ın kendi geçiş ve dönüştürme motoruna sahip olmasının nedeni bu ve benzeri sorunlardır. Evet, 2000'ler bizi aradı, vb. biliyorum. Yerleşik olarak eklediğim özellikler CSS3'e kıyasla çok daha zayıf. Ancak motor ne yaparsa yapsın bunu tutarlı bir şekilde yapar ve bize çok daha fazla kontrol sağlar.

Basit bir işlem (etkinlik) sistemiyle başladım. Bu sistem, setTimeout kullanmadan gelecekte etkinlikleri tetikleyen bir zaman çizelgesidir. Çünkü karalama defteri zamanı, herhangi bir noktada daha hızlı (ileri sarma), daha yavaş (düşük kare hızı veya CPU'yu korumak için uykuya dalma) veya tamamen durabilir (resimlerin yüklenmesinin bitmesini bekleme).

Geçişler, başka bir işlem türüdür. Temel hareketlere ve dönmeye ek olarak, göreceli hareketleri (ör. bir nesneyi 10 piksel sağa taşıma), titreme gibi özel işlemleri ve animasyon karesi resim animasyonlarını da destekliyoruz.

Döndürmelerden bahsetmiştim. Bunlar da manuel olarak yapılır: Döndürülmesi gereken nesneler için çeşitli açılarda sprite'larımız vardır. Bunun başlıca nedeni, hem CSS3 hem de kanvas rotasyonlarının kabul edilemez bulduğumuz görsel kusurlara yol açması ve bu kusurların platforma göre değişmesidir.

Dönen bazı nesnelerin diğer dönen nesnelere bağlı olması (ör. bir robotun eli, alt kola bağlıdır ve alt kol da dönen bir üst kola bağlıdır) nedeniyle, pivotlar şeklinde basit bir transform-origin oluşturmam gerekiyordu.

Tüm bunlar, HTML5 tarafından zaten ele alınan konuları kapsayan önemli bir çalışmadır. Ancak bazen yerel destek yeterli değildir ve tekerleği yeniden icat etme zamanı gelir.

Resimlerle ve sprite'larla çalışma

Motor, doodle'ı çalıştırmak için değil, üzerinde çalışmak için de kullanılır. Yukarıda bazı hata ayıklama parametrelerini paylaştım. Kalanlarını engine.readDebugParams adresinde bulabilirsiniz.

Sprite, karalamalarda da kullandığımız, bilinen bir tekniktir. Bu sayede bayt tasarrufu yapabilir, yükleme sürelerini kısaltabilir ve ön yüklemeyi kolaylaştırabiliriz. Ancak bu, geliştirme sürecini de zorlaştırır. Görüntülerdeki her değişiklik için yeniden sprite oluşturma işlemi gerekir (genellikle otomatiktir ancak yine de zahmetli bir işlemdir). Bu nedenle motor, geliştirme için ham resimlerde ve engine.useSprites aracılığıyla üretim için sprite'larda çalıştırmayı destekler. Her ikisi de kaynak koda dahildir.

Pac-Man doodle&#39;ı
Pac-Man doodle'ında kullanılan sprite'lar.

Ayrıca, ilerleme durumunu gösteren sahte bir çubukla birlikte, resimleri önceden yüklemeyi ve resimler zamanında yüklenmezse karalamayı durdurmayı da destekliyoruz. (Maalesef HTML5 bile bir resim dosyasının ne kadarının yüklendiğini bize söyleyemediği için sahtedir.)

Sahte ilerleme çubuğunun bulunduğu yükleme grafiğinin ekran görüntüsü.
Yanlış ilerleme çubuğu içeren yükleme grafiğinin ekran görüntüsü.

Bazı sahnelerde, paralel bağlantılar kullanarak yüklemeyi hızlandırmak için değil, iOS'teki resimler için 3/5 milyon piksel sınırlaması nedeniyle birden fazla sprite kullanırız.

HTML5 bu tüm gelişmelerin neresinde? Yukarıda çok fazla yer kaplamıyor ancak spriting/kırpma için yazdığım araç tamamen yeni web teknolojilerini kullanıyordu: kanvas, blob'lar, a[download]. HTML'nin heyecan verici özelliklerinden biri, daha önce tarayıcı dışında yapılması gereken işlemleri yavaş yavaş kapsaması. Burada tek yapmamız gereken PNG dosyalarını optimize etmekti.

Oyunlar arasında durumu kaydetme

Lem'in dünyaları her zaman büyük, canlı ve gerçekçi hissettirmiştir. Hikayeleri genellikle fazla açıklama olmadan başlardı. İlk sayfa, ortada bir yerden başlardı ve okuyucunun yolunu bulması gerekirdi.

Cyberiad da bu istisnalar arasında değildi. Bu duyguyu doodle'da da yansıtmak istedik. Öncelikle hikayeyi fazla açıklamamaya çalışıyoruz. Bir diğer önemli bölüm de rastgelelik. Bu özelliğin, kitabın evrenin mekanik yapısına uygun olduğunu düşündük. Rastgelelikle ilgili birçok yerde kullandığımız çeşitli yardımcı işlevlerimiz var.

Ayrıca, yeniden oynanabilirliği başka şekillerde de artırmak istedik. Bunun için doodle'ın daha önce kaç kez tamamlandığını bilmemiz gerekiyordu. Bunun tarihsel olarak doğru teknolojik çözümü çerezdir ancak bu, Google ana sayfası için işe yaramaz. Her çerez, her sayfanın yükü artırır. Ayrıca hız ve gecikme bizim için çok önemlidir.

Neyse ki HTML5 bize Web Depolama özelliğini sunuyor. Kullanımı basit olan bu özellik, genel oynatma sayısını ve kullanıcının oynattığı son sahneyi çerezlerden çok daha kolay bir şekilde kaydetmemize ve hatırlamamıza olanak tanıyor.

Bu bilgilerle ne yapıyoruz?

  • Kullanıcının daha önce gördüğü ara sahneleri hızlıca atlamasına olanak tanıyan bir ileri sarma düğmesi gösteririz.
  • Finalde farklı N öğesi gösteriyoruz
  • Atış seviyesinin zorluğunu biraz artırdık.
  • Üçüncü ve sonraki oynatmalarınızda, farklı bir hikayeden küçük bir paskalya yumurtası olasılık ejderhası gösteririz.

Bunu kontrol eden birkaç hata ayıklama parametresi vardır:

  • ?doodle-debug&doodle-first-run – ilk çalıştırma işlemiymiş gibi davranın
  • ?doodle-debug&doodle-second-run – ikinci bir çalıştırma olduğunu varsayalım
  • ?doodle-debug&doodle-old-run – eski bir çalışmaymış gibi davranın

Dokunmatik cihazlar

Doodle'ın dokunmatik cihazlarda rahatça kullanılabilmesini istedik. En modern cihazlar, doodle'ın sorunsuz şekilde çalışması için yeterince güçlüdür. Ayrıca oyunu dokunarak oynamak, tıklayarak oynamaktan çok daha eğlencelidir.

Kullanıcı deneyiminde bazı ön değişiklikler yapılması gerekiyordu. Başlangıçta, kesme sahnesi/etkileşimli olmayan bir bölümün oynatıldığını gösteren tek yer fare işaretçimizdi. Daha sonra, sağ alt köşeye küçük bir gösterge ekledik. Böylece, dokunmatik cihazlarda fare imleci olmadığı için yalnızca fare imlecini kullanmak zorunda kalmadık.

Normal Meşgul Tıklanabilir Tıklandı
Devam eden iş
Devam eden iş normal işaretçisi
Devam eden iş için meşgul işaretçi
Devam eden iş tıklanabilir işaretçisi
Devam eden iş tıklanan işaretçi
Final
Son normal işaretçiv
Son meşgul işaretçi
Son tıklanabilir işaretçi
Son tıklanan işaretçi
Geliştirme aşamasındaki fare işaretçileri ve nihai eşdeğerleri.

Çoğu şey hemen çalıştı. Ancak dokunma deneyimimizin anlık olarak yapılan kısa kullanılabilirlik testleri iki sorun olduğunu gösterdi: Hedeflerin bazılarına basmak çok zordu ve fare tıklama etkinliklerini geçersiz kıldığımız için hızlı dokunmalar yoksayılıyordu.

Ayrı tıklanabilir şeffaf DOM öğelerine sahip olmak, bunları görsellerden bağımsız olarak yeniden boyutlandırabildiğim için çok yardımcı oldu. Dokunmatik cihazlar için 15 piksellik ek dolgu ekledim ve tıklanabilir öğeler oluşturulduğunda bunu kullandım. (Bay Fitts'i mutlu etmek için fare ortamları için de 5 piksellik dolgu ekledim.)

Diğer soruna gelince, fare tıklamasına güvenmek yerine uygun dokunma başlangıç ve bitiş işleyicilerini ekleyip test ettim.

Ayrıca, WebKit tarayıcıların varsayılan olarak eklediği bazı dokunma özelliklerini (dokunma vurgusu, dokunma açıklama metni) kaldırmak için daha modern stil özellikleri kullanıyoruz.

Doodling'in çalıştığı belirli bir cihazın dokunma özelliğini destekleyip desteklemediğini nasıl anlarız? Yavaşça. Bunu önceden anlamak yerine, ilk dokunma başlangıcı etkinliğini aldıktan sonra cihazın dokunmayı desteklediğini anlamak için ortak zekamızı kullandık.

Fare işaretçisini özelleştirme

Ancak her şey dokunmatik değildir. Doodle'un evrenine mümkün olduğunca çok şey sığdırmak, temel ilkelerimizden biriydi. Küçük kenar çubuğu kullanıcı arayüzü (ileri sarma, soru işareti), ipucu ve hatta fare işaretçisi.

Fare işaretçisini nasıl özelleştirebilirim? Bazı tarayıcılar, özel bir resim dosyasına bağlantı vererek fare imlecini değiştirmenize olanak tanır. Ancak bu yöntem yeterince desteklenmez ve biraz kısıtlayıcıdır.

Bu değilse ne? Fare işaretçisini, karalamanın bir parçası haline getirebilir miyiz? Bu yöntem işe yarar ancak bazı sakıncaları vardır. Başlıca sakıncaları şunlardır:

  • Yerleşik fare işaretçisini kaldırabilmeniz gerekir.
  • Fare işaretçinizi "gerçek" işaretçiyle senkronize tutmanız gerekir.

İlki biraz zordur. CSS3, cursor: none özelliğine izin verir ancak bu özellik de bazı tarayıcılarda desteklenmez. Bazı hileler uygulamamız gerekiyordu: Yedek olarak boş .cur dosyası kullanmak, bazı tarayıcılar için belirli bir davranış belirtmek ve hatta diğerlerini deneyimden tamamen hariç tutmak için sabit kod kullanmak.

Diğeri ise ilk bakışta önemsiz görünse de fare işaretçisi, karalamanın evrenine ait bir parça olduğundan tüm sorunlarını da devralır. En büyük sorun nedir? Karalamanın kare hızı düşükse fare işaretçisinin kare hızı da düşük olur. Elinizin doğal bir uzantısı olan fare işaretçisinin her ne olursa olsun duyarlı hissetmesi gerektiğinden bu durum ciddi sonuçlara yol açar. (Geçmişte Commodore Amiga kullananlar şimdi kafalarını şiddetle sallıyor.)

Bu sorunun biraz karmaşık bir çözümü, fare işaretçisini normal güncelleme döngüsünden ayırmaktır. Tam da bunu yaptık. Uyumaya gerek duymadığım alternatif bir evrende. Bunun için daha basit bir çözüm var mı? Kaydırma kare hızı 20 fps'nin altına düşerse yerel fare işaretçisine geri dönmeniz yeterlidir. (Bu noktada değişen kare hızı devreye girer. Mevcut kare hızına tepki verseydik ve kare hızı 20 fps civarında dalgalanmaya başlasa kullanıcı, özel fare işaretçisinin sürekli olarak gizlenip gösterildiğini görürdü.) Bu da bizi şu noktaya getiriyor:

Kare hızı aralığı Davranış
>10fps Daha fazla kare atlanmaması için oyunu yavaşlatın.
10-20 fps Özel fare işaretçisi yerine yerel fare işaretçisini kullanın.
20-60 fps Normal çalışma.
>60fps Kare hızının bu değeri aşmaması için hızı kısın.
Kare hızına bağlı davranışın özeti.

Fare imleci Mac'te koyu renkte, PC'de ise beyaz renktedir. Neden? Çünkü platform savaşları, kurgusal evrenlerde bile yakıta ihtiyaç duyar.

Sonuç

Bu motor mükemmel değildir ancak mükemmel olmaya çalışmaz. Lem doodle'ı ile birlikte geliştirildi ve bu doodle'a özeldir. Bu normaldir. Don Knuth'un meşhur dediği gibi, "Erken optimizasyon tüm kötülüklerin anasıdır". Önce bir motoru tek başına yazıp daha sonra uygulamanın mantıklı olduğunu düşünmüyorum. Uygulama, teoriyi teori kadar bilgilendirir. Benim durumumda, kod çöpe atıldı, bazı bölümler tekrar tekrar yazıldı ve birçok ortak parça, ante factum yerine post factum fark edildi. Ancak sonunda, istediğimizi yapmamıza olanak tanıyan bu çalışmayı ortaya çıkardık: Stanisław Lem'in kariyerini ve Daniel Mróz'un çizimlerini aklımıza gelen en iyi şekilde kutladık.

Yukarıdakilerin, yapmamız gereken bazı tasarım seçimlerine ve ödünlere, ayrıca HTML5'i belirli bir gerçek yaşam senaryosuna nasıl uyguladığımıza ışık tutmasını umuyoruz. Şimdi kaynak kodla oynayın, denemeler yapın ve düşüncelerinizi bizimle paylaşın.

Bunu ben yaptım. Aşağıdaki sayaç, Lem doodle'ının gösterildiği ilk saat dilimi olan Rusya'da 23 Kasım 2011'in ilk saatlerinde geri sayımı gösteriyordu. Belki de saçma bir şey ama karalamalar gibi, önemsiz görünen şeylerin bazen daha derin bir anlamı vardır. Bu sayaç, motor için gerçekten iyi bir "stres testi" oldu.

Lem doodle&#39;ındaki evren içi geri sayım saatinin ekran görüntüsü.
Lem doodle'ındaki evren içi geri sayım saatinin ekran görüntüsü.

Google Doodle'ların ömrünü bu şekilde de değerlendirebilirsiniz: Aylarca süren çalışma, haftalarca süren test, 48 saat boyunca pişirme, tüm bunlar kullanıcıların beş dakika oynayacağı bir şey için. Bu binlerce JavaScript satırının her biri, bu 5 dakikanın iyi harcanmasını ister. Keyfini çıkarın.