آناتومی یک بازی ویدیویی

ساخت وبلاگ

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

حال ، پذیرش ، تفسیر ، محاسبه ، تکرار

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

مشخصات آن به بازی بستگی دارد.

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

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

اما ممکن است به کنترل هر فریم احتیاج نداشته باشد. حلقه بازی شما ممکن است شبیه به Find the Fintions باشد و خود را بر روی رویدادهای ورودی قرار دهد. ممکن است به زمان ورودی و شبیه سازی شده نیاز داشته باشد. حتی ممکن است بر اساس چیز دیگری کاملاً حلقه شود.

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

ساختن یک حلقه اصلی در جاوا اسکریپت

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

برخی از کد ها باید قاب به صورت فریم اجرا شوند ، بنابراین چرا این عملکرد را به غیر از برنامه بازسازی مرورگر وصل می کنید؟در وب ، Window. RequestanimationFrame () پایه و اساس بیشترین حلقه های اصلی در هر فریم خواهد بود. در صورت فراخوانی ، یک عملکرد پاسخ به تماس باید به آن منتقل شود. این عملکرد پاسخ به تماس در زمان مناسب قبل از رنگ آمیزی بعدی اجرا می شود. در اینجا نمونه ای از یک حلقه اصلی ساده است:

پنجره.اصلی = () => پنجره.درخواست ANIMATIONFRAME(اصلی); // هر آنچه حلقه اصلی شما باید انجام دهد >; اصلی(); // چرخه را شروع کنید 

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

قطعه کد فوق دارای دو جمله است. عبارت اول تابعی را به عنوان یک متغیر جهانی به نام اصلی () ایجاد می کند. این عملکرد برخی از کارها را انجام می دهد و همچنین به مرورگر می گوید که خود را با Frame Next با Window. RequestanimationFrame () صدا کند. بیانیه دوم عملکرد اصلی () را تعریف می کند ، که در بیانیه اول تعریف شده است. از آنجا که اصلی () یک بار در بیانیه دوم خوانده می شود و هر تماس آن خود را در صف کارهایی قرار می دهد تا قاب بعدی را انجام دهد ، اصلی () با نرخ فریم شما هماهنگ می شود.

البته این حلقه کامل نیست. قبل از اینکه ما در مورد راه های تغییر آن بحث کنیم ، اجازه دهید در مورد آنچه که قبلاً به خوبی انجام می دهد بحث کنیم.

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

اما بلافاصله فرض نکنید که انیمیشن ها به کنترل قاب نیاز دارند. انیمیشن های ساده را می توان به راحتی با انیمیشن های CSS و سایر ابزارهای موجود در مرورگر به راحتی انجام داد. تعداد زیادی از آنها وجود دارد و آنها زندگی شما را آسان تر می کنند.

ایجاد یک حلقه اصلی بهتر در JavaScript

با حلقه اصلی قبلی ما دو مسئله آشکار وجود دارد: اصلی () شیء پنجره را آلوده می کند (جایی که تمام متغیرهای جهانی ذخیره می شوند) و کد مثال ما را با راهی برای متوقف کردن حلقه ترک نمی کند مگر اینکه کل برگه بسته یا تازه شود. برای مسئله اول ، اگر می خواهید حلقه اصلی فقط اجرا شود و به دسترسی آسان (مستقیم) به آن احتیاج ندارید ، می توانید آن را به عنوان یک عبارت عملکرد بلافاصله (IIFE) ایجاد کنید.

