صفر تا صد ساخت بازی با سی شارپ 8#

صفر تا صد ساخت بازی با سی شارپ 8#

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

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

ما اسم این متغییر را shoutCount در نظر می گیریم، این متغییر را به برنامه اضافه کنید و مقدار آن را مساوی صفر قرار دهید.
int shoutCount = 0;
 
با هر شلیک می بایستی که یک واحد به آن اضافه شود، پس در بلاک متد fire کد زیر را وارد کنید.
shoutCount++;
 
حالا برای اینکه کاربر متوجه شود که چند تیر شلیک کرده است، باید تعداد آن را به کار بر نمایش دهیم. به این منظور دو کنترل label  روی پنل سمت چپ بازی قرار می دهیم.
 
Name = lbl_shoutCountText
موشک های شلیک شده : = Text
Location  = 850 ,780
 
Name = lbl_shoutCount
Text = 0
Location  = 810 ,780
ویژگی های مشترک این دو کنترل :
Visible = false
BackColor = Transparent
ForeColor = White
Font = Tahoma, 9pt
 
در این لحظه صفحه نمایش شما باید شبیه تصویر زیر باشد.

 

خاصیت Visible این کنترل ها باید false باشد زیرا قبل از شروع بازی نباید دیده شوند و زمانی که بازی آغاز شد نمایش داده می شوند، پس شما باید در رخداد کلیک دکمه شروع این ویژگی را true کنید. کد زیر را به رخداد کلیک شروع اضافه کنید.
 
lbl_shoutCountText.Visible = true;
lbl_shoutCount.Visible = true;
 
اما همانطور که در جلسه قبل گفتم الان این کنترل ها متعلق به پنل سمت چپ هستند ولی جز کنترل های ptb_backGround نیستند، برای اینکار باید این کنترل ها را به مجموعه ptb_backGround اضافه کنید، به رخداد load فرم اصلی بروید و کد زیر را به این قسمت اضافه کنید.
 
ptb_backGround.Controls.Add(lbl_shoutCountText);
ptb_backGround.Controls.Add(lbl_shoutCount);
 
هنوز یک کار دیگر مانده است و آن اینکه shoutCount فقط عدد صفر را نمایش می دهد در صورتی که ما می خواهیم تعداد موشک هایی که تا الان شلیک شده اند را نمایش بدهد. برای اینکار کد زیر را در آخر بلاک متد fire بنویسید.
 
lbl_shoutCount.Text = shoutCount.ToString();
 
هر بار که یک موشک شلیک می شود، شمارنده یکی اضافه می شود، با قطعه کد بالا مقدار درون شمارنده تبدیل به رشته می شود و درون lbl_shoutCount قرار می گیرد.

برنامه را اجرا کنید و بازی را شروع کنید می بینید که با هر بار شلیک تعداد موشک ها شلیک شده در گوشه سمت راست بازی نمایش داده می شود.

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



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

بر روی آن کلیک کنید و در پنجره Properties  ویژگی های آن را بصورت زیر تغییر دهید.
Name = tmr_main
Interval = 100
 
روی tmr_main دوبار کلیک کنید تا رخداد آن ساخته شود، این کنترل فقط همین یک رخداد را دارد. با تنظیم ویژگی Interval به 100، هر 100 میلی ثانیه یکبار این رخداد بصورت اتوماتیک وار اجرا می شود. ما هم با استفاده از این مزیت حرکت موشک ها را برنامه نویسی می کنیم. به این صورت که می گوییم، در هر بار اجرا این رخداد موشک ها کمی به بالا حرکت کند، یعنی با ذره ذره کم کردن ارتفاع موشک ها این حس برای کاربر به وجود می آید که موشک ها در حال حرکت هستند در صورتی که در هر 100 میلی ثانیه تنها چند پیکسل جابجا می شوند. خب در رخداد تایمر کد زیر را بنویسید.
foreach (Control element in ptb_backGround.Controls)
{
         if (x is Button)
         {
                  element.Location = new Point(element.Location.X, element.Location.Y - 10);
         }
}
 
