مطالعه موردی - ساختن Doodle Stanisław Lem Google

سلام دنیای (عجیب)

صفحه اصلی گوگل محیطی جذاب برای کدنویسی است. با محدودیت های چالش برانگیز بسیاری همراه است: تمرکز ویژه بر سرعت و تأخیر، نیاز به پاسخگویی به انواع مرورگرها و کار در شرایط مختلف، و… بله، شگفتی و لذت.

من در مورد Google doodles صحبت می کنم، تصاویر خاصی که گهگاه جایگزین لوگوی ما می شوند. و در حالی که رابطه من با قلم‌ها و قلم‌ها مدت‌هاست که طعم متمایز یک دستور بازدارنده را داشته است، من اغلب به موارد تعاملی کمک می‌کنم.

هر ابله تعاملی که کدنویسی کردم ( پک-من ، ژول ورن ، نمایشگاه جهانی ) - و بسیاری از آنها که به آنها کمک کردم - به طور مساوی آینده نگر و نابهنگام بودند: فرصت های عالی برای برنامه های کاربردی در آسمان ویژگی های پیشرفته وب... و عملگرایی سخت سازگاری بین مرورگرها.

ما از هر doodle تعاملی چیزهای زیادی یاد می گیریم، و مینی بازی اخیر Stanisław Lem نیز از این قاعده مستثنی نبود، با 17000 خط کد جاوا اسکریپت آن برای اولین بار در تاریخ doodle چیزهای زیادی را امتحان کرد. امروز، می‌خواهم آن کد را با شما به اشتراک بگذارم – شاید چیز جالبی در آنجا پیدا کنید، یا به اشتباهات من اشاره کنید – و کمی در مورد آن صحبت کنید.

مشاهده کد Doodle Stanisław Lem »

نکته ای که ارزش در نظر گرفتن دارد این است که صفحه اصلی گوگل مکانی برای نمایش های فناوری نیست. با ابله‌های خود، می‌خواهیم افراد و رویدادهای خاصی را جشن بگیریم، و می‌خواهیم این کار را با استفاده از بهترین هنر و بهترین فناوری‌هایی که می‌توانیم احضار کنیم انجام دهیم - اما هرگز فناوری را به خاطر فناوری جشن نگیریم. این به این معنی است که به دقت به هر بخشی از HTML5 که به طور کلی قابل درک است در دسترس است و اینکه آیا به ما کمک می‌کند تا doodle را بدون حواس‌پرتی از آن یا تحت الشعاع قرار دادن آن بهتر کنیم، نگاه کنیم.

بنابراین، اجازه دهید برخی از فن‌آوری‌های وب مدرن را که در Doodle Stanisław Lem جای خود را پیدا کردند – و برخی دیگر که نیافته‌اند، مرور کنیم.

گرافیک از طریق DOM و بوم

Canvas قدرتمند است و دقیقاً برای کارهایی که ما می‌خواستیم در این doodle انجام دهیم، ایجاد شده است. با این حال، برخی از مرورگرهای قدیمی‌تری که ما به آن‌ها اهمیت می‌دادیم، از آن پشتیبانی نمی‌کردند - و حتی با وجود اینکه من به معنای واقعی کلمه یک دفتر را با شخصی که یک کاوشگر عالی را گردآوری کرده به اشتراک می‌گذارم، تصمیم گرفتم راه دیگری را انتخاب کنم.

من یک موتور گرافیکی را کنار هم قرار دادم که اولیه‌های گرافیکی به نام «rects» را انتزاع می‌کند و سپس آنها را با استفاده از هر یک از بوم‌ها، DOM در صورت در دسترس نبودن بوم، رندر می‌کند.

این رویکرد با چالش‌های جالبی همراه است - برای مثال، جابجایی یا تغییر یک شی در DOM پیامدهای فوری دارد، در حالی که برای بوم یک لحظه خاص وجود دارد که همه چیز در همان زمان ترسیم می‌شود. (تصمیم گرفتم فقط یک بوم داشته باشم و آن را پاک کنم و با هر فریم از ابتدا نقاشی بکشم. از یک طرف، به معنای واقعی کلمه، قطعات متحرک بسیار زیاد است - و از سوی دیگر پیچیدگی کافی برای تقسیم شدن به چندین بوم روی هم افتاده و به روز رسانی انتخابی آنها وجود ندارد. )

