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

در این مطلب از مجله فرادرس به بررسی ساخت بازی با سی شارپ پرداختهایم. زبان سیشارپ کاربردهای متنوعی دارد. هر حوزه هم شامل تخصصها و ابزارهای مخصوص به خود است. بنابراین در بخش انتهای هم چند مورد از ابزارها یا موتورهای بازیسازی با سیشارپ را معرفی کردیم. علاوه بر این موارد، به عنوان تمرین، روش پیادهسازی دو بازی دوز و پازل تصویری را به کمک سی شارپ توضیح دادهایم.
چگونه از سی شارپ در ساخت بازی استفاده میشود؟
از زبان سی شارپ در بخشهای مختلف توسعه بازی استفاده میشود. برای مثال میتوان به موتورهای بازیسازی، ابزارها و اسکریپتها اشاره کرد. تعداد زیادی از موتورهای بازیسازی مانند Unity و Godot از زبان سی شارپ به عنوان اولویت اول برای اسکریپتنویسی استفاد میکنند. برای مثال در Unity برای تعریف منطق بازی، رابطهای کاربری و سایر سیستمهای بازی از #C، استفاده شده است. در صورت تمایل به آموزش حرفهای این رشته میتوانید فیلم آموزش ساخت بازی با سی شارپ را از فرادرس مشاهده کنید. لینک مربوط به این فیلم را در پایین نیز قرار دادهایم.
کاربرد دیگر سی شارپ در توسعه بازیها، ساخت ابزارهای سفارشی است. به عنوان نمونهای از این ابزارها میتوان به «ویرایشگرهای سطح» (Level Editors) در بازی و «سیستمهای مدیریت دارایی» (Asset Management Systems) اشاره کرد. این ابزارها فرایند توسعه بازی را سریعتر و راحتتر میکنند. در ضمن، کارآمدی تیم توسعه بازی را نیز بیشتر میکنند.

از سی شارپ برای نوشتن اسکریپتهای بازی هم استفاده میشود. اسکریپت به تکههای کوچکی از کدها گفته میشود که باید در زمانهای خاصی از جریان بازی اجرا شوند. مانند زمانی که کاراکتر بازی ضربه میخورد. میتوان این اسکریپتها را با زبان سی شارپ نوشت و توسط موتور بازیسازی اجرا کرد. در نتیجه توسعهدهندگان میتوانند ویژگیهای بازیهای خود را بهسادگی تغییر داده یا ویژگی جدیدی به آن اضافه کنند.
استفاده از سی شارپ برای ساخت سازوکارهای بازی
«مکانیک بازی | سیستم تعامل بازیکن و بازی» (Game Mechanics) اصول و قواعدی هستند که روش کار بازی را تعیین میکنند. برای ساخت این سازوکارها با استفاده از #C، از مواردی مانند متغیرها، متدها و توابع استفاده میکنیم. توسعهدهندگان با کمک این موارد، رفتار بازی را تعریف میکنند.
برای مثال، در بازیهای «پلتفرمر» (PlatFormer)، توسعهدهندگان میتوانند از #C برای تعریف حرکت کاراکتر بازی استفاده کنند. در اینباره چند مثال ساده را در فهرست زیر نوشتهایم.
- آنها از متغیرها برای ذخیره کردن موقعیت بازیکن استفاده میکنند.
- از متدها برای مدیریت دادههای ورودی صفحه کلید یا دسته بازی استفاده میکنند.
- توابع به محاسبه حرکت از طریق قوانین فیزیک و «تشخیص برخورد» (Collision Detection) کمک میکنند.
در ادامه مطلب، با پیادهسازی دو بازی مختلف، کارآمدی و روش استفاده از سی شارپ را برای ساخت بازی به صورت عملی بررسی کردهایم.
ساخت بازی دوز در سی شارپ
در این قسمت، روش ساخت بازی دوز را با کمک سی شارپ ارائه کردهایم. برای انجام این کار از «IDE» ویژوال استودیو استفاده میکنیم. در این مطلب از ابزار «Windows Form» استفاده کردهایم. با کمک این ابزار، توابع خود را به دکمههای بازی متصل میکنیم. در این بازی از رقیب کامپیوتری استفاده کردهایم. هدف ما در این بازی ساخت مدل هوشمند و سادهای است که در مقابل کاربر، بازی کند. استفاده از این مدل نه تنها نباید زحمت تولید بازی را بیشتر کند، بلکه باید بازی را سرگرمکنندهتر نیز بکند.
برای شروع، ابتدا ویژوال استودیو را باز میکنیم.

پروژه جدیدی در ویژوال استودیو تعریف میکنیم. در زیر زبان برنامه نویسی #C، گزینه Windows Form App را انتخاب میکنیم. نام پروژه را «tictactoe» گذاشته و بر روی «OK» کلیک میکنیم.

این پروژه در فولدر «Documents» ذخیره میشود. سپس در فولدر «Visual Studio»، داخل فولدر «Projects» نیز ذخیره میشود.
ساخت صفحه بازی
اکنون باید فرم جدیدی ایجاد کرده و سپس مطابق با تصویر زیر، تنظیمات فرم جدید را پیکربندی کنیم.

حتما مقدار مربوط به ردیف «اندازه» (Size) را بر روی «718 ,687» تنظیم کنید. در بخش مربوط به «متن» (Text) عبارت «Tic Tac Toe » را اضافه کنید.