در کد بالا یک حلقه foreach ساختیم که قبلا آن را مختصرا توضیح داده بودیم. از این حلقه زمانی استفاده می کنیم که طول مجموعه ای که در آن می گردیم را نمی دانیم. در این مورد هم ما نمی دانیم که چه تعداد کنترل درون ptb_backGround قرار دارند. اما برای جستجو درون یک مجموعه با استفاده از حلقه foreach باید بدونید که اعضا درون این مجموعه از چه نوعی هستند. در این برنامه ما می دانیم که تمام اعضا این مجموعه از نوع کنترل های ویندوزی هستند پس می توانیم از این حلقه استفاده کنیم. حالا اگر ندانیم که اعضا از چه نوعی هستند چه اتفاقی خواهد افتاد؟ در این حلقه یک متغییر تعریف می شود در اینجا x این متغییر است، سپس تک تک اعضا درون آن ریخته می شوند و حلقه یک دور می چرخد و هر کدی که درون حلقه باشد اجرا می شود، اما مشکل اینجاست اگر نوعی که شما برای x انتخاب می کنید، با نوع اعضا مجموعه متفاوت باشد در زمان ریخته شدن اعضا بدرون x خطا رخ می دهد، این خطا حاکی از آن است که شما نمی توانید یک نوع مثل int را به یک نوع مثل Control تبدیل کنید. این کار را امتحان کنید تا به خوبی متوجه موضوع بشوید. ولی برای درک بهتر به مثال زیر توجه کنید.

تصور کنید یک کیسه در بسته پر از اشکال هندسی مثل : دایره، مربع، مثلث و ... را به شما داده اند سپس به شما یک قالب مربع شکل تو خالی می دهند و از شما می خواهند که بدونه اینکه درون کیسه را نگاه کنید تک تک این اشیاء را بیرون بیاورید و از داخل این قالب رد کنید اگر رد شد، یک شئی دیگر از توی کیسه بردارید و همان کار را ادامه دهید، اما اگر رد نشد بازی را تمام کنید و در کیسه را ببندید. مسلم است تنها زمانی اشیاء از درون قاب مثلثی شکل رد می شوند که مثلث باشند و نه دایره یا مربع. پس اگر شئی بیرون آورده شده مثلث نباشد شما بازی را تمام نکرده اید.

در مثال foreach هم دقیقا همین اتفاق رخ می دهد، حلقه بدون اینکه بداند این عضوی که از مجموعه انتخاب کرده و به درون متغییر x می ریزد چه نوعی است این کار را انجام  می دهد اما در زمانی که این عضو شبیه قالب x نیست برنامه دچار خطا می شود. پس چاره چیست؟ چاره انتخاب یک قالب انعطاف پذیر است. می دانید که مربع، دایره و هم مثلث جز اشکال هندسی هستند و اگر قالبی مثل یک شش ضلعی داشته باشیم هم مربع ، هم مثلث و هم دایره از این قالب رد می شوند، در نتیجه بازی ما تمام نمی شود. در بازی ما نیز چنین است ما با در نظر گرفتن نوع Control برای x مطمعا هستیم که تمام کنترل های ویندوزی از این قالب رد خواهند شد و برنامه دچار خطا نمی شود.


اما در قسمت شرط درون حلقه چک می کنیم که آیا کنترلی که در حال حاضر درون متغییر x قرار دارد یک Button است یا خیر؟ به دلیل اینکه ما غیر از کنترل Button کنترل  PictureBox هم در مجموعه کنترل های درون ptb_backGround داریم ولی ما فقط می خواهیم کنترل هایی که دکمه هستند و ما آنها را موشک در نظر گرفتیم به جلو حرکت کنند.

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