متأسفانه، جابجایی به بوم به این سادگی نیست که پس‌زمینه‌های CSS را با drawImage() انعکاس دهید: هنگام کنار هم قرار دادن چیزها از طریق DOM، تعدادی از چیزهایی را که به صورت رایگان ارائه می‌شوند از دست می‌دهید - مهم‌ترین آنها لایه‌بندی با شاخص‌های z و رویدادهای ماوس.

من قبلاً شاخص z را با مفهومی به نام "صفحه ها" انتزاع کردم. ابله تعدادی صفحه را تعریف می کرد - از آسمان دورتر، تا نشانگر ماوس در جلوی همه چیز - و هر بازیگر درون ابله باید تصمیم می گرفت که به کدام یک تعلق دارد (اصلاحات کوچک مثبت/منفی در یک هواپیما با استفاده از آن امکان پذیر بود. planeCorrection ).

با رندر کردن از طریق DOM، صفحات به سادگی به z-index ترجمه می شوند. اما اگر از طریق بوم رندر می‌گیریم، باید رکت‌ها را بر اساس صفحه‌هایشان مرتب کنیم قبل از ترسیم. از آنجایی که انجام هر بار این کار هزینه بر است، سفارش تنها زمانی که بازیگری اضافه می‌شود یا زمانی که به هواپیمای دیگری می‌رود، دوباره محاسبه می‌شود.

برای رویدادهای ماوس، من آن را نیز انتزاع کردم... به نوعی. هم برای DOM و هم برای بوم، من از عناصر DOM شناور کاملا شفاف اضافی با شاخص z بالا استفاده کردم که عملکرد آنها فقط واکنش دادن به ماوس روی/خارج کردن، کلیک ها و ضربه ها است.

یکی از چیزهایی که می خواستیم با این ابله امتحان کنیم، شکستن دیوار چهارم بود. موتور فوق به ما این امکان را می دهد که بازیگران بوم را با بازیگران مبتنی بر DOM ترکیب کنیم. به عنوان مثال، انفجارهای آخر هم در بوم برای اشیاء درون جهان و هم در DOM برای بقیه صفحه اصلی گوگل هستند. پرنده که معمولاً به اطراف پرواز می کند و مانند هر بازیگر دیگری توسط ماسک دندانه دار ما قیچی می شود، تصمیم می گیرد در طول سطح عکسبرداری از مشکل دور بماند و روی دکمه I'm Feeling Lucky می نشیند. روشی که انجام می شود این است که پرنده بوم را ترک می کند و به عنصر DOM تبدیل می شود (و بالعکس بعدا) که امیدوارم برای بازدیدکنندگان ما کاملاً شفاف باشد.

نرخ فریم

دانستن نرخ فریم فعلی، و واکنش به زمانی که خیلی کند است (و خیلی سریع!) بخش مهمی از موتور ما بود. از آنجایی که مرورگرها نرخ فریم را گزارش نمی دهند، باید خودمان آن را محاسبه کنیم.

من با استفاده از requestAnimationFrame شروع کردم و در صورت در دسترس نبودن قبلی به setTimeout قدیمی باز می گردم. requestAnimationFrame به طور هوشمندانه ای CPU را در برخی موقعیت ها ذخیره می کند – اگرچه ما برخی از این کارها را خودمان انجام می دهیم، همانطور که در زیر توضیح داده خواهد شد – اما به سادگی به ما امکان می دهد نرخ فریم بالاتری نسبت به setTimeout داشته باشیم.

محاسبه نرخ فریم فعلی ساده است، اما در معرض تغییرات شدید است – برای مثال زمانی که برنامه دیگری کامپیوتر را برای مدتی درگیر کند، ممکن است به سرعت کاهش یابد. بنابراین، ما نرخ فریم چرخشی (متوسط) را فقط در هر 100 تیک فیزیکی محاسبه می کنیم و بر اساس آن تصمیم می گیریم.

