نوید سلطانی یک بازی دوبعدی کوچک نوشت که در آن یک پیک موتوری از میان بازار رد میشود، و روی لپتاپ خودش با ۶۰ فریم بر ثانیه اجرا میشد. روی دستگاه تازهتر یک دوستش که ۱۴۴ فریم میداد، پیک در کمتر از نصف زمان از عرض صفحه رد میشد و هر پرش از سکو جلوتر میافتاد. هیچچیز تصادفی نبود و هیچچیز خراب نشده بود: او حرکت را بر حسب پیکسل در هر فریم نوشته بود، و تعداد فریمها را ماشین تعیین میکند.
همین یک اشکال در ورودی کل این موضوع است. بازی برنامهای نیست که اجرا شود و تمام شود؛ برنامهای است که شصت بار یا بیشتر در ثانیه از آن پرسیده میشود جهان الان چه شکلی است، و هر موضوعی زیر این صفحه نتیجه بودن روی همین ساعت است. برای بازی فارسی یک بند دوم هم هست که هیچ منبعی نامش را نمیبرد و نوید همان هفته با آن روبهرو شد: خود متن.
حلقه، و بودجهای که به شما میدهد
حلقه ورودی، بهروزرسانی و رسم است، و چه چیزی اتفاق بیفتد چه نیفتد اجرا میشود. دسته را بخوان، جهان را یک برش زمان جلو ببر، یک تصویر روی صفحه بگذار، و دوباره از اول. یک واژهپرداز منتظر یک کلید میماند. بازی منتظر هیچچیز نمیماند، و فریمی که بازیکن در آن هیچ کاری نکرده هم یک دور کامل خرج برمیدارد.
آن دور یک سقف سخت دارد. بودجه هر فریم در شصت فریم بر ثانیه، ۱۶٫۷ میلیثانیه است برای همهچیز: فیزیک، تصمیم دشمنها، صدا، و رسم. از دستش بدهید فریم دیر میرسد، و بازیکن این را به شکل یک عدد نمیخواند بلکه به شکل تکان خوردن بازی میبیند. همین انضباط است که کدی که شصت بار در ثانیه اجرا میشود را از برنامهنویسی معمولی جدا میکند، جایی که تابعی با سی میلیثانیه سریع حساب میشود.
دو خطی که پرش پیک را درست کرد
تعمیرش یکی از قابلانتقالترین ایدههای این کار است. دلتا تایم: هر حرکت را در ثانیههای گذشته از فریم قبل ضرب کنید. به جای اینکه پیک هر فریم چهار پیکسل جلو برود، ۲۴۰ پیکسل در ثانیه جلو میرود و در مدت واقعی فریم قبل ضرب میشود. در ۶۰ فریم این میشود چهار پیکسل و در ۱۴۴ فریم حدود ۱٫۷ پیکسل، و پیک روی هر دو ماشین در یک زمان از عرض صفحه رد میشود.
x = x + speed * dtspeed = 240.0dt = 0.0167
نیمه دومش را تازهکارها دیرتر و دردناکتر میبینند. فیزیک با برشهای نامساوی زمان جان سالم به در نمیبرد: فریمی که غیرعادی طول بکشد به یک جسم تند اجازه میدهد از دیوار رد شود، چون در هیچ لحظهای از محاسبه داخل دیوار نبوده است. جوابش گام زمانی ثابت برای فیزیک و گام متغیر برای رسم است، یعنی شبیهسازی در برشهای یکسان جلو میرود و رسم میان آنها انجام میشود. ماشینآلات بیشتری از آنچه به نظر میرسد لازم دارد و به همین دلیل است که موتورها این کار را برای شما میکنند.
متن فارسی، که موتور آن را به شما نمیدهد
گفتوگوهای بازی نوید حرفهای جدا از هم و چپبهراست چاپ میشدند، با اینکه فونت درست انتخاب شده بود. متن فارسی در موتور هم شکلدهی میخواهد و هم جهت، و فونت هیچکدام را نمیدهد: فونت شکل هر حرف را دارد و تصمیم اینکه کدام شکل در کدام جای کلمه بنشیند و کل خط از کدام طرف چیده شود کار موتور متن است، نه کار فونت.
و بند دوم همانجاست و مستقیم به بودجه فریم وصل میشود. اطلس فونت از یک فهرست نویسه ساخته میشود، پس بازه فارسی و نیمفاصله باید در آن باشند. اطلس یک بافت است، از پیش ساخته میشود، و هر نویسهای که در فهرستش نباشد روی صفحه مربع خالی است. فهرست پیشفرض تقریباً همیشه لاتین است، پس یک بازی فارسی باید بازه را خودش اضافه کند و بعد ببیند بافتی که درآمده چقدر حافظه میگیرد، که همان معاملهای است که داراییهایی که به بودجهای ساخته میشوند که موتور تعیین کرده دربارهاش است.
یک بازی
چهار قطعه، و بازیای که یکیشان را نداشته باشد یک نمونه است
اینها نه مرحلهاند و نه دپارتمان. برداشتن یکی بازی را کوچکتر نمیکند، ناتمام میکند.
- سیستمهاقاعدهها، حلقه، و کدی که ۱۶٫۷ میلیثانیه وقت دارد اجرایشان کند
- دلیل ادامه دادناینکه بازیکن دارد چه چیزی را تصمیم میگیرد، و چرا دقیقه بعد ارزش دارد
- داراییها، به اندازه بودجهاطلس فونت و بافتها، که پیش از هر تصمیم سلیقهای با حساب تعیین میشوند
- ده درصد آخرمنو، ذخیره، تنظیمات و بیلد فروشگاه، که نصف تقویم است
قطعهها از نظر ساعت برابر نیستند. چهارمی معمولاً به اندازه سه تای دیگر روی هم وقت میگیرد و همانی است که تقریباً در هر پروژه رهاشدهای غایب است.
موتور واقعاً برای چیست، و ترتیبی که جواب میدهد
موتور میانبر ساختن بازی نیست. جواب هر چیزی در یک بازی است که خود بازی نیست: پنجره، دسته، میکس صدا، خط لوله دارایی، فیزیک، و خروجی گرفتن برای چند پلتفرم. فریمورکهایی که همهچیز را جز خود بازی شما اداره میکنند دقیق نامگذاری شده و همین نامگذاری نکته است. چیزی که نمیدهد دلیل بازی کردن است، و آن تمام محتوای تصمیم گرفتن اینکه بازیکن چه میکند، و چرا ادامه میدهد است.
ترتیبی که جواب میدهد یک چیز کوچک تمامشده است، بعد یک چیز بزرگتر. برعکسش شکل مشخصی دارد: پروژه اول ایدهای است که یک استودیو چهار سال رویش کار میکند، و درست جایی رها میشود که بخش جالبش تمام شده و باقیاش منو و ذخیره و تنظیمات صداست. عوض کردن موتور هم بعداً یک انتقال نیست، بازنویسی همهچیز است جز هنر و ایده، پس آن تصمیم را زودتر و آگاهانه بگیرید.
جایی که کار میایستد: دامنه، و بعد ده درصد آخر
ایست اول دامنه است و تقریباً همگانی است. کسانی که منتشر میکنند آنهاییاند که پروژه اولشان آنقدر کوچک بوده که بخش کسلکنندهاش دو هفته طول کشیده، نه دو سال. نوید بازی پیک را عمداً به یک محله بازار محدود کرد و همان تصمیم بود که باعث شد تمام شود.
ایست دوم ده درصد آخر است که واقعاً نصف کار است، و برای خواننده اینجا یک لایه اضافه دارد: بیلد فروشگاه، اعلامیه حریم خصوصی، و اینکه فروشگاهی که واقعاً به آن میرسید همان فروشگاه موبایل داخلی است، نه ویترینهایی که در ویدیوهای آموزشی میبینید. اینها همه در فروشگاهها، بیلدها، تست بازیکن، و ده درصد آخر جمعاند، و بخش انتشارش همان چیزی است که برنامههایی روی دستگاهی که آدمها با خود میبرند دربارهاش صریح است.
سه موتوری که در ۲۰۲۶ باز میکنید
Godot گزینه رایگان بدون هیچ شرط درآمدی است، متنباز است، و از ۲۰۲۳ سهم بزرگی از کار دوبعدی را گرفت، وقتی رقیب تجاری اصلیاش کارمزد به ازای هر نصب را اعلام کرد و بعد پس گرفت. برای خواننده این صفحه یک دلیل فنی هم دارد که مهمتر از آن است: از Godot 4 در ۲۰۲۳ شکلدهی خط عربی و چیدمان راستبهچپ داخل خود موتور است، پس دو بند بالا آنجا از قبل حل شدهاند.
Unity هنوز گستردهترین گزینه از نظر تعداد آگهی شغلی و پشتیبانی پلتفرم است و زیر یک آستانه درآمدی رایگان است. اینجا باید صریح بود: هم آن آستانه و هم فروشگاه داراییاش یک رابطه پرداخت میخواهند که از ایران مستقیم برقرار نمیشود، پس بخشی از چیزی که در آموزشهای فارسی نشان داده میشود عملاً در دسترس شما نیست. Unreal جواب کار سهبعدی سطح بالاست و به جای حق پروانه، بالای یک آستانه درصد میگیرد، که همان رابطه را لازم دارد.
هر سه جای نوشتن موتور را گرفتند، که تا حدود ۲۰۱۰ معنی یک پروژه بازی بود و حالا انتخابی عمدی است برای یاد گرفتن همان لایه. برای بازی اول تقریباً همیشه انتخاب درست آن است که کوتاهترین راه را به چیزی قابل بازی کردن دارد، و دلیلش همان چیزی است که در بقیه برنامهنویسی، از اولین متغیر تا سیستمی که بالا آمده است هم درست است: یک چیز کوچک تمامشده بیشتر یاد میدهد تا یک چیز بزرگ نیمهکاره.
آنچه هیچکدام از اینها تعیین نمیکنند این است که آن چیز اصلاً خوب هست یا نه، که با استدلال معلوم نمیشود و فقط با تماشا کردن معلوم میشود: در یک اتاق، از پشت شانه کسی، بیآنکه چیزی بگویید. و اگر پرسش برگشت به اینکه چرا آن ۱۶٫۷ میلیثانیه پر شد، جوابش در ایدههایی که با عوض شدن زبان از بین نمیروند است.