اما Timer ها یک متد به نام Start دارند که هر زمان این متد فراخوانی شود، Timer شروع به کار کردن می کند، یعنی اگر شما الان برنامه را اجرا کنید موشک های بازی شما حرکت نخواهندکرد. پس ابتدا باید این Timer را فعال کنید اما کجا این کار را انجام دهید؟ بله درست حدس زدید درون کد دکمه شروع دقیقا زمانی که بازی شروع می شود. پس لطفا کد زیر را به کد دکمه شروع اضافه کنید.
tmr_main.Start();
برنامه را اجرا کنید مشاهده خواهید کرد که پس از شلیک هر موشک آن موشک به سمت بالا حرکت می کند.
اما همانطور که متوجه شدید سرعت حرکت موشک ها بسیار کم است، برای زیاد و کم کردن سرعت موشک ها دو پارامتر باید تغییر کنند، یکی ویژگی Interval کنترل Timer و دوم تعداد پیکسلی که در هر بار اجرا رخداد Tik کنترل Timer از ارتفاع موشک ها کاسته می شود. برای اینکه سرعت موشک ها را کمی زیاد کنید، به محیط طراحی بروید و سپس ویژگی Interval کنترل Timer را مساوی 20 قرار دهید در این صورت هر 20 میلی ثانیه یکبار این رخداد اتفاق می افتد.

اما این موشک ها تا کجا به سمت بالا حرکت می کنند؟ خب این بالا رفتن تا پایان برنامه ادامه پیدا می کند. اما موشکی که از تصویر خارج شود سودی برای ما ندارد و باید از بین برود تا منابع سیستم ما را در گیر نکند. به این منظور باید چک کنیم ارتفاع هر موشکی که کمتر از 0 بود آن را از بین ببریم و منابعی که در اختیار گرفته را آزاد کنیم. به این منظور باید کد زیر را در بدنه froeach اضافه کنید.
if (element.Location.Y <= 0)
{
          ptb_backGround.Controls.Remove(x);
          element.Dispose();
          missShout++;
          lbl_missShout.Text = missShout.ToString();
}
کار خط اول و دوم کاملا مشخص است، خط سوم هم شئی که ساخته شده است را از بین می برد و منابعی که از سیستم در اختیار دارد را آزاد می کند. اما missShout یک متغییر سراسری است که شما باید آن را به برنامه تان اضافه کنید، در آینده از این متغییر برای محاسبه امتیاز استفاده می کنیم، یعنی هر یک شلیک بی ثمر بازیکن یک امتیاز منفی در نظر گرفته می شود. در حال حاظر فقط این متغییر را به برنامه اضافه می کنیم فقط برای اینکه بازی را کاملتر کنیم. مثل قسمت قبل که برای موشک های شلیک شده دو label روی فرم قرار دادیم برای موشک های از دست رفته نیز دو label قرار می دهیم، همانطور که در کد بالا مشاهده می کنید یک label به نام missShout داریم که اینکار را برای ما انجام می دهد. پس از اضافه کردن متغییر missShout و دو کنترل  lbl_missShout و lbl_missShoutText بازی شما باید بصورت زیر نمایش داده شود.  

*نکته : تمام کارهای که برای نمایش تعداد موشک های شلیک شده انجام دادید برای این دو label نیز انجام دهید. منظور true کردن ویژگی Visible و اضافه کردن این کنترل ها به لیست کنترل های ptb_backGround و همه کارهایی که روی ویژگی های آن دو label قبلی انجام دادید.
 

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

ساخت دشمنان

اگر با ماتریس ها آشنا باشید، حتما متوجه شده اید که گروه دشمنان بصورت یک ماتریس دو بعدی است. پس برای پیاده سازی دشمنان ما به یک ماتریس احتیاج داریم، اما برای پیاده سازی یک ماتریس چگونه باید عمل کنیم؟ اگر بخاطر داشته باشید در جلسه سوم در مورد آرایه ها صحبت کردیم، اگر آرایه ها را خوب بخاطر ندارید لطفا مروری بر این قسمت داشته باشید. اما ارتباط آرایه ها با ماتریس ها چیست؟ هر سطر از ماتریس را می شود یک آرایه در نظر گرفت و همچنین می شود آرایه های دوبعدی ساخت که در واقع همان ماتریس ها هستند. برای ساخت یک آرایه دوبعدی باید بصورت زیر عمل کنید. فراموش نکنید که آرایه های دوبعدی نیز مثل آرایه های یک بعدی از صفر شروع می شوند.
int[,] matrix = new int[3,3];
 