چه نوع تصمیماتی؟

  • اگر نرخ فریم بالاتر از 60 فریم بر ثانیه باشد، آن را دریچه گاز می گیریم. در حال حاضر، requestAnimationFrame در برخی از نسخه‌های فایرفاکس هیچ سقف بالایی در نرخ فریم ندارد و هیچ فایده‌ای برای هدر دادن CPU وجود ندارد. توجه داشته باشید که ما در واقع 65 فریم بر ثانیه را محدود می‌کنیم، زیرا خطاهای گرد کردنی که باعث می‌شود نرخ فریم در سایر مرورگرها کمی بالاتر از 60 فریم بر ثانیه باشد – نمی‌خواهیم به اشتباه آن را کاهش دهیم.

  • اگر نرخ فریم کمتر از 10 فریم در ثانیه باشد، به جای رها کردن فریم، سرعت موتور را کاهش می دهیم. این یک پیشنهاد باخت-باخت است، اما من احساس کردم که پرش بیش از حد فریم ها گیج کننده تر از داشتن یک بازی کندتر (اما همچنان منسجم) است. یک عارضه جانبی خوب دیگر نیز وجود دارد - اگر سیستم به طور موقت کند شود، کاربر یک پرش عجیب به جلو را تجربه نخواهد کرد زیرا موتور به شدت در حال نزدیک شدن است. (من این کار را کمی متفاوت برای Pac-Man انجام دادم، اما حداقل نرخ فریم رویکرد بهتری است.)

  • در نهایت، زمانی که نرخ فریم به طور خطرناکی پایین می‌آید، می‌توانیم به ساده‌سازی گرافیک فکر کنیم. ما این کار را برای Lem doodle انجام نمی‌دهیم، به استثنای اشاره‌گر ماوس (در ادامه در مورد آن بیشتر توضیح می‌دهیم)، اما فرضاً می‌توانیم برخی از انیمیشن‌های اضافی را از دست بدهیم تا doodle حتی در رایانه‌های کندتر نیز روان باشد.

ما همچنین یک مفهوم تیک فیزیکی و یک تیک منطقی داریم. مورد اول از requestAnimationFrame / setTimeout می آید. نسبت در گیم پلی معمولی 1:1 است، اما برای فوروارد سریع، فقط تیک های منطقی بیشتری به ازای هر تیک فیزیکی اضافه می کنیم (تا 1:5). این به ما امکان می‌دهد همه محاسبات لازم را برای هر تیک منطقی انجام دهیم، اما فقط آخرین مورد را به‌عنوان یکی از موارد به‌روزرسانی روی صفحه تعیین کنیم.

محک زدن

می توان این فرض را ایجاد کرد (و در واقع در اوایل این کار) که بوم هر زمان که در دسترس باشد سریعتر از DOM خواهد بود. این همیشه درست نیست. در حین آزمایش متوجه شدیم که Opera 10.0-10.1 در مک و فایرفاکس در لینوکس در هنگام جابجایی عناصر DOM در واقع سریعتر هستند.

در دنیای بی‌نقص، doodle به‌طور بی‌صدا تکنیک‌های گرافیکی مختلف را محک می‌زند - عناصر DOM با استفاده از style.left و style.top حرکت می‌کنند، روی بوم نقاشی می‌کشند، و شاید حتی عناصر DOM با استفاده از تبدیل‌های CSS3 حرکت می‌کنند.

– و سپس به هر کدام که بالاترین نرخ فریم را داده است تغییر دهید. من شروع به نوشتن کد برای آن کردم، اما متوجه شدم که حداقل روش محک زدن من کاملاً غیرقابل اعتماد است و به زمان زیادی نیاز دارد. زمانی که در صفحه اصلی خود نداریم – ما به سرعت اهمیت زیادی می دهیم و می خواهیم که doodle فوراً نمایش داده شود و به محض کلیک یا ضربه زدن، بازی شروع شود.

در پایان، توسعه وب گاهی اوقات به انجام کاری خلاصه می شود که باید انجام دهید. به پشت شانه‌ام نگاه کردم تا مطمئن شوم هیچ‌کس به آن نگاه نمی‌کند، و بعد فقط اپرا 10 و فایرفاکس را با کد سخت از روی بوم حذف کردم. در زندگی بعدی، من به عنوان یک تگ <marquee> برمی گردم.