نتیجه نهایی، ساخت فرمی به شکل تصویر بالا است.
اکنون باید عناصر مورد نظر خود را به بازی اضافه کنیم. از نوارابزار، دو «برچسب» (Label) انتخاب میکنیم. البته میتوانیم از یک برچسب هم دوبار استفاده کنیم. برای این کار، فقط باید برچسبها را کشیده و بر روی فرم رها کنیم.

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

در صفحه تنظیمات و در پایین بخش فونت بر روی سه نقطه «…» کلیک میکنیم. اکنون کادر مربوط به تنظیمات فونت – مانند تصویر زیر – باز شده است.

در این بخش اندازه فونت را بر روی ۱۲ قرار داده و ظاهر آن را «درشت» (BOLD) میکنیم. سپس بر روی دکمه OK کلیک میکنیم.
متن برچسب «label1» را برابر با «Player Wins – 0» و متن برچسب «label2» را برابر با «AI Wins – 0» قرار میدهیم. رنگ متن «fore colour» را در برچسب «label1» برابر با سبز یا «green» و رنگ متن برچسب «label2» را برابر با قرمز «red» قرار میدهیم.

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

برای شروع، دکمهای را از نوارابزار کشیده و بر روی فرم بازی، رها میکنیم.
در بخش تنظیمات دکمه، اندازه آن را بر روی «177, 160» و «برچسب» (Tag) آن را با کلمه play مقداردهی میکنیم. مقدار تنظیمات متغیر Font را هم مانند دفعه پیش – بر روی سه نقطه کلیک کرده – برابر با مقادیر «Microsoft Sans Serif, 36pt, style Bold» تنظیم میکنیم.

در نهایت دکمه باید شبیه به تصویر بالا باشد.

اکنون برای اینکه چیدمان فرم مانند تصویر بالا شود، فقط کافیست دکمه مورد نظر را کپی کرده و ۸ بار بر روی فرم پیست کنیم.

یک دکمه دیگر هم به صفحه بازی اضافه کنید. وارد تنظیمات این دکمه شده و مقدار مقابل متغیر Text را برابر با Restart قرار دهید. این دکمه برای ریست کردن سایر دکمههای بازی به کار برده میشود. به دکمه Restart هیچ برچسبی اضافه نکنید.
افزودن زمانسنج به بازی
میخواهیم عنصر زمانسنجی هم به این فرم اضافه کنیم. بنابراین از نوارابزار، گزینه «زمانسنج» (Timer) را انتخاب کرده و بر روی فرم قرار میدهیم. برای انجام این کار هم میتوانیم از تکنیک کشیدن و رها کردن استفاده کنیم.

مطابق با تصویر زیر، در پنجره «Properties»، تنظیمات نشان داده شده را بر روی عنصر زمانسنج، پیکربندی میکنیم. نام این عنصر را به AImoves تغییر داده و مقدار «Interval» را برابر با 1000 میگذاریم.

تعریف رویدادهای بازی
اکنون باید رویدادهای بازی را به آن اضافه کنیم. بنابراین ابتدا تمام دکمههای با علامت سوال را در فرم انتخاب کرده و سپس پنجره مربوط به رویدادها «Events Window» را باز میکنیم.

وقتی که تمام دکمهها انتخاب شدند، بر روی آیکون شبیه به رعدوبرق در پایین پنجره تنظیمات «Properties» کلیک میکنیم. در بخش پایینِ تصویر بالا این آیکون دیده میشود. انجام اینکار باعث باز شدن پنجره «Events Window» میشود.
در پنجره رویدادها، میتوانیم رویداد «Click» را پیدا کنیم. مقدار این «رویداد» (Event) را بر روی playerClick تنظیم کرده و سپس دکمه اینتر را فشار میدهیم.

سپس بر روی شیء زمانسنج «AImoves» کلیک میکنیم.

همانند مرحله قبل، در پنجره رویدادها عبارت AImoves را نوشته و سپس دکمه اینتر را فشار میدهیم. توجه کنید که نام زمانسنج همراه با «s» و به صورت «AImoves» آمده است. اما در نام رویداد این حرف «s» وجود نداشته و به صورت ساده «AImove» نوشته شده است.

اکنون دکمه Restart را با کلیک کردن انتخاب میکنیم.

سپس به «پنجره رویدادها» (Events Window) رفته و آنجا رویداد Click را پیدا میکنیم. در مقابل این رویداد عبارت «restartGame» را نوشته و دکمه اینتر را میزنیم.

اکنون تمام رویدادها را تنظیم کردهایم. نوبت به کدنویسی بازی رسیده است.
شروع کدنویسی بازی
ابتدا وقتی که به صفحه کدهای مربوط به فرم بازی میرویم کدها به شکل زیر نوشته شدهاند. توابع تعریف شده در این کدها بر اساس عناصر تعریف شده در فرم و به صورت خودکار ساخته شدهاند.
در کدهای زبان برنامه نویسی سی شارپ، خطوطی که با نماد // شروع میشوند، کامنت هستند. این کامنتها هیچ تاثیری در روند اجرای برنامه ندارند. اما وجود آنها به سازماندهی هرچه بهتر کدها کمک میکند. استفاده از کامنتها یکی از عادتهای خوب در برنامه نویسی است. اکنون کدهای علامت گذاری شده در پایین را به بخش کدهای بازی اضافه میکنیم.
نکته: حتما به قراردادن آکولادها در جای صحیح خود توجه کنید.
ساختار «public enum Player» نوعی ساختار داده است که به این کد اضافه کردهایم. این ساختار، شامل دو مقدار «X» و «O» است. این ساختار داده برای جابهجایی نمادها بین بازیکنان به کار برده میشود. بازیکن از بین X و O فقط میتواند یک مورد را انتخاب کند. بنابراین استفاده از نوع enum امکان انتخاب از بین این گزینهها را سادهتر میکند.