با نوشتن این کد یک ماتریس سه در سه از نوع int ساخته می شود. اما برای دسترسی به هر عضو از این آرایه از چه کدی استفاده می کنیم؟ دسترسی به خانه های آرایه ها دوبعدی هم مثل دسترسی به خانه های آرایه های یک بعدی است فقط یک تفاوت کوچک بین آنها وجود دارد. در زمان استفاده از آرایه های دوبعدی بصورت زیر عمل می کنیم.
Matrix[2,0] = 2;
 
با این خط کد اولین عضو سطر سوم را مساوی 2 قرار دادیم. برای دیگر اعضا نیز با همین روش کار می کنیم. پس بخاطر داشته باشید برای مقدار دهی هر عضو از آرایه های دوبعدی باید آدرس سطر و ستون آن عضو را بدهید. در مثال بالا شماره سطر 2 و شماره ستون صفر است به تصویر زیر دقت کنید تا بهتر متوجه موضوع شوید.
 

پس برای ساخت موشک ها از ماتریس استفاده می کنیم. همانطور که قبلا گفتیم برای ساخت دشمنان از کنترل PictureBox استفاده می کنیم. در نتیجه باید یک آرایه دوبعدی از کنترل PictureBox بسازیم که هر خانه از آن یک دشمن است. اما اینکه این ماتریس چند در چند باشد بعهده شماست، ما چون می خواهیم در آینده به بازیکن این امکان را بدهیم که خودش تعداد دشمنان را تنظیم کند باید تعداد سطر و ستون را بصورت دو متغییر سراسری تعریف کنیم.
کدهای زیر را در قسمت بالای برنامه در جایی که متغییرهای سراسری را تعریف می کنید بنویسید.
 
PictureBox[,] enemies;
int enemiesRow = 0;//تعداد سطر های دشمنان
int enemiesCol = 0;//تعداد ستون های دشمنان

 
به این ترتیب یک آرایه دوبعدی از نوع کنترل PictureBox ساختیم، اما هنوز کارمان تمام نشده است، چند مرحله دیگر باقی مانده :
1- تعریف آرایه بطور کامل
2- ساخت و تنظیم ویژگی های خانه های آریه
3 – حرکت دادن آرایه

اما چرا آرایه دشمنان را بصورت سراسری تعریف کردیم؟ این آرایه در چند قسمت مختلف بازی مورد استفاده قرار می گیرد،(بعنوان مثال در رخداد کلیک دکمه شروع ساخته می شود، در رخداد Tik، Timer استفاده می شود و ...) از این رو مجبور بودیم تا این آرایه را سراسری تعریف کنیم تا در تمام برنامه در دسترس باشد.
 