حفظ CPU

آیا دوستی را می شناسید که به خانه شما می آید، فصل پایانی بریکینگ بد را تماشا می کند، آن را برای شما اسپویل می کند و سپس آن را از DVR شما حذف می کند؟ شما نمی خواهید آن مرد باشید، نه؟

بنابراین، بله، بدترین قیاس تا کنون. اما ما نمی‌خواهیم doodle ما هم آن شخص باشد – این واقعیت که ما اجازه ورود به برگه مرورگر شخصی را داریم یک امتیاز است و احتکار چرخه‌های CPU یا پرت کردن حواس کاربر باعث می‌شود ما مهمان ناخوشایندی شویم. بنابراین، اگر هیچ کس با doodle بازی نمی کند (بدون ضربه، کلیک ماوس، حرکت ماوس، یا فشار دادن کلید)، ما می خواهیم که در نهایت به خواب برود.

چه زمانی؟

  • پس از 18 ثانیه در صفحه اصلی (بازی های آرکید به این حالت جذب می گویند)
  • بعد از 180 ثانیه اگر برگه فوکوس داشته باشد
  • پس از 30 ثانیه اگر برگه فوکوس نداشته باشد (مثلاً کاربر به پنجره دیگری تغییر مکان داده است، اما شاید همچنان در حال تماشای doodle در یک برگه غیرفعال است)
  • اگر برگه نامرئی شود، فوراً (مثلاً کاربر در همان پنجره به برگه دیگری تغییر مکان داده است - اگر ما دیده نشویم، چرخه‌های هدر رفته فایده‌ای ندارد)

چگونه بفهمیم که برگه در حال حاضر فوکوس دارد؟ ما خودمان را به window.focus و window.blur متصل می کنیم چگونه بفهمیم که برگه قابل مشاهده است؟ ما از API مشاهده صفحه جدید استفاده می کنیم و به رویداد مناسب واکنش نشان می دهیم.

تایم اوت های بالا برای ما بخشنده تر از حد معمول هستند. من آنها را با این ابله خاص تطبیق دادم که انیمیشن های محیطی زیادی دارد (عمدتاً آسمان و پرنده). در حالت ایده‌آل، تایم اوت‌ها به تعامل درون بازی محدود می‌شدند - به عنوان مثال، درست پس از فرود، پرنده می‌توانست به ابله گزارش دهد که اکنون می‌تواند بخوابد - اما من در پایان آن را اجرا نکردم.

از آنجایی که آسمان همیشه در حرکت است، هنگام به خواب رفتن و بیدار شدن از خواب، ابله فقط متوقف یا شروع نمی شود - قبل از مکث کند می شود و بالعکس برای از سرگیری، افزایش یا کاهش تعداد تیک های منطقی در هر تیک فیزیکی در صورت لزوم.

انتقال ها، دگرگونی ها، رویدادها

یکی از قدرت‌های HTML این بوده است که شما می‌توانید خودتان آن را بهتر کنید: اگر چیزی در مجموعه معمولی HTML و CSS به اندازه کافی خوب نیست، می‌توانید جاوا اسکریپت را برای گسترش آن به چالش بکشید. متأسفانه، اغلب به این معنی است که باید از صفر شروع کنید. انتقال‌های CSS3 عالی هستند، اما نمی‌توانید یک نوع انتقال جدید اضافه کنید یا از انتقال‌ها برای انجام کارهای دیگری غیر از عناصر استایل استفاده کنید. مثال دیگر: تبدیل‌های CSS3 برای DOM عالی هستند، اما وقتی به بوم می‌روید، ناگهان به حال خود می‌روید.

این مسائل و موارد دیگر دلیلی است که Lem doodle موتور انتقال و تبدیل خاص خود را دارد. بله، می‌دانم، سال‌های 2000 و غیره - قابلیت‌هایی که من در آن‌ها ساخته‌ام به اندازه CSS3 قدرتمند نیستند، اما هر کاری که موتور انجام می‌دهد، به طور مداوم انجام می‌دهد و به ما کنترل بسیار بیشتری می‌دهد.