به محض شروع شدن بازی، خط resetGame() از درون تابع Public Form1() اجرا میشود. این مسئله به بازیکنان کمک میکند، بلافاصله بازی را شروع کنند. در پایین کدها سه تابع دیگر هم دیده میشوند.
- loadButton
- resetGame
- check
هر کدام از این توابع، هدف مخصوص به خود را در بازی دنبال میکنند. در ادامه همین مطلب، روش استفاده از سه تابع معرفی شده را نیز توضیح دادهایم.
متغیرهای بازی
همینطور که در کدهای زیر مشاهده میکنید، برای هر متغیر، کامنتی نوشته شده است. این کامنتها کاربرد و وضعیت متغیرها را توضیح میدهند. با توجه به مطالبی که تا به اینجا یاد گرفتهایم، اکنون بهخوبی نقش و وظیفه هر متغیر را درک میکنیم.
خطوط کد نوشته شده در کادر بالا را به ترتیب در فهرست زیر توضیح دادهایم.
- خط اول – Player currentPlayer: این خط، کلاس Player را فراخوانی میکند. کلاس Player را در بخشهای قبلی با مقادیر X و O تعریف کردهایم.
- خط دوم- List<Button> buttons: این کد، متغیری را از نوع لیست، تعریف میکند. از این متغیر در طول بازی استفاده خواهیم کرد. متغیر لیست، نوعی از آرایهها است که دکمههای بازی را در آن ذخیره میکنیم. در زمان بازی، بازیکن کامپیوتری با کمک این لیست میتواند یکی از دکمهها را انتخاب کند.
- خط سوم- Random rand = new Random(): با کمک این خط کد، میتوانیم در بازی عدد تصادفی بسازیم. با استفاده از این اعداد، بازیکن کامپیوتری میتواند در نوبت خود یکی از دکمهها را به صورت تصادفی انتخاب کند.
- خط چهارم و پنجم – int playerWins و int computerWins: هر دو متغیر int playerWins و int computerWins از نوع عدد صحیح هستند. مقدار این متغیرها از 0 شروع میشود. هر کدام از آنها به ترتیب تعداد برد کاربر و کامپیوتر را میشمارند.
تعریف توابع مربوط به دکمههای بازی
در کادر پایین، تابع loadButtons را تعریف کردهایم. در این تابع، تمام دکمههای قابل استفاده در بازی را در لیست دکمهها buttons - تعریف شده در بالا – اضافه کردیم.
توجه: دکمه button9 همان دکمه ریست بازی است. این دکمه را به لیست بالا اضافه نمیکنیم. زیرا نیازی به انجام این کار وجود ندارد.
در کادر زیر هم تابع مربوط به دکمه Restart را تعریف کردهایم.
برای اجرای رویداد ریست کردن بازی باید تابع restartGame را تعریف کنیم. تعریف این تابع را در کادر بالا مشاهده میکنید. وقتی که دکه ریست، کلیک شد، تابع resetGame فعال شده و بازی را از اول شروع میکند.