حالا که آرایه را تعریف کردید وقت آن رسیده تا محتوای درون آن را نیز بسازید و درون خانه های آرایه قرار دهید. اما پیش از تعریف محتوای آن بیاید این فرض را در نظر بگیریم که شاید در آینده بخواهیم این امکان را به بازیکن بدهیم که خودش مرحله بسازد، یعنی مثلا تعداد دشمنان را خودش مشخص کند. اما این کار یک سری مشکلات برای ما به وجود می آورد، همانطور که به خاطر دارید ما عرض پنل بازی را 900 پیکسل در نظر گرفتیم حالا فرض کنید که کاربر بخواهد که تعداد سطر را 100 و تعداد ستون را 50 در نظر بگیرد، مشخص است که در این صورت بازی ما به هم می ریزد همچنین جلوتر زمانی که می خواهیم حرکت کردن دشمنان را بسازیم متوجه خواهید شد که چند پیکسل کم یا زیاد شدن طول دشمنان باعث خراب شدن بازی ما می شود. در نتیجه برای جلوگیری از چنین اتفاقاتی مجبور هستیم که چند متغییر دیگر تعریف کنیم تا به این مشکلات برخورد نکنیم. اما این متغییرها چی هستند : اول از همه یک متغییر برای نگهداری اندازه طول دشمن ها لازم داریم. دوم فاصله بین دشمنان هم لازم داریم. سوم یک متغییر که اندازه کلی ماتریس دشمنان را در خود نگاه داری می کند. به تصویر زیر نگاه کنید با خطوط قرمز اندازه دشمنان، فاصله بین آنها و طول صفحه را مشخص کرده ایم.
 

 
همانطور که در تصویر مشاهده می کنید، فاصله عمودی و افقی بین دشمنان یکی است اما  می توان این قسمت را با دو متغییر تعریف کرد یکی برای فاصله عمودی بین آنها و یکی برای فاصله افقی بین آنها، ولی به دلیل اینکه دشمنان را همیشه بصورت مربع تعریف می کنیم فقط یک متغییر برای عرض و ارتفاع کافی است. پس با این اوصاف باید کدهای زیر را نیز در محل متغییرهای سراسری بنویسید.
int verticalSpace = 0;//فاصله عمودی
int horizentalSpace = 0;//فاصله افقی
int sizeOfEnemies = 0;//سایز دشمنان
int totalSize = 0;//سایز کلی آرایه دشمنان را در خود نگه می دارد
 
اما چرا این متغییرها را اضافه کردیم در صورتی که می توانستیم از بازیکن بخواهیم که مواظب باشد که اندازه دشمنان بیشتر از صفحه نشود. مشخص است که این کار درست نبود در این دوره یک بازی ساده آموزشی می سازیم ولی در آینده زمانی که برنامه ها یا بازی های حرفه ای بسازید حتما باید احتیاط کنید که روند برنامه تان دچار مشکل نشود، پس مجبور هستیم خودمان اتفاقات پیش بینی نشده مثل خرابکاری عمدی بازیکن را در نظر بگیریم. به این منظور کد زیر به در رخداد دکمه شروع بازی اضافه می کنیم.
 
totalSize = (enemiesCol * sizeOfEnemies) + ((enemiesCol - 1) * horizontalSpace);
if (totalSize >= 900 || totalSize <= 0)
{
           enemiesCol = 5;
           enemiesRow = 4;
           sizeOfEnemies = 50;
           horizontalSpace = verticalSpace = 20;
           totalSize = (enemiesCol * sizeOfEnemies) + ((enemiesCol - 1) * horizontalSpace);
}
 
در پرانتز اول خط اول تعداد ستون های ماتریس در عرض دشمنان ضرب می شود این کار باعث می شود تا عرض تمام دشمنان روی هم محاسبه شود اما فاصله بین آنها محاسبه نشده است. در پرانتز دوم فاصله بین آنها محاسبه می شود، اما چرا از تعداد ستون ها یکی کم شده است؟ اگر به تصویر قبلی نگاه کنید متوجه می شوید که همیشه فاصله بین ستون ها از خود ستون ها یکی کمتر است. با جمع این دو پرانتز عرض کل گروه دشمنان بدست می آید.

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

خب برای این جلسه کافی است انشاالله در جلسه بعد ساخت دشمنان را تمام می کنیم تا جلسه بعد دست از تمرین بر ندارید.

دانلود سورس کد برنامه را از اینجا دانلود کنید.
 

مصطفی مدرک کارشناسی نرم افزار دارد و از برنامه نویسان شرکت آرتیمان استودیو است. از سال 86 برنامه نویسی با زبان سی شارپ را آغاز کرده و در حوزه توسعه وب با تکنولوژی دات نت بسیار مسلط است. وی هم اکنون در حال توسعه اپلیکیشن های موبایل از طریق پلتفرم زامارین است.

نظرات و سوالات کاربران