من با یک سیستم کنش (رویداد) ساده شروع کردم - یک جدول زمانی که رویدادهای آینده را بدون استفاده از setTimeout نشان می‌دهد، زیرا در هر نقطه مشخصی، زمان doodle می‌تواند از زمان فیزیکی جدا شود، زیرا سریع‌تر (سریع به جلو)، کندتر (نرخ فریم پایین) یا به خواب رفتن برای صرفه جویی در CPU)، یا به طور کلی متوقف می شود (منتظر تمام شدن بارگذاری تصاویر).

انتقال ها نوع دیگری از اقدامات هستند. علاوه بر حرکات اولیه و چرخش، ما همچنین از حرکات نسبی (مثلاً حرکت دادن چیزی به اندازه 10 پیکسل به راست)، چیزهای سفارشی مانند لرزیدن و همچنین انیمیشن‌های تصویر فریم کلیدی پشتیبانی می‌کنیم.

من به چرخش‌ها اشاره کردم و آن‌ها نیز به صورت دستی انجام می‌شوند: ما برای زوایای مختلف برای اجسامی که باید بچرخند، اسپرایت داریم. دلیل اصلی این است که هر دو چرخش CSS3 و بوم، مصنوعات بصری را معرفی می کردند که به نظر ما غیرقابل قبول بود - و علاوه بر آن، این مصنوعات در هر پلت فرم متفاوت بودند.

با توجه به اینکه برخی از اشیایی که می چرخند به اجسام در حال چرخان دیگر متصل می شوند - یک مثال، دست رباتی است که به بازو پایینی متصل است، که خود به بازوی چرخان متصل است - این بدان معنی بود که من همچنین نیاز داشتم که منشاء تغییر شکل یک مرد فقیر را ایجاد کنم. از محورها

همه اینها مقدار زیادی از کار است که در نهایت زمینی را که قبلاً توسط HTML5 مراقبت شده است را پوشش می دهد - اما گاهی اوقات پشتیبانی بومی به اندازه کافی خوب نیست و زمان اختراع مجدد چرخ فرا رسیده است.

برخورد با تصاویر و جن

یک موتور فقط برای اجرای doodle نیست - بلکه برای کار روی آن نیز هست. من برخی از پارامترهای اشکال زدایی را در بالا به اشتراک گذاشتم: بقیه را می توانید در engine.readDebugParams پیدا کنید.

Spriting یک تکنیک شناخته شده است که ما نیز برای doodle از آن استفاده می کنیم. این به ما امکان می دهد بایت ها را ذخیره کنیم و زمان بارگذاری را کاهش دهیم، به علاوه بارگذاری اولیه را آسان تر می کند. با این حال، توسعه را نیز سخت‌تر می‌کند – هر تغییری در تصاویر نیاز به اسپریت مجدد دارد (عمدتاً خودکار، اما هنوز هم دست و پا گیر). بنابراین، موتور از اجرا بر روی تصاویر خام برای توسعه و همچنین sprites برای تولید از طریق engine.useSprites پشتیبانی می کند - هر دو با کد منبع گنجانده شده اند.

Doodle Pac-Man
Sprites استفاده شده توسط Pac-Man doodle .

ما همچنین از بارگیری از قبل تصاویر پشتیبانی می کنیم و اگر تصاویر به موقع بارگیری نشدند، doodle را متوقف می کنیم - با نوار پیشرفت ساختگی کامل می شود! (تقلبی چون متأسفانه حتی HTML5 هم نمی تواند به ما بگوید چه مقدار از یک فایل تصویر قبلاً بارگذاری شده است.)

تصویری از بارگیری گرافیک با نوار پیشرفت تقلبی.
تصویری از بارگیری گرافیک با نوار پیشرفت تقلبی.

برای برخی از صحنه‌ها، ما از بیش از یک اسپرایت استفاده می‌کنیم، نه برای سرعت بخشیدن به بارگذاری با استفاده از اتصالات موازی، بلکه صرفاً به دلیل محدودیت 3/5 میلیون پیکسلی برای تصاویر در iOS .