در کادر زیر، تابع resetGame را پیادهسازی کردهایم.
در تابع بالا از حلقه for-each استفاده کردهایم. این حلقه تمام مهرههایی را که در آنها مقدار TAG مساوی با “PLAY” است، بررسی میکند. سپس همه آنها را به حالت اولیه – در شروع بازی – برمیگرداند. عملیات تابع resetGame را در فهرست زیر نوشتهایم.
- ابتدا همه دکمهها را فعال میکند.
- سپس مقدار Text یا نوشته روی دکمهها را برابر با علامت سوال «“?» قرار میدهد.
- رنگ پسزمینه را به رنگ پیشفرض دکمهها تغییر میدهد.
بعد از اجرای دستورات بالا باید تابع loadbuttons() را برای بارگذاری دکمهها اجرا کنیم. اجرای این تابع تمام دکمههای قابل استفاده در بازی را به لیست دکمههای List<Button> اضافه میکند.
در کادر زیر، تابع playerClick را تعریف کردهایم. هر دکمه به یک رویداد یا Event خاصی متصل شده است. بعد از کلیک کردن بر روی دکمهها باید این رویدادها اجرا شوند. تابع playerClick وظیفه اجرای رویدادها را بر عهده دارد.
در کادر بالا رویداد کلیک کردن را توسط بازیکن تعریف کردهایم. هربار که بازیکن بر روی یکی از دکمهها کلیک کند، این رویداد فعال میشود.
در پایین فرایند اجرای کدهای کادر بالا را توضیح دادهایم.
- خط سوم – var button = (Button)sender; : ابتدا یک «متغیر محلی» (Local Variable) به نام button ایجاد میکنیم. از بیرون تابع نمیتوان به این متغیر دسترسی داشت. در نتیجه متغیر تعریف شده امنیت بالایی دارد و فقط دستور نوشته شده در تابع را اجرا میکند. متغیر button مقدار خود را از (Button)sender دریافت میکند. این مسئله به معنای آن است که دکمهای که بر روی آن کلیک شده، تمام دستورالعملهای تعریف شده در تابع را اجرا میکند.
- خط چهارم – currentPlayer = Player.X;: بازیکن انسانی همیشه از نماد X استفاده میکند. در این خط از کلاس enum استفاده میکنیم. این کلاس را در بخشهای قبلی مطلب تعریف کردهایم.
- خط پنجم – ;()button.Text = currentPlayer.ToString: این خط متن روی دکمه را به X تغییر میدهد.
- خط ششم – button.Enabled = false;: بعد از کلیک کردن بر روی هر دکمهای، آن دکمه باید غیرفعال شود. به معنی اینکه هر دکمه را فقط یکبار میتوان کلیک کرد.
- خط هفتم – ;button.BackColor = System.Drawing.Color.Cyan: این خط، رنگ دکمه کلیک شده را به «فیروزهای» با کد Cyan تغییر میدهد.
- خط هشتم – buttons.Remove(button);: در مراحل قبل، تمام دکمهها را به لیست مخصوص دکمههای قابل استفاده در بازی اضافه کرده بودیم. با این خط کد، دکمه کلیک شده را از آن لیست حذف میکنیم.
کد نوشته شده در خط هشتم، باعث میشود که بازیکن کامپیوتری دچار خطا نشود. دو مورد از رایجترین خطاها برای بازیکن کامپیوتری شامل موارد زیر است.
- کلیک بر روی دکمههای غیرفعال شده
- کلیک بر روی دکمههای کاربر
در نتیجه حرکات بازیکن کامپیوتری با حرکات کاربر همپوشانی نخواهند داشت. سپس تابع Check() را اجرا میکنیم. بعد از آنهم زمانسنج AImoves شروع به کار میکند. تابع Check() را در کادر پایین پیادهسازی کردهایم.
تابع پیادهسازی شده در بالا، تابع Check() است. بعد از هر حرکت در بازی، یکبار تابع Check() اجرا میشود. وظیفه تابع Check() این است که دائما وضعیت صفحه بازی را بررسی کرده و ببیند که آیا کاربر یا کامپیوتر برنده بازی شدهاند یا نه.

در این تابع دو عبارت شرطی if وجود دارد. هر کدام از عبارتهای if شامل شرط بزرگی هستند. در عبارتهای شرطی زبان برنامه نویسی سی شارپ وجود دو نماد || به معنای «یا» (OR) است. برای نمونه در کد زیر یک عبارت شرطی پیادهسازی کردهایم.
در کد بالا، اگر مقدار text در button1 و button2 برابر با X باشند یا مقدار text در button1 و button2 برابر با O باشند، دستورهای درون عبارت if اجرا میشوند. بسیار مهم است که در زمان ساخت بازی با سی شارپ مهارت کار با عبارتهای شرطی را داشته باشیم.
- هروقت که یکی از عبارتهای شرطی برقرار شدند، اجرای زمانسنج را متوقف میکنیم.
- بعد از آن پیغامی بر روی صفحه نمایش نشان میدهیم. در این پیغام نوشته شده است که یکی از بازیکنان – کاربر یا کامپیوتر – برنده بازی شده است.
- سپس ۱ امتیاز به مجموع امتیازات کاربر یا کامپیوتر – بازیکن برنده – اضافه میکنیم.
- در نهایت هم بازی را ریست میکنیم. با این کار بازیکنان میتوانند دوباره بازی کنند.
تمام شرایط پیروزی هر دو بازیکن X و O در این عبارت if پیادهسازی شدهاند. باید روش کار تابع بالا را به خوبی متوجه شویم. در کادر پایین هم تابع AImove را پیادهسازی کردهایم.
تابع بالا با عبارت شرطی if شروع میشود. زیرا اگر هیچ دکمهای برای بازی باقینمانده باشد، بازیکن کامپیوتری هم نمیتواند بازی کند. به همین دلیل، بررسی میکنیم که آیا در لیست دکمهها حداقل یک دکمه قابل استفاده وجود دارد یا نه. اگر این لیست خالی نشده باشد، تابع بقیه دستورالعملها را اجرا میکند.
در ادامه، یک متغیر محلی با نوع عدد صحیح و به نام index ایجاد کردهایم. از این متغیر برای ساخت عدد تصادفی استفاده میکنیم. این عدد از بین شماره دکمههایی انتخاب میشود که هنوز در لیست دکمههای قابل بازی باقی ماندهاند. با استفاده از ویژگی Count میتوانیم تعداد دکمههای باقیمانده در لیست را بشماریم. بعد از انجام این مراحل و از خط ۱۴ به بعد عملیات زیر را انجام میدهیم.
- بازیکن کامپیوتری را برابر با player.O یا بازیکن با حرف O قرار دادیم. درنتیجه متن روی دکمهها با هر کلیک توسط این بازیکن باید به شکل O نوشته شود.
- همچنین بعد از هر حرکت کامپیوتر در بازی، رنگ پسزمینه را هم به رنگ «نارنجی تیره» با کد Dark Salmon تغییر میدهیم.
- سپس باید دکمهی مورد استفاده توسط کامپیوتر در بازی را از لیست دکمهها حذف کنیم. این کار با کد buttons.RemoveAt(index); انجام میشود.
- بعد از آن امکان برنده شدن کامپیوتر را بر اثر این حرکت بررسی میکنیم. شرایط مربوط به برنده شدن در تابع Check() نوشته شده است.
- در نهایت هم بعد از انجام شدن حرکت کامپیوتر باید زمانسنج را با کد AImoves.Stop(); متوقف کنیم.
در کادر پایین تصاویر مختلف مربوط به اجرای بازی را مشاهده میکنید. با اجرای بازی و آزمایش آن میتوانیم از درستی عملکرد توابع نوشته شده مطمئن شویم. بازی دوز یکی از بازیهای سرگرم کنندهای است که برنامه نویسان برای افزایش مهارت خود اقدام به پیادهسازی آن میکنند. در صورت علاقهمندی به زبان پایتون میتوانید ساخت بازی دوز با پایتون را هم تمرین کنید. به عنوان کمک، پیشنهاد میکنیم که مطلب مربوط به آن را در مجله فرادرس مطالعه کنید.
برای اجرای پروژه در ویژوال استودیو باید بر روی دکمه دیباگ کلیک کرده یا دکمه «F5» را بر روی صفحه کلید فشار دهیم.