ارسال پاسخ amir
amir
شنبه ۲۰ شهریور ۱۳۹۵ ۱۴:۲۸
با سلام.
متغیر x در بخش ساخت حرکت موشک ها چگونه متنغیری است و کجا تعریف می شود؟
با تشکر
ارسال پاسخ davood
davood
دوشنبه ۰۷ تیر ۱۳۹۵ ۱۷:۴۰
سلام.
من هرکاری میکنم نمیتونم ماتریس رو بسازم یعنی تمام دستورات شمارو نوشتم ولی نشونش نمیده
ممنون میشم اگه بگید مشکل کجاس
ارسال پاسخ mary
mary
پنج شنبه ۲۰ خرداد ۱۳۹۵ ۲۱:۵۱
ببخشید متغییر x نباید تعریف شه؟
ارسال پاسخ مصطفی درخشان
مصطفی درخشان
سه شنبه ۳۱ شهریور ۱۳۹۴ ۲۳:۳۷
در پاسخ به دیدگاه marasiali ارسال شده در سه شنبه ۳۱ شهریور ۱۳۹۴ ۲۱:۰۰

شرمنده نتونستم متوجه اشکال کار بشم سورس پروژه خودمو میذارم بی زحمت برسیش کنین
http://uplod.ir/w3nd723ukb20/S...
البته این عین اون پروژه ای که گفتین نیس و خیلی چیزها مثل فول اسکرین بودن،محدودیت حرکت سفینه،تیرها،رخداد دکمه شروع و... توش نیس ولی به نظرم چیزی توش حذف نشده که باعث این مشکل شده باشه.

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

سلام!

برنامه تون رو دانلود کردم، خیلی خوب انجام دادید. مشکل کدتون هم خیلی ساده است. شما باید یک picturebox به پنل سمت چپ splitcontainer اضافه کنید و ویژیگی Dock اون رو fill بذارید. بعد ویژگی Image اون رو عکسی که دوست دارید بذارید. توجه کنید که ویژگی Image، نه ویژگی backgroundimage، اگر برای backgroundimage عکس بذارید برنامه تون همون مشکل قبلی رو پیدا می کنه.
بعد از این کار سفینه تون رو به لیست کنترل های pictureboxای که روی پنل سمت چپ گذاشتید اضافه کنید و اون خط کدی که نوشته بودید، که سفینه به پنل سمت چپ اضافه شود را پاک کنید.
البته می تونید اصلاح شده کدتون رو از این لینک دانلود کنید.
uplod.ir/oqqyt033xjl4/SpaceWar_Debugged.rar.htm" rel="nofollow">http://uplod.ir/oqqyt033xjl4/S...

در مورد اون باگ هم حرف شما درست است، که البته راهکارش هم هست ولی در حال حاظر نیازی به درست کردنش نیست ولی اگر شما لازم داشتید براتون توضیح می دم.

ارسال پاسخ marasiali
marasiali
سه شنبه ۳۱ شهریور ۱۳۹۴ ۲۱:۰۰

شرمنده نتونستم متوجه اشکال کار بشم سورس پروژه خودمو میذارم بی زحمت برسیش کنین
uplod.ir/w3nd723ukb20/SpaceWar.zip.htm" rel="nofollow">http://uplod.ir/w3nd723ukb20/S...
البته این عین اون پروژه ای که گفتین نیس و خیلی چیزها مثل فول اسکرین بودن،محدودیت حرکت سفینه،تیرها،رخداد دکمه شروع و... توش نیس ولی به نظرم چیزی توش حذف نشده که باعث این مشکل شده باشه.

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

ارسال پاسخ مصطفی درخشان
مصطفی درخشان
یکشنبه ۲۹ شهریور ۱۳۹۴ ۱۴:۲۹
در پاسخ به دیدگاه marasiali ارسال شده در یکشنبه ۲۹ شهریور ۱۳۹۴ ۱۰:۵۱

عالی
واقعا بهش نمیاد بازی ای به این کوتاهی اینقدر ساختش طولانی و جزئیاتش زیاد باشه

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

ارسال پاسخ marasiali
marasiali
یکشنبه ۲۹ شهریور ۱۳۹۴ ۱۰:۵۱

عالی
واقعا بهش نمیاد بازی ای به این کوتاهی اینقدر ساختش طولانی و جزئیاتش زیاد باشه