HTML5 در کجای این همه جای می گیرد؟ چیز زیادی از آن در بالا وجود ندارد، اما ابزاری که من برای spriting/cropping نوشتم، تمام فناوری جدید وب بود: بوم، حباب ، [دانلود] . یکی از چیزهای هیجان انگیز در مورد HTML این است که به آرامی کارهایی را که قبلاً باید خارج از مرورگر انجام می شد، درج می کند. تنها کاری که باید در آنجا انجام می دادیم بهینه سازی فایل های PNG بود.

ذخیره حالت در بین بازی ها

دنیای لم همیشه بزرگ و زنده و واقع گرایانه بود. داستان‌های او معمولاً بدون توضیح زیادی شروع می‌شد، صفحه اول با medias res شروع می‌شد و خواننده باید راه خود را پیدا می‌کرد.

Cyberiad نیز از این قاعده مستثنی نبود و ما می خواستیم این حس را برای doodle تکرار کنیم. ما با تلاش برای توضیح بیش از حد داستان شروع می کنیم. بخش بزرگ دیگر، تصادفی‌سازی است که ما احساس کردیم با ماهیت مکانیکی جهان کتاب مناسب است. ما تعدادی توابع کمکی داریم که با تصادفی بودن سروکار دارند که در بسیاری از مکان‌ها استفاده می‌کنیم.

همچنین می‌خواستیم قابلیت پخش مجدد را به روش‌های دیگری افزایش دهیم. برای آن، ما باید بدانیم که قبلاً چند بار doodle تمام شده است. راه حل فنی صحیح تاریخی برای آن یک کوکی است، اما برای صفحه اصلی Google کار نمی کند - هر کوکی بار بار هر صفحه را افزایش می دهد، و باز هم، ما به سرعت و تأخیر بسیار اهمیت می دهیم.

خوشبختانه، HTML5 فضای ذخیره‌سازی وب را به ما می‌دهد، که در استفاده بی‌اهمیت است، و به ما امکان می‌دهد تعداد بازی‌های کلی و آخرین صحنه بازی‌شده توسط کاربر را ذخیره و به خاطر بیاوریم - با ظرافت بسیار بیشتر از کوکی‌ها.

با این اطلاعات چه کنیم؟

  • ما یک دکمه فوروارد سریع را نشان می‌دهیم که به کاربر اجازه می‌دهد تا از طریق کات سین‌هایی که قبلاً دیده بود، فشرده شود
  • ما N آیتم های مختلف را در فینال نشان می دهیم
  • ما کمی سختی سطح تیراندازی را افزایش می دهیم
  • ما یک اژدهای احتمالی تخم مرغ عید پاک را از داستانی متفاوت در نمایشنامه سوم و بعدی شما نشان می دهیم

تعدادی پارامتر اشکال زدایی وجود دارد که این را کنترل می کند:

  • ?doodle-debug&doodle-first-run - وانمود کنید که این اولین اجرا است
  • ?doodle-debug&doodle-second-run - وانمود کنید که اجرای دوم است
  • ?doodle-debug&doodle-old-run - وانمود کنید که یک اجرای قدیمی است

دستگاه های لمسی

ما می‌خواستیم که doodle در دستگاه‌های لمسی احساس راحتی کند - مدرن‌ترین آنها به اندازه کافی قدرتمند هستند تا doodle واقعاً خوب اجرا شود، و تجربه بازی از طریق ضربه زدن بسیار سرگرم‌کننده‌تر از کلیک کردن است.

برخی تغییرات اولیه در تجربه کاربری باید انجام شود. در اصل، نشانگر ماوس ما تنها مکانی بود که ارتباط یک قسمت برش/غیر تعاملی در حال انجام است. ما بعداً یک نشانگر کوچک در گوشه سمت راست پایین اضافه کردیم، بنابراین نیازی نبود به نشانگر ماوس تنها تکیه کنیم (با توجه به اینکه این نشانگرها در دستگاه های لمسی وجود ندارند).

طبیعی مشغول قابل کلیک کلیک کرد
کار در حال انجام
نشانگر عادی کار در حال پیشرفت
نشانگر مشغول کار در حال انجام
نشانگر قابل کلیک در حال انجام
نشانگر کلیک شده در حال انجام
نهایی
اشاره گر معمولی نهایی v
نشانگر مشغول نهایی
اشاره گر نهایی قابل کلیک
نشانگر کلیک نهایی
نشانگرهای ماوس در طول توسعه، و معادل های نهایی.