در کادر پایین، کدهای کامل این بازی را قرار دادهایم.
یادگیری سی شارپ با کمک فرادرس
زبان برنامه نویسی #C، به دلیل ویژگیهای قدرتمند و یادگیری ساده، به انتخابی مناسب برای افراد تازهکار و برنامهنویسان حرفهای تبدیل شده است. سیشارپ به دلیل پشتیبانی از ویژگیهایی مانند برنامهنویسی شیگرا، مدیریت حافظه خودکار و امنیت بالا، ابزاری مناسب برای ساخت نرمافزارهای مقیاسپذیر و باکیفیت است. از طرف دیگر در حوزههای مختلفی مانند بازیسازی، ساخت نرمافزارهای کاربردی، برنامههای تحت وب و غیره هم بازار کار دارد. در نتیجه افراد زیادی علاقهمند به یادگیری این زبان برنامه نویسی شدهاند.

وبسایت آموزشی فرادرس، فیلمهای آموزشی بسیار خوبی را برای کمک به یادگیری زبان سیشارپ تهیه کرده است. فیلمهای آموزشی فرادرس، با بهترین اساتید و بیشترین کیفیت تولید شدهاند. فرادرس تلاش کرده که در فیلمهای آموزشی خود تمام بخشهای مربوط به زبان سیشارپ را پوشش دهد. در فهرست پایین، چند فیلم از «مجموعه آموزشی سیشارپ، از مقدماتی تا پیشرفته» را معرفی کردهایم.
ساخت بازی پازل با سی شارپ
یکی از بهترین روشها برای یاد گرفتن ساخت بازی با سی شارپ این است که چند مثال مختلف را در کنار هم بررسی کنیم. به همین دلیل در این بخش از مطلب، ساخت بازی پازل با سی شارپ را آموزش دادهایم. پازل تصویری، یکی از بازیهای سرگرم کننده و روش مناسبی برای گذراندن زمان است. ساخت این بازی، فرصت خوبی برای ارتقای مهارتهای برنامه نویسی است. روش کار بازی را در فهرست زیر نوشتهایم.
- تصویری انتخاب شده و به چندین تکه مختلف تقسیم میشود.
- تکههای مختلف به صورت تصادفی با یکدیگر مخلوط میشوند.
- اکنون بازیکن باید این تکههای درهم بُرخورده را به صورت اولیه و مرتب شده بچیند.
در ادامه، تمام مراحل ساخت این بازی را یک به یک توضیح دادهایم.
راه اندازی پروژه
قبل از پرداختن به مراحل ساخت بازی، باید پروژه جدیدی در ویژوال استودیو برای این بازی بسازیم.
مرحله اول باز کردن ویژوال استودیو
ابتدا باید ویژوال استودیو را در کامپیوتر خود فعال کنیم. اما اگر این نرمافزار را به صورت نصب شده بر روی کامپیوتر ندارید، با مراجعه به لینک (+) میتوانید نسخه عمومی و رایگان آن را دانلود کرده و استفاده کنید.
مرحله دوم ساخت پروژه جدید
برای ساخت پروژه جدید راحتترین روش استفاده از پنجره شروع در زمان راهاندازی ویژوال استودیو است.
- همزمان با بازکردن ویژوال استودیو «پنجره شروع» (Start Window) باز میشود. در این پنجره بر روی گزینه «Create a new project» کلیک میکنیم.

- در نوار جستوجو، عبارت «Windows Forms App» را بنویسید. سپس از لیست باز شده گزینه منطبق با این عبارت را انتخاب کنید.

