این مطلب مربوط به تجربه مطالعه کتاب Game Programming Patterns نوشتهی رابرت نایستروم میباشد. این کتاب یکی از شناختهشدهترین کتابها در حوزه معماری و طراحی نرمافزار برای بازیهای ویدیویی است و با استفاده از مثالهای واقعی از توسعه بازی، الگوهای طراحی مختلف را معرفی میکند.
دلیل انتخاب این کتاب، علاقه و فعالیت اصلی من در حوزه بازیسازی بود. بیشتر تجربه برنامهنویسی من مربوط به توسعه بازی و پیادهسازی سیستمهای Gameplay و هوش مصنوعی است. به همین دلیل، احساس میکردم مطالعه کتابی که مستقیماً از مسائل واقعی توسعه بازی صحبت میکند، برایم مفیدتر از مطالعه کتابهای معماری عمومی خواهد بود. علاوه بر این، بارها نام این کتاب را در بین برنامهنویسان بازی شنیده بودم و مدت زیادی بود که قصد خواندن آن را داشتم.
از این کتاب فصلهای Architecture, Performance, and Games، Component، Event Queue، Observer، Command، State، Service Locator و Object Pool را مطالعه کردم.
تجربه خواندن این کتاب برای من با بسیاری از کتابهای فنی دیگر متفاوت بود. معمولاً هنگام خواندن کتابهای معماری نرمافزار، مثالها مربوط به سیستمهای بانکی، فروشگاههای اینترنتی یا نرمافزارهای سازمانی هستند و گاهی ارتباط دادن آنها به بازیسازی دشوار است. اما در این کتاب تقریباً هر مثال به مشکلی اشاره میکند که یک برنامهنویس بازی احتمالاً با آن مواجه شده است؛ از کنترل شخصیت و مدیریت انیمیشنها گرفته تا سیستم صوتی، مدیریت حافظه و طراحی رفتار دشمنان.
در همان فصل ابتدایی، بخشی که بیش از همه توجه من را جلب کرد، تأکید نویسنده بر سادگی بود. به عنوان یک برنامهنویس، بارها وسوسه شدهام که از همان ابتدا سیستمها را بسیار انعطافپذیر و عمومی طراحی کنم تا برای هر نیاز احتمالی آینده آماده باشند. اما نویسنده بارها تأکید میکند که معماری بیش از حد میتواند به اندازه نداشتن معماری مضر باشد. این بخش باعث شد به برخی تصمیمهای گذشته خودم در پروژههای بازی فکر کنم؛ پروژههایی که در آنها زمان زیادی صرف طراحی سیستمهای بسیار عمومی کرده بودم، در حالی که شاید هنوز نیازی به آن پیچیدگی وجود نداشت.
هنگام مطالعه فصل Component، بارها به سیستمهایی که در پروژههای خودم نوشتهام فکر میکردم. توصیف کلاسهای بزرگ و چند هزار خطی که به مرور مسئولیتهای مختلف را به خود جذب میکنند، برایم کاملاً آشنا بود. احساس میکردم نویسنده دقیقاً مشکلاتی را توصیف میکند که هر برنامهنویس بازی بعد از مدتی با آنها مواجه میشود. این موضوع باعث شد فصل Component را با دقت بیشتری بخوانم و حتی بعد از پایان فصل، مدتی به ساختار برخی از سیستمهای فعلی پروژه خودم فکر کنم.
در فصل Event Queue، چیزی که برایم جالب بود این بود که نویسنده فقط درباره تمیزتر شدن معماری صحبت نمیکند، بلکه دائماً محدودیتهای واقعی توسعه بازی را نیز در نظر میگیرد؛ محدودیتهایی مانند عملکرد، استفاده از Threadهای مختلف و هزینههای مدیریت حافظه. همین نگاه عملی باعث شد احساس کنم کتاب توسط کسی نوشته شده که واقعاً سالها در صنعت بازی کار کرده است، نه صرفاً یک نویسنده دانشگاهی.
فصل Observer نیز تجربه مشابهی داشت. هنگام خواندن مثال سیستم Achievement، بلافاصله به سیستمهایی که خودم در بازیها پیادهسازی کردهام فکر کردم؛ سیستمهایی که به مرور وابستگیهای زیادی پیدا میکنند و تغییر آنها دشوار میشود. جالبترین بخش این فصل برای من، توضیح مشکلات و معایب الگو بود. در بسیاری از منابع آموزشی، الگوهای طراحی تقریباً بدون ایراد معرفی میشوند، اما این کتاب دائماً تأکید میکند که هر راهحل جدید، مشکلات جدیدی نیز به همراه میآورد.
از بین تمام فصلهایی که مطالعه کردم، فصل State بیش از همه برایم جذاب بود. احتمالاً دلیل آن این است که در بازیسازی دائماً با طراحی رفتار کاراکترها و دشمنان سر و کار داریم. هنگام خواندن مثال Heroine و اضافه شدن تدریجی قابلیتهای جدید، بارها به یاد کدهایی افتادم که با اضافه شدن ویژگیهای جدید، به مرور پر از شرطها و حالتهای مختلف شده بودند. احساس میکردم مثالهای کتاب صرفاً مثالهای آموزشی نیستند، بلکه از مشکلات واقعی و تجربههای عملی نویسنده به وجود آمدهاند.
فصل Service Locator نیز برایم جالب بود، زیرا برخلاف بسیاری از مطالب اینترنتی که این الگو را یا کاملاً خوب و یا کاملاً بد معرفی میکنند، نویسنده دیدگاه متعادلتری دارد. او نشان میدهد که چرا این الگو به وجود آمده، چه مزایایی دارد و در عین حال در چه شرایطی میتواند به یک متغیر سراسری پنهان تبدیل شود. این رویکرد واقعگرایانه تقریباً در تمام کتاب دیده میشود.
در نهایت، فصل Object Pool یکی از فصلهایی بود که بیشترین ارتباط را با تجربههای شخصی من داشت. در توسعه بازی، مخصوصاً در سیستمهایی مانند افکتها، پرتابهها و ذرات، موضوع مدیریت حافظه و ایجاد و حذف مداوم اشیاء اهمیت زیادی دارد. هنگام خواندن این فصل، چند بار به پیادهسازیهایی که قبلاً انجام داده بودم فکر کردم و متوجه شدم چرا بسیاری از موتورهای بازی تا این اندازه روی استفاده مجدد از اشیاء تأکید میکنند.
به طور کلی، تجربه خواندن این کتاب برای من بیشتر از آنکه شبیه یاد گرفتن چند الگوی طراحی جدید باشد، شبیه گفتوگو با یک برنامهنویس باتجربه بازی بود که مشکلات واقعی توسعه بازی را توضیح میدهد و تجربههای خود را در قالب الگوهای مختلف به اشتراک میگذارد. چیزی که بیش از همه از این کتاب در ذهنم باقی ماند، خود الگوها نبودند، بلکه شیوه فکر کردن نویسنده درباره طراحی نرمافزار بود؛ اینکه هر تصمیم معماری یک هزینه دارد، هیچ راهحل کاملی وجود ندارد و سادگی و عملگرایی در بسیاری از مواقع ارزش بیشتری از پیچیدگی و انتزاع بیش از حد دارند.
اين مطلب، بخشی از تمرينهای درس معماری نرمافزار در دانشگاه شهيد بهشتی است.