اکثر چیزها خارج از جعبه کار می کردند. با این حال، آزمایش‌های کاربردی سریع و بداهه تجربه لمسی ما دو مشکل را نشان داد: فشار دادن برخی از اهداف خیلی سخت بود، و ضربه‌های سریع نادیده گرفته شدند، زیرا ما فقط رویدادهای کلیک ماوس را لغو کردیم.

وجود عناصر DOM شفاف قابل کلیک جداگانه در اینجا بسیار کمک کرد، زیرا می‌توانم اندازه آنها را مستقل از تصاویر بصری تغییر دهم. من پد 15 پیکسلی اضافی را برای دستگاه های لمسی معرفی کردم و هر زمان که عناصر قابل کلیک ایجاد می شدند از آن استفاده می کردم. (من برای محیط های ماوس نیز پد 5 پیکسلی اضافه کردم تا آقای فیتس را خوشحال کنم.)

در مورد مشکل دیگر، من فقط مطمئن شدم که به جای تکیه بر کلیک ماوس، کنترل کننده های شروع و پایان لمسی مناسب را متصل و آزمایش کردم.

ما همچنین از ویژگی‌های سبک مدرن‌تری برای حذف برخی از ویژگی‌های لمسی استفاده می‌کنیم که مرورگرهای WebKit به‌طور پیش‌فرض اضافه می‌کنند (بر روی برجسته، ضربه بزنید callout).

و چگونه تشخیص دهیم که آیا دستگاه معینی که Doodle را اجرا می کند از لمس پشتیبانی می کند یا خیر؟ تنبلی به جای اینکه آن را از قبل مشخص کنیم، فقط از ضریب هوشی ترکیبی خود برای کسر اینکه دستگاه از لمس پشتیبانی می کند استفاده کردیم... پس از دریافت اولین رویداد شروع لمسی.

سفارشی کردن نشانگر ماوس

اما همه چیز مبتنی بر لمس نیست. یکی از اصول راهنمای ما این بود که تا جایی که می‌توانیم چیزهای زیادی را در جهان ابله قرار دهیم. UI نوار کناری کوچک (سریع به جلو، علامت سوال)، راهنمای ابزار، و حتی، بله، نشانگر ماوس.

چگونه یک نشانگر ماوس را سفارشی کنیم؟ برخی از مرورگرها اجازه می دهند مکان نما ماوس را با پیوند دادن به یک فایل تصویری سفارشی تغییر دهید. با این حال، این به خوبی پشتیبانی نمی شود و همچنین تا حدودی محدود کننده است.

اگر این نیست پس چی؟ خوب، چرا یک نشانگر ماوس را فقط یک بازیگر دیگر در doodle نمی سازیم؟ این کار می کند، اما با تعدادی اخطار همراه است، به طور عمده:

  • شما باید بتوانید نشانگر موس بومی را حذف کنید
  • شما باید در هماهنگ نگه داشتن نشانگر ماوس خود با "واقعی" بسیار خوب باشید

اولی مشکل است. CSS3 اجازه cursor: none ، اما در برخی از مرورگرها نیز پشتیبانی نمی شود. ما باید به برخی از ژیمناستیک متوسل می شدیم: استفاده از فایل .cur خالی به عنوان یک بازگشت، مشخص کردن رفتار مشخص برای برخی از مرورگرها، و حتی کدگذاری سخت دیگران از تجربه.

دیگری از نظر ظاهری نسبتاً بی اهمیت است، اما با توجه به اینکه نشانگر ماوس تنها بخشی دیگر از جهان ابله است، تمام مشکلات آن را نیز به ارث خواهد برد. بزرگترین؟ اگر نرخ فریم doodle کم باشد، نرخ فریم نشانگر ماوس نیز پایین خواهد بود - و این عواقب بدی دارد زیرا نشانگر ماوس، که یک امتداد طبیعی دست شما است، باید هرچه باشد احساس پاسخگویی داشته باشد. (افرادی که در گذشته از Commodore Amiga استفاده می کردند، اکنون به شدت سر تکان می دهند.)

یک راه حل تا حدودی پیچیده برای آن مشکل جدا کردن نشانگر ماوس از حلقه به روز رسانی معمولی است. ما دقیقاً همین کار را کردیم - در یک جهان جایگزین که در آن نیازی به خوابیدن ندارم. راه حل ساده تر برای این یکی؟ اگر نرخ فریم چرخشی به زیر 20 فریم در ثانیه کاهش یابد، فقط به نشانگر اصلی ماوس برگردید. (این جایی است که نرخ فریم چرخشی مفید است. اگر ما به نرخ فریم فعلی واکنش نشان می‌دادیم، و اگر اتفاق می‌افتد که حدود 20 فریم در ثانیه نوسان کند، کاربر نشانگر سفارشی ماوس را می‌بیند که همیشه پنهان و نشان داده می‌شود.) این ما را به این موضوع می‌رساند. :

محدوده نرخ فریم رفتار - اخلاق
> 10 فریم در ثانیه سرعت بازی را کم کنید تا فریم های بیشتری افت نکند.
10-20 فریم در ثانیه از اشاره گر ماوس بومی به جای نشانگر سفارشی استفاده کنید.
20–60 فریم در ثانیه عملکرد عادی.
> 60 فریم در ثانیه دریچه گاز به طوری که نرخ فریم از این مقدار تجاوز نکند.
خلاصه رفتار وابسته به نرخ فریم.

اوه، و نشانگر ماوس ما در مک تیره است، اما در رایانه شخصی سفید است. چرا؟ زیرا جنگ های پلت فرم حتی در جهان های خیالی نیز به سوخت نیاز دارند.

نتیجه

این یک موتور کامل نیست، اما سعی نمی کند یکی باشد. در کنار Lem doodle توسعه داده شد و بسیار مختص آن است. اشکالی ندارد. همانطور که دان کنوت به قول معروف «بهینه‌سازی زودرس ریشه همه بدی‌ها است»، و من فکر نمی‌کنم که ابتدا نوشتن یک موتور به صورت مجزا، و فقط اعمال آن بعداً منطقی باشد – عمل به همان اندازه که تئوری از عمل خبر می‌دهد، به تئوری کمک می‌کند. در مورد من، کد دور ریخته شد، چندین قسمت بارها و بارها بازنویسی شد، و بسیاری از قطعات رایج به جای ante factum، متوجه پست شدند. اما در نهایت، آنچه در اینجا داریم به ما اجازه داد تا آنچه را که می‌خواستیم انجام دهیم - زندگی حرفه ای استانیسلاو لم و نقاشی‌های دانیل مروز را به بهترین شکلی که می‌توانیم فکر کنیم، جشن بگیریم.

امیدوارم موارد فوق برخی از انتخاب‌های طراحی و مبادلاتی را که باید انجام می‌دادیم روشن کند - و اینکه چگونه از HTML5 در یک سناریوی خاص و واقعی استفاده کردیم. اکنون، با کد منبع بازی کنید، آن را برای چرخش در نظر بگیرید و نظر خود را به ما بگویید.

من خودم این کار را انجام دادم - این زیر در روزهای آخر به صورت زنده بود، شمارش معکوس برای ساعات اولیه 23 نوامبر 2011 در روسیه، که اولین منطقه زمانی بود که Doodle Lem را دید. یک چیز احمقانه، شاید، اما درست مانند ابله ها، چیزهایی که بی اهمیت به نظر می رسند گاهی معنای عمیق تری دارند - این شمارنده واقعاً یک "تست استرس" خوب برای موتور بود.

تصویری از ساعت شمارش معکوس Lem doodle در جهان.
تصویری از ساعت شمارش معکوس Lem doodle در جهان.

و این یکی از راه‌های نگاه کردن به زندگی یک doodle Google است – ماه‌ها کار، هفته‌ها آزمایش، 48 ساعت پختن آن، همه برای چیزی که مردم به مدت پنج دقیقه بازی می‌کنند. هر یک از آن هزاران خط جاوا اسکریپت امیدوار است که آن 5 دقیقه زمان مناسبی باشد. لذت ببرید.