- بعد از انتخاب «Windows Forms App» بر روی دکمه «Next» کلیک کنید. در مرحله بعد باید به پروژه خود نامی اختصاص دهیم. در این مطلب از نام Jigsaw_Puzzle برای پروژه خود استفاده کردهایم.
- سپس محل مورد نظر برای ساخت پروژه را انتخاب کرده و بر روی دکمه «Create» کلیک میکنیم.
اکنون پروژهای با نوع «Windows Form» ساخته شده است. در ادامه مطلب، مراحل توسعه این فرم را بررسی کردهایم.
طراحی رابط کاربری بازی
مراحل بعد به طراحی رابط کاربری بازی پازل تصویری مربوط میشوند. در این مراحل، باید بخشهایی مثل دکمهها و صفحهی بازی را به فرم اضافه کنیم.
مرحله اول افزودن صفحهای برای نگهداری تکههای پازل
تمام گامهای این مرحله را در فهرست زیر به صورت مرتب توضیح دادهایم.
- در منوی Designer View بر روی گزینه Form1 کلیک کرده و آن را باز میکنیم.
- برای ساخت صفحه از بخش «نوارابزار» (Toolbox) گزینه «Panel» را انتخاب میکنیم. سپس با ماوس کشیده و بر روی فرم قرار میدهیم.
- مقدار اندازه پنل را در مقابل متغیر Size برابر با 270×270 پیسکل تنظیم میکنیم. این اندازه محلی است که تکههای پازل در آنجا نمایش داده میشوند.
نکته: مراحل ۱ و ۲ از فهرست بالا معمولا به صورت خودکار انجام میشوند. یعنی بعد از ساختن پروژه، فرم خامی ساخته شده و نمایش داده میشود.
مرحله دوم افزودن دکمه به تکههای پازل
گامهای این مرحله را هم به صورت قدم به قدم در پایین نوشتهایم.
- ۸ دکمه یا «Button» به داخل پنل اضافه میکنیم. هر کدام از این دکمهها یکی از تکههای پازل تصویری را تشکیل میدهند.

- اندازه تمام دکمهها را برابر با 90×90 پیکسل تنظیم میکنیم. با این کار تمام دکمهها به خوبی با پنل مطابقت پیدا میکنند. دکمههای تعریف شده باید ساختار شبکهای سه در سه تشکیل دهند. فضای خالی پایین، سمت راست برای جابهجایی دکمهها در زمان بازی به کار برده میشود.

- تمام دکمهها را به ترتیب نامگذاری کنید. برای مثال میتوان از button1 و button2 شروع کنیم و همینطور تا button8 بهپیش برویم.
نکته: در نسخههای موجود ویژوال استودیو بعد از اضافه کردن دکمهها، خودشان به طور خودکار و مرتب نامگذاری میشوند.
مرحله سوم افزودن دکمه شروع بازی
دکمه دیگری هم باید به پایین پنل اضافه کنیم. این دکمه باید با بارگذاری بقیه دکمهها و بهمریختن تکههای پازل، بازی را از اول شروع کند. در این دکمه مقدار ویژگی «Text» را برابر با Start قرار دهید.

بارگذاری و برش تصویر
هسته اصلی در بازی پازل تصویری شامل بارگذاری تصویر، برش آن به قطعات کوچکتر و نمایش این تکهها بر روی دکمههای صفحه بازی است.
در این بخش از مطلب، کد مربوط به این حرکت را نوشتهایم.
مرحله اول وارد کردن فضاهای نام ضروری
برای وارد کردن «فضاهای نام ضروری» (Necessary Namespaces) فرم «Form1.cs» را باز میکنیم. در ابتدای کار باید کدهای زیر را به بالای فایل فرم اضافه کنیم.
نکته: «فضاهای نام» (Namespaces) برای سازماندهی کلاسها در برنامهنویسی استفاده میشوند. اصلی این مفهوم – بهویژه در پروژههای بزرگ – برای مدیریت محدودهی فعالیت کلاسها و متدها کاربرد دارد. شاید ظاهر و روش اضافهکردن فضاهای نام و کتابخانهها در زبان سیشارپ شبیه به هم باشند، اما نباید این دو را با هم به اشتباه بگیریم.
مرحله دوم مقداردهی متغیرها
در این مرحله دو متغیر مهم به کلاس «Form1» اضافه میکنیم. در کادر زیر، کدهای افزودن این متغیرها را به کلاس Form1 نوشتهایم.
از متغیر EmptyPoint برای ردگیری فضای خالی در پازل استفاده میشود. متغیر images هم تکههای برش خورده عکس اصلی را نگهداری میکند.
مرحله سوم بارگذاری و برش تصویر
در تابع Form1_Load - رویداد مربوط به کلیک بر روی دکمه «Start» – کد زیر را اضافه کنید. این کد هم تصویر مشخص شده را بارگذاری میکند و هم آن تصویر را به قطعات کوچکتر برش میدهد.
کد بالا، تصویری را از پوشه img واکشی میکند. سپس این تصویر را به قطعاتی با اندازه «90×90» پیکسل تقسیم میکند.

نکته: تصویر موجود در این پوشه، مربوط به سیستم ما بوده و برای طراحی این پازل استفاده شده است. احتمالاً شما باید مسیر – آدرسدهی – این تصویر را با توجه به محل ذخیرهسازی خود تغییر دهید. البته اگر فولدر پروژه را از بخشهای پایینتر همین مطلب دانلود کنید، در اجرای برنامه با مشکل خاصی روبهرو نمیشوید.
دَرهم ریختن و نمایش قطعات پازل
بعد از بریدن عکس اصلی به تکههای کوچکتر، تکههای ایجاد شده را باید به صورت درهم و تصادفی جابهجا کنیم.
مرحله اول بُر زدن قطعات پازل
برای ساخت بازی با سی شارپ، خودمان باید بتوانیم متدهای مختلف و مورد نیاز بازی را پیادهسازی کنیم. متد نوشته شده در کادر پایین برای بُر زدن قطعات پازل به کار برده میشود.
این متد، ترتیب عناصر درون آرایه را به صورت تصادفی تغییر میدهد. عناصر درون این آرایه، موقعیت تکههای پازل را نشان میدهند.

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