/ * * شروع با نیمه رنگ در صورتی است که هر خط کد بالاتر از این مثال * به درج خودکار نیمه رنگ (ASI) متکی است. مرورگر می تواند به طور تصادفی * فکر کند که این مثال کل از خط قبلی ادامه دارد. در صورت خالی بودن یا خاتمه دادن ، نیمه اصلی * پیشرو * آغاز خط جدید ما است.*/ ;(() =>  تابع اصلی() پنجره.درخواست ANIMATIONFRAME(اصلی); // محتویات حلقه اصلی شما > اصلی(); // چرخه را شروع کنید >)(); 

هنگامی که مرورگر با این Iife روبرو می شود ، حلقه اصلی شما را تعریف می کند و بلافاصله آن را برای قاب بعدی صف می کند. این ماده به هیچ شیء و اصلی (یا اصلی () برای روشها) ضمیمه نمی شود ، یک نام بدون استفاده معتبر در بقیه برنامه ها خواهد بود ، رایگان است که به عنوان چیز دیگری تعریف شود.

توجه: در عمل ، به جای فراخوانی CancelanimationFrame () ، جلوگیری از درخواست بعدی AnimationFrame () با یک بیانیه معمول است.

برای مسئله دوم ، متوقف کردن حلقه اصلی ، باید تماس با main () را با windows. cancelanimationframe () لغو کنید. شما باید هنگام آخرین فراخوانی ، رمزگذاری شده توسط ID را که توسط درخواست ANIMATIONFRAME () داده شده است ، عبور دهید. بگذارید فرض کنیم که عملکردها و متغیرهای بازی شما در یک فضای نام ساخته شده است که شما به آن MyGame خوانده اید. با گسترش آخرین مثال ما ، حلقه اصلی اکنون به نظر می رسد:

/ * * شروع با نیمه رنگ در صورتی است که هر خط کد بالاتر از این مثال * به درج خودکار نیمه رنگ (ASI) متکی است. مرورگر می تواند به طور تصادفی * فکر کند که این مثال کل از خط قبلی ادامه دارد. در صورت خالی بودن یا خاتمه دادن ، نیمه اصلی * پیشرو * آغاز خط جدید ما است.* * بگذارید فرض کنیم که MyGame قبلاً تعریف شده است.*/ ;(() =>  تابع اصلی() بازی من.توقفگاه=پنجره.درخواست ANIMATIONFRAME(اصلی); // محتویات حلقه اصلی شما > اصلی(); // چرخه را شروع کنید >)(); 

ما اکنون متغیری را در فضای نام MyGame خود ، که ما آن را Stopmain می نامیم ، اعلام کرده ایم ، که شامل شناسه برگشتی از جدیدترین تماس حلقه ما برای درخواست AnaryMationFrame () است. در هر نقطه ، می توانیم با گفتن مرورگر ، حلقه اصلی را متوقف کنیم تا درخواستی را که مربوط به نشانه ما است ، لغو کنیم.

پنجره.cancelanimationframe(بازی من.توقفگاه); 

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

ساختن یک حلقه اصلی بهینه تر در JavaScript

در نهایت ، در JavaScript ، مرورگر حلقه اصلی خود را اجرا می کند و کد شما در برخی از مراحل آن وجود دارد. بخش های فوق حلقه های اصلی را توصیف می کنند که سعی می کنند کنترل خود را از مرورگر دور نکنند. این روشهای اصلی خود را به Windows. RequestanimationFrame () وصل می کنند ، که از مرورگر برای کنترل قاب آینده می خواهد. این مرورگر است که چگونه می توان این درخواست ها را با حلقه اصلی خود ارتباط داد. مشخصات W3C برای درخواست ANIMATIONFRAME دقیقاً دقیقاً مشخص نمی کند که مرورگرها باید تماس های درخواست درخواست AneverAmationFrame را انجام دهند. این می تواند یک مزیت باشد زیرا فروشندگان مرورگر را برای آزمایش با راه حل هایی که احساس می کنند بهترین هستند و به مرور زمان آن را تغییر می دهند ، آزاد می کند.

نسخه های مدرن Firefox و Google Chrome (و احتمالاً دیگران) سعی می کنند در همان ابتدای Timeslice یک قاب ، تماس های برگشتی RequestAnimationFrame را به موضوع اصلی خود متصل کنند. بنابراین موضوع اصلی مرورگر سعی می کند مانند موارد زیر به نظر برسد:

  1. یک قاب جدید را شروع کنید (در حالی که قاب قبلی توسط صفحه نمایش اداره می شود).
  2. لیست تماس های درخواست درخواست ANEARYAMATIONFRAME را طی کرده و از آنها استفاده کنید.
  3. جمع آوری زباله ها و سایر کارهای هر فریم را هنگامی که تماس های فوقانی کنترل موضوع اصلی را متوقف می کنند ، انجام دهید.
  4. خواب (مگر اینکه یک رویداد چرت مرورگر را قطع کند) تا زمانی که مانیتور برای تصویر شما (VSYNC) آماده شود و تکرار شود.

شما می توانید در مورد توسعه برنامه های Realtime به عنوان بودجه زمان برای انجام کار فکر کنید. تمام مراحل فوق باید هر 16 و نیم میلی ثانیه انجام شود تا با صفحه نمایش 60 هرتز همراه باشد. مرورگرها در اسرع وقت از کد شما استفاده می کنند تا حداکثر زمان محاسبه را به آن اختصاص دهند. موضوع اصلی شما اغلب بارهای کاری را شروع می کند که حتی در موضوع اصلی نیست (مانند شلاق زدن یا سایه بان ها در WebGL). محاسبات طولانی را می توان در یک کارگر وب یا GPU همزمان با مرورگر از موضوع اصلی خود برای مدیریت جمع آوری زباله ، سایر کارهای آن یا رسیدگی به وقایع ناهمزمان انجام داد.

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

توجه: سیستم ها (سخت افزار یا نرم افزار) که قادر به دقت میکرو ثانیه نیستند ، مجاز به ارائه دقت میلی ثانیه به عنوان حداقل هستند. با این وجود آنها باید دقت 0. 001mm را ارائه دهند.

این مقدار به تنهایی خیلی مفید نیست ، زیرا این امر به یک رویداد نسبتاً جالب توجه نیست ، اما می توان آن را از یک زمان سنج دیگر کم کرد تا با دقت و دقیق تعیین کند که چقدر زمان بین این دو نقطه می گذرد. برای به دست آوردن یکی از این جدول زمانی ، می توانید با Window. Performance. now () تماس بگیرید و نتیجه را به عنوان متغیر ذخیره کنید.

محاصره کردنقوت=پنجره.کارایی.اکنون(); 

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

/ * * شروع با نیمه رنگ در صورتی است که هر خط کد بالاتر از این مثال * به درج خودکار نیمه رنگ (ASI) متکی است. مرورگر می تواند به طور تصادفی * فکر کند که این مثال کل از خط قبلی ادامه دارد. در صورت خالی بودن یا خاتمه دادن ، نیمه اصلی * پیشرو * آغاز خط جدید ما است.* * بگذارید فرض کنیم که MyGame قبلاً تعریف شده است.*/ ;(() =>  تابع اصلی(قاب) بازی من.توقفگاه=پنجره.درخواست ANIMATIONFRAME(اصلی); // محتویات حلقه اصلی شما // tframe ، از "عملکرد اصلی (tframe)" ، اکنون یک Domhighrestimamp است که توسط RAF تهیه شده است. > اصلی(); // چرخه را شروع کنید >)(); 

چندین بهینه سازی دیگر امکان پذیر است و واقعاً بستگی به این دارد که بازی شما برای انجام آن چه چیزی را انجام می دهد. ژانر بازی شما بدیهی است که تغییر خواهد کرد اما حتی می تواند ظریف تر از آن باشد. شما می توانید هر پیکسل را به صورت جداگانه روی یک بوم بکشید یا می توانید عناصر DOM (از جمله چندین بوم WebGL با پس زمینه های شفاف را در صورت تمایل) به یک سلسله مراتب پیچیده لایه کنید. هر یک از این مسیرها به فرصت ها و محدودیت های مختلف منجر می شود.

این تصمیم است ... زمان

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

توجه: تغییر نحوه برخورد حلقه اصلی شما با زمان ، یک کابوس اشکال زدایی است ، در همه جا. قبل از کار روی حلقه اصلی خود به نیازهای خود با دقت فکر کنید.

آنچه بیشتر بازی های مرورگر باید به نظر برسد

اگر بازی شما می تواند حداکثر نرخ تازه کردن هر سخت افزاری را که از آن پشتیبانی می کنید برخورد کند ، کار شما نسبتاً آسان است. شما می توانید تا VSYNC هیچ کاری انجام دهید ، و سپس هیچ کاری انجام ندهید.

/ * * شروع با نیمه رنگ در صورتی است که هر خط کد بالاتر از این مثال * به درج خودکار نیمه رنگ (ASI) متکی است. مرورگر می تواند به طور تصادفی * فکر کند که این مثال کل از خط قبلی ادامه دارد. در صورت خالی بودن یا خاتمه دادن ، نیمه اصلی * پیشرو * آغاز خط جدید ما است.* * بگذارید فرض کنیم که MyGame قبلاً تعریف شده است.*/ ;(() =>  تابع اصلی(قاب) بازی من.توقفگاه=پنجره.درخواست ANIMATIONFRAME(اصلی); به روز رسانی(قاب); // با روش بروزرسانی خود تماس بگیرید. در مورد ما ، ما به آن زمان بندی RAF می دهیم. ارائه دادن(); > اصلی(); // چرخه را شروع کنید >)(); 

اگر حداکثر نرخ تازه سازی حاصل نشود ، می توان تنظیمات کیفیت را تنظیم کرد تا در بودجه زمان شما بماند. مشهورترین نمونه این مفهوم بازی از نرم افزار ID ، Rage است. این بازی کنترل را از کاربر حذف کرد تا زمان محاسبه خود را تقریباً در 16ms (یا تقریباً 60 فریم در ثانیه) حفظ کند. اگر محاسبات خیلی طولانی طول بکشد ، وضوح ارائه شده کاهش می یابد ، بافت ها و سایر دارایی ها در بارگیری یا ترسیم و غیره ناکام می شوند. این مطالعه موردی (غیر WEB) چند فرض و تجارت را انجام داد:

  • هر قاب انیمیشن برای ورودی کاربر حساب می کند.
  • هیچ قاب لازم نیست (حدس زده شود) زیرا هر قرعه کشی به روزرسانی خاص خود را دارد.
  • سیستم های شبیه سازی اساساً می توانند فرض کنند که هر به روزرسانی کامل است~16ms از هم فاصله دارد.
  • کنترل کاربر بر تنظیمات کیفیت یک کابوس خواهد بود.
  • مانیتورهای مختلف با نرخ های مختلف ورودی: 30 فریم در ثانیه ، 75 فریم در ثانیه ، 100 فریم در ثانیه ، 120 فریم در ثانیه ، 144 فریم در ثانیه و غیره.
  • سیستمهایی که قادر به کنار آمدن با 60 فریم در ثانیه نیستند ، کیفیت بصری را از دست می دهند تا بازی را با سرعت بهینه نگه دارد (در نهایت اگر کیفیت خیلی کم شود ، به طور کامل شکست می خورد.)

راه های دیگر برای رفع نیازهای نرخ تازه سازی متغیر

روشهای دیگر مقابله با مشکل وجود دارد.

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

  • در یک setInterval () یا setTimeOut () به روز کنید.
    • این از زمان پردازنده حتی در صورت عدم تمرکز یا به حداقل رساندن ، موضوع اصلی استفاده می کند ، و احتمالاً مصنوعی از حلقه های بازی سنتی است (اما ساده است.)
    • این همان موارد فوق است ، به جز بروزرسانی موضوع اصلی را نمی کند (و همچنین نخ اصلی آن را گره نمی زند). این یک راه حل پیچیده تر است ، و ممکن است برای به روزرسانی های ساده بیش از حد سرب باشد.
    • این می خوابد تا زمانی که درخواست درخواست نامیده شود و موضوع اصلی را آلوده نمی کند ، به علاوه شما به روش های قدیمی متکی نیستید. باز هم ، این کمی پیچیده تر از دو گزینه قبلی است و شروع هر به روزرسانی مسدود می شود تا اینکه مرورگر تصمیم به آتش سوزی تماس های RAF کند.

    هر یک از این روشها دارای تجارت مشابهی هستند:

    • کاربران می توانند بسته به عملکرد آنها ، فریم های ارائه دهنده را پرش کنند یا موارد اضافی را درون یابی کنند.
    • شما می توانید روی همه کاربران که متغیرهای غیر کاشی کاری را در همان فرکانس ثابت منهای سکسکه به روز می کنند ، حساب کنید.
    • برنامه بسیار پیچیده تر از حلقه های اساسی که قبلاً دیدیم.
    • ورودی کاربر تا زمان بروزرسانی بعدی کاملاً نادیده گرفته می شود (حتی اگر کاربر دستگاه سریع داشته باشد).
    • درون یابی اجباری مجازات عملکردی دارد.

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

    هشدار: این مثال ، به طور خاص ، نیاز به بررسی فنی دارد.

    / * * شروع با نیمه رنگ در صورتی است که هر خط کد بالاتر از این مثال * به درج خودکار نیمه رنگ (ASI) متکی است. مرورگر می تواند به طور تصادفی * فکر کند که این مثال کل از خط قبلی ادامه دارد. در صورت خالی بودن یا خاتمه دادن ، نیمه اصلی * پیشرو * آغاز خط جدید ما است.* * بگذارید فرض کنیم که MyGame قبلاً تعریف شده است.* * mygame. lastrender آخرین زمان بندی درخواست شده ارائه شده را پیگیری می کند.* mygame. lasttick آخرین زمان بروزرسانی را پیگیری می کند. همیشه با طول تیک افزایش می یابد.* mygame. tickl طول چندان است که حالت بازی به روز می شود. در اینجا 20 هرتز (50ms) است.* * Timesincetick زمان بین درخواست پاسخ به تماس و آخرین به روزرسانی است.* numticks این است که چند به روزرسانی باید بین این دو قاب ارائه شده اتفاق بیفتد.* * رندر () از طریق tframe منتقل می شود زیرا فرض بر این است که روش رندر محاسبه می کند * از زمان به روزرسانی اخیراً به روزرسانی برای * برون یابی (صرفاً لوازم آرایشی برای دستگاه های سریع) محاسبه می کند. صحنه را ترسیم می کند.* * به روز رسانی () حالت بازی را از یک نقطه معین در زمان محاسبه می کند. همیشه باید * با طول کنگره افزایش یابد. این اقتدار برای حالت بازی است. آن را برای مدت زمانی که نمایانگر است ، به تصویب رسیده است (که دوباره ، همیشه * آخرین بروزرسانی + mygame. tickl طول است ، مگر اینکه یک ویژگی مکث اضافه شود ، و غیره)اجرا کن.* این فقط یک عملکرد نمونه عمومی است که ممکن است اضافه کرده باشید.*/ ;(() =>  تابع اصلی(قاب) بازی من.توقفگاه=پنجره.درخواست ANIMATIONFRAME(اصلی); محاصره کردنبعد از آن=بازی من.ثابت+بازی من.طول کنگره; اجازه دهیدnumticks= 0; // اگر tframe// اگر tframe = nextTick ، 1 تیک باید به روز شود (و غیره). // توجه: همانطور که به طور خلاصه ذکر می کنیم ، باید پیگیری کنید که تعداد NumTicks بزرگ است. // اگر بزرگ باشد ، یا بازی شما در خواب بود ، یا دستگاه نمی تواند ادامه یابد. if (قاب>بعد از آن)  محاصره کردنTimeincetick=قاب-بازی من.ثابت;numticks=ریاضی.کف(Timeincetick/بازی من.طول کنگره); > صفات(numticks); ارائه دادن(قاب);بازی من.سرپرست=قاب; > تابع صفات(numticks)  برای (اجازه دهیدمن= 0;منnumticks; i++) بازی من.ثابت+=بازی من.طول کنگره; // اکنون LastTick این تیک است. به روز رسانی(بازی من.ثابت); > >بازی من.ثابت=کارایی.اکنون();بازی من.سرپرست=بازی من.ثابت; // وانمود کنید که اولین قرعه کشی در اولین بروزرسانی بود.بازی من.طول کنگره= 50; // این شبیه سازی شما را با سرعت 20 هرتز (50ms) تنظیم می کند ستمگر(); اصلی(کارایی.اکنون()); // چرخه را شروع کنید >)(); 

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

    این ممکن است در مورد برخی از کارهای شخصی شما نیز صدق کند. این کاندیداهای خوبی هستند که در صورت وجود منابع در دسترس ، دریچه گاز می شوند.

    خلاصه

    من می خواهم واضح باشم که هر یک از موارد فوق یا هیچ یک از آنها نمی تواند برای بازی شما بهترین باشد. تصمیم صحیح کاملاً بستگی به معامله هایی دارد که شما مایل هستید (و مایل به آن نیستید). این نگرانی بیشتر با تغییر به گزینه دیگر است. خوشبختانه ، من هیچ تجربه ای در این زمینه ندارم ، اما من شنیده ام که این یک بازی فریبنده از Whack-A-Mole است.

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

    • شکاف "مکث" را در نظر بگیرید و زمان را پرش کنید.
      • احتمالاً می توانید ببینید که چگونه این مسئله برای اکثر بازی های چند نفره مشکل ساز است.
      • این می تواند یک مشکل برای قطره های طولانی و/یا به روزرسانی های پیچیده باشد.
      • این امر بی اثر است اگر همسالان یا سرور شما نیز قدیمی نباشند ، یا آنها وجود ندارند زیرا بازی تک بازیکن است و سرور ندارد.

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

      با این صفحه مشکل محتوا پیدا کرده اید؟

      • صفحه را در GitHub ویرایش کنید.
      • گزارش محتوا را گزارش دهید.
      • منبع را در GitHub مشاهده کنید.

      این صفحه آخرین بار در 23 فوریه 2023 توسط مشارکت کنندگان MDN اصلاح شد.

پلتفرم های تجاری...
ما را در سایت پلتفرم های تجاری دنبال می کنید

برچسب : نویسنده : مریم کاویانی بازدید : 24 تاريخ : سه شنبه 24 مرداد 1402 ساعت: 12:08