برای مشخص شدن پایان بازی، باید تکمیل شدن پازل را با استفاده از کد زیر، دائما بررسی کنیم.
با کلیک بر روی این لینک(+) میتوانید تمام کدها و فایلهای پروژه را به صورت کامل دانلود کنید. بعد از دانلود فایلها ابتدا Visual Studio را باز کنید. سپس فولدر را از حالت فشرده خارج و در محیط Visual Studio رها کنید.
چگونه با کمک فرادرس استفاده از یونیتی را یاد بگیریم؟
فرادرس برای کمک به یادگیری یونیتی مجموعهای از فیلمهای آموزشی مختلف را تهیه و منتشر کرده است. تمام این فیلمها ساختار منسجمی داشته و مطالب را به صورت کامل و گامبهگام آموزش میدهند. یونیتی یکی از بهترین ابزارهای ساخت بازی است. این ابزار به شکل یکپارچه و بسیار سادهای با زبان برنامه نویسی سی شارپ کار میکند. به همین دلیل پیشنهاد میکنیم برای گرفتن نتیجه بهتر، آموزشهای مقدماتی مربوط به سی شارپ را نیز تماشا کرده باشید. فرادرس در انتهای بعضی از این فیلمها به کاربران خود، مدرک دوزبانه پایان دوره هم میدهد.

موتورهای بازی سازی سازگار با سی شارپ
استفاده از «موتورهای بازیسازی» (Game Engines) برای ساخت بازی با سی شارپ، باعث افزایش کیفیت، سرعت و سادهتر شدن کار میشود. این فریمورکهای بازیسازی از زبان برنامه نویسی سی شارپ استفاده میکنند. موتورهای بازی مجموعهای از ابزارها، کتابخانهها و ویژگیهای را ارائه میدهند. وجود این ابزارها به مدیریت وظایف دشواری مانند ساخت جلوههای گرافیکی، پیادهسازی قوانین فیزیک و گرفتن ورودی از کاربر کمک میکنند. موتورهای بازیسازی سیشارپ، این امکان را فراهم میکنند که توسعهدهندگان بهجای درگیر شدن با جزئیات پیچیده و فنی بر روی طراحی و منطق اصلی بازی تمرکز کنند.
بهترین و مشهورترین موتورهای بازیسازی سازگار با سی شارپ را در فهرست زیر نام بردهایم.
- Unity: موتور بازیسازی Unity ابزار چند پلتفرمی است. Unity ابزارهای جامعی برای انیمیشنسازی دارد. از «واقعیت مجازی» (Virtual Reality | VR) و «واقعیت افزوده» (Augmented Reality | AR) پشتیبانی میکند. همچنین این موتور میتواند رفتارهای بازیکن را ردگیری کرده و تحلیل کند.
- Godot: موتور Godot عناصر بازی را در صحنه سازماندهی میکند. این موتور، سیستم انیمیشنی پیشرفتهای دارد. همچنین ادیتور گرافیکی و رابط کاربری دارد که به روش «کشیدن و رها کردن» (Drag-And-Drop) کار میکند.
- Stride یا Paradox ، قبلا با نام Xenko شناخته میشد: معماری این موتور بازیسازی ماژولار است و به شکل کامل توسط سی شارپ پشتیبانی میشود. Stride تواناییهای رندر کردن پیشرفتهای مانند PBR و HDR داشته و از واقعیت مجازی هم پشتیبانی میکند. این موتور، ادیتور پیشرفتهای دارد که امکان پیشنمایش بازی به صورت بیدرنگ را فراهم میکند.
- MonoGame: موتور بازیسازی MonoGame چندپلتفرمی است. این موتور کیفیت بسیار بالایی – مخصوصا برای بازیهای دوبعدی – دارد. همچنین جامعه کاربری بزرگ و منابع آموزشی فراوانی هم دارد.
- WaveEngine: تمرکز خاصی بر روی توسعه VR و AR و MR دارد. معماری این موتور بازیسازی ماژولار است. با سی شارپ به راحتی میتوان برای این ابزار اسکریپت نوشت. WaveEngine از تکنیکهای رندر کردن پیشرفته پشتیبانی میکند. همچنین امکان استفاده رایگان از این موتور برای اهداف تجاری وجود دارد.
- CryEngine: کیفیت گرافیکی این موتور بالا بوده و همچنین میتواند به صورت بیدرنگ همزمان با توسعه بازی، صحنه را رندر کند. CryEngine سیستمهای هوش مصنوعی و قوانین فیزیکی پیشرفتهای دارد. این موتور از VR و AR پشتیبانی میکند. در ضمن مجموعه ابزار کاملی برای توسعه بازیهای کامپیوتری دارد.

- Duality: به طور کامل از اسکریپتهای سی شارپ پشتیبانی میکند. ویرایشگر این موتور بازیسازی با ابزارهای گرافیکی ادغام شده است. موتور Duality کم حجم بوده و کاربری سادهای دارد. همچنین جامعه اوپن سورس و فعالی هم دارد.
- FlatRedBall: موتور بازیسازی FlatRedBall ابزارهای بسیار قدرتمندی برای توسعه بازیهای دوبعدی دارد. ابزار FlatRedBall چندپلتفرمی بوده و ویرایشگر آن هم با ویژگیهایی مانند «کشیدن و رها کردن» به سادگی کار میکند. جامعه کاربری فعالی داشته و منابع آموزشی آن فراوان است. در ضمن به طور گستردهای نیز از سی شارپ پشتیبانی میکند.
- Banshee Engine: موتور Banshee Engine به طور کامل اوپن سورس است. این موتور سیستم رندر کردن پیشرفتهای دارد که از PBR پشتیبانی میکند. همچنین به طور کامل از اسکریپتهای سی شارپ پشتیبانی میکند.
- Unigine: موتور رندر پیشرفتهای دارد. این موتور میتواند محیطهایی با مقیاس بزرگ را هم رندر کند. Unigine به طور کامل از VR پشتیبانی میکند. میتوان با هر دو زبان سی شارپ و سی پلاس پلاس بازیها را توسعه داد. این ابزار، امکان سفارشیسازی بسیار بالایی دارد. Unigine هم برای بازیسازی مناسب است و هم برای شبیهسازیهای صنعتی.
- Flax Engine: ابزار Flax Engine به سرعت بهروزرسانیهای جدیدی ارائه میدهد. این موتور بازیسازی، سیستم رندر کردن پیشرفتهای دارد که از PBR پشتیبانی میکند. همچنین از توسعه چندپلتفرمی بازیها و از سی شارپ نیز پشتیبانی میکند.
- Evergine: بر روی توسعه VR و AR و MR تمرکز کرده است. این موتور بازیسازی، چندپلتفرمی است و بر روی HoloLens و Oculus هم کار میکند. Evergine به طور کامل از اسکریپتهای سی شارپ پشتیبانی میکند، کاربری آن ساده است و به صورت بیدرنگ گرافیک بازی را رندر میکند. ابزار Evergine هم برای ساخت بازیهای دوبعدی مناسب است و هم برای ساخت بازیهای سهبعدی.
مزایای ساخت بازی با سی شارپ
به دلیل شباهت زبان برنامه نویسی #C به ++C و جاوا توسعهدهندگان زیادی آن را برای ساخت بازی میپسندند. این زبان، سینتکس ساده، کتابخانههای قدرتمند و سیستم مدیریت حافظه کارآمدی دارد.
زبان برنامه نویسی سی شارپ، مزایای بسیار زیادی برای استفاده در صنعت بازیسازی دارد. در فهرست زیر، چند مورد از مزایای استفاده از سی شارپ را نوشتهایم.
- زبان #C جزو زبانهای شیءگرا است. به همین دلیل به یکی از گزینههای محبوب در حوزه بازیسازی تبدیل شده است. شیءگرایی در ساخت عناصر پیچیده و تعاملی بسیار خوب عمل میکند. این رویکرد، کدهای ماژولاری میسازد که دارای قابلیت استفاده مجدد هستند. در نتیجه، زبان #C برای ساخت پروژههای بزرگ ایدهآل است.
- ابزار درونی این زبان برای انجام «Garbage Collection» به صورت خودکار، حافظه را مدیریت میکند. در نتیجه توسعهدهندگان میتوانند فقط بر روی ساخت بازی تمرکز کنند.
- زبان سی شارپ، جامعه کاربری زنده و پویایی دارد. در نتیجه، منابع آموزشی فراوان و کتابخانههای قدرتمندی برای آن توسعه داده شدهاند.
- #C به خوبی با Unity کار میکند. Unity مشهورترین موتور بازیسازی در دنیاست. به همین دلیل بیشتر توسعهدهندگان از سی شارپ برای نوشتن اسکریپتهای بازیها استفاده میکنند. از ترکیب #C و Unity برای ساخت انواع پروژهها استفاده میشود. از پروژههای ساده و مستقل گرفته تا بازیهای بزرگی مانند «Call of Duty» یا «Fortnite» را میتوان با کمک سی شارپ ساخت.

جمعبندی
سی شارپ به انتخاب محبوب توسعهدهندگان بازی تبدیل شده است. مهمترین دلایل این مسئله وجود سینتکس ساده، کتابخانههای کلاسی قدرتمند و سیستم مدیریت حافظه بهینه است. ساختار چندپلتفرمی این زبان برنامه نویسی، ساخت بازیها را برای توسعهدهندگان سادهتر کرده است. یکی دیگر از مهمترین ویژگیهای این زبان، وجود موتورهای بازیسازی قدرتمندی است که کار را برای توسعهدهندگان سادهتر کرده است.
در این مطلب از مجله فرادرس فرایند ساخت بازی با سی شارپ را بررسی کردهایم. دو نمونه بازی ساده را با کمک سی شارپ پیادهسازی کرده و مشهورترین موتورهای بازیسازی را نیز نام بردیم. وجود ویژگیهای قدرتمند، سرعت بالا، ابزار مدیریت حافظه و فریمورکهای حرفهای بازیسازی، این زبان را به یکی از مشهورترین انتخابها برای توسعه بازی تبدیل کرده است.
source