ساخت بازی با کانواس و جاوا اسکریپت

saalek110

Well-Known Member
آموزش ساخت بازی Star Wars




ساخت صفحه شطرنج با اچ‌تی‌ام‌ال


ایجاد بازی با جاوا اسکریپت​

بازی مین​

 
آخرین ویرایش:

saalek110

Well-Known Member
ایجاد بازی مار با جاوا اسکریپت

 

saalek110

Well-Known Member
مفهوم پکیج در جاوااسکریپت

وقتی با جاوااسکریپت کار می‌کنیم، واژه‌های package و module خیلی به چشممان می‌خورند. این دو واژه بسیاری اوقات عملاً معنای مشابهی می‌دهند و مفهومی شبیه library ها در زبان‌های دیگر دارند. اما اگر بخواهیم دقیق‌تر بیان کنیم:

· معمولاً موقع کار با js خیلی با واژه library سر و کار نداریم.

· منظور از module در جاوااسکریپت، کوچک‌ترین واحد functionality است. (مثلاً هر چیزی که در جاوااسکریپت require، import و export می‌کنیم، یک module به حساب می‌آید)

· منظور از پکیج، distribution unit در کدهای مبتنی بر node.js می‌باشد. یک ماژول یا مجموعه‌ای از ماژول‌ها در کنار هم که به نحوی خاص ترکیب شده‌اند تا یک کار مشخص انجام دهند، یک package را تشکیل می‌دهند. در واقع واژه package وقتی وارد کار می‌شود که ما می‌خواهیم با community ارتباط برقرار کنیم و کدمان را در اختیار دیگران قرار بدهیم و آن را distribute کنیم. درست اتفاقی که در مورد npm رخ داده و می‌گوییم npm ابزاری‌ست برای مدیریت توزیع این واحد ها(یعنی همین پکیج‌ها). ایده اصلی این ساختارِ پکیجی، این است که هر پکیج تا جای ممکن کوچک باشد و یک کار خاص را انجام دهد، و بعداً از کنار هم قرار گرفتن این پکیج‌ها یک پروژه‌ایجاد شود. امروزه هر پروژه جاوااسکریپتی، مثلاً یک وب‌سایت، از تعداد زیادی پکیج در کنار یکدیگر تشکیل شده. در واقع پکیج یک دایرکتوری‌ست که یک یا چند فایل در آن قرار دارد، و فایلی به نام package.json دارد که اطلاعاتی (metadata هایی) درباره آن پکیج به ما می‌دهد.

نقل از:
 

saalek110

Well-Known Member

npm چیست؟


npm یا همان node package manager، بزرگ‌ترین بستر برای ثبت، نشر، اشتراک‌گذاری، بروزرسانی و استفاده از پکیج‌های جاوااسکریپت است. npm یک بستر software registry در اختیارمان قرار می‌دهد که از طریق آن، برنامه‌نویس‌ها از سراسر دنیا پکیج‌های خود را به اشتراک می‌گذارند یا پکیج سایر برنامه‌نویس ها را برای استفاده برمی‌دارند. در این بین اگر برنامه‌نویسی پکیجش را آپدیت کرد، npm به سادگی این امکان را به وی می‌دهد که پکیج بروز شده‌اش را مجدداً روی npm قرار دهد، و سایر کسانی هم که قبلاً در پروژه‌هایشان از آن پکیج استفاده می‌کردند، بتوانند آن را بروز کنند.

وقتی از npm صحبت می‌کنیم، معمولاً سه چیز مد نظرمان است:

1. ابزار CLI (command-line interface) ای که npm در اختیار قرار می‌دهد، یعنی همین دستوراتی که در ترمینال اجرا می‌کنیم.

2. وب‌سایت رسمی npm که حتماً با آن آشنایی دارید: npmjs.com. و در آن می توانیم دنبال پکیج‌های مورد نظرمان بگردیم، درباره آن‌ها اطلاعات کسب کنیم، برای خود و یا تیممان پروفایل بسازیم، ثبت‌نام با دسترسی و امکانات خاص انجام بدهیم، پکیج‌های private و public منتشر کنیم و ... .

از همان سایت.
 

saalek110

Well-Known Member
سالک: ۳ پست بالا ، در حد مطالعه و اطلاعات عمومی است. ربطی به روال کار ما ندارد.
 

saalek110

Well-Known Member
ورژن اول بازی ماشین:




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


Screenshot_۲۰۲۴-۰۲-۲۹_۲۰۰۵۳۰.jpg



در ورژن car2 ایرادات برطرف شد... در این ورژن ماشین می رسه به همون جا که هواپیما بود. یعنی فرودگاه برایش کار می کند.
 
آخرین ویرایش:

saalek110

Well-Known Member
ورژن ۴ ماشین:



تغییرات این ورژن:
توقف گاه ، به وسط صفحه آورده شد.شکل زیر:
Screenshot_۲۰۲۴-۰۳-۰۱_۰۷۰۸۲۵.jpg

یک ابتکاری که در این ورژن استفاده کردم این است که وقتی ماشین به سمت بالامی رود یعنی y آن کم می شود ، می رود پشت توقف گاه... یعنی دیگه دیده نمی شود. روش انجام این کار اینه که در فایل update رسم قهرمان مشروط انجام بشود بر اساس y قهرمان ، به این شکل:

JavaScript:
if (hero.y <165)
{
         hero.newPos();
         hero.update();
    }// hero.y

for (i = 0; i < myObstacles_airport.length; i += 1) {
        myObstacles_airport[i].x += -1;
        myObstacles_airport[i].update();
    }

if (hero.y >165)
{
         hero.newPos();
         hero.update();
    }// hero.y

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

وقتی قبل ساختمان رسم بشه ، بعد رسم ساختمان ، ساختمان اون را می پوشاند.

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

در مورد درخت های پایین هم میشه همین کار را کرد ، که من در این ورژن هنوز نکردم ... یعنی همیشه درخت ها روی ماشین نصب می شود.

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

از نرم افزار زیر برای کاهش حجم عکس استفاده می کنم:


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

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

saalek110

Well-Known Member
ورژن ۵ ، ورژن بوته دار:


ورژن دارای علف در بیابان.

Screenshot_۲۰۲۴-۰۳-۰۱_۰۸۳۹۴۰.jpg

من چهار تا آرایه برای علف ساختم ، چون سرعت علف ها در فاصله های مختلف ، باید متفاوت باشه.
کد حرکت علف ها:
JavaScript:
for (i = 0; i < myObstacles_grass1.length; i += 1) {
        const g1=2/10;
        myObstacles_grass1[i].x += -g1;
        myObstacles_grass1[i].update();
   }
for (i = 0; i < myObstacles_grass2.length; i += 1) {
        const g2=3/10;
    myObstacles_grass2[i].x += -g2;
        myObstacles_grass2[i].update();
    }
for (i = 0; i < myObstacles_grass3.length; i += 1) {
        const g3=4/10;
    myObstacles_grass3[i].x += -g3;
        myObstacles_grass3[i].update();
   }
for (i = 0; i < myObstacles_grass4.length; i += 1) {
        const g4=6/10;
    myObstacles_grass4[i].x += -g4;
        myObstacles_grass4[i].update();
    }

اعداد کسری:
اینکه چرا کسری دادم و اعشاری ندادم، چون اعداد اعشاری خودبخود پاک میشد،.شاید مشکل از ادیتورم بود.

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

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

استفاده از تابع راندوم:
با تابع راندوم میشه نامنظم کرد مکان نشستن علف ها را... یک مقدار با تابع راندوم کار کردم من، بعدا بیشتر کار می کنم. روی اینکه چه زمانی متولد بشن میشه کار کرد، و روی اینکه y شون و x شون چقدر باشه هم میشه کار کرد. اعدادی هم که به تابع راندوم می دهید موثر است.
 
آخرین ویرایش:

saalek110

Well-Known Member
1709285870482.jpg



دکمه های افزایش و کاهش سرعت اضافه شد.
عدد میلی سکند اجرای تابع update در کنار y با فونت ریز نمایش داده شده.
در شکل زیر توضیح داده شده:


Screenshot_۲۰۲۴-۰۳-۰۱_۱۳۰۱۳۸.jpg

طرز ساخت سرعت:
اول برنامه یک متغیر بیرون توابع تعریف کردم به نام s و مقدار ۱ بهش دادم.
چون بیرون توابع تعریف شده ، داخل توابع هم شناخته شده است. پس داخل تابع update میشه ازش استفاده کرد.
اگر داخل تابع uodate اون متغیر را تعریف می کردم. اگر بهش مقدار می دادم...چون تابع update چرخشی هی اجرا می شود ، مدام اون مقدار اولیه را به متغیر s می داد. پس ترجیح دادم اول برنامه مقدار بدهم.

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

saalek110

Well-Known Member
تحلیل بازی ماشین و هواپیما:
می دانید که من همان بازی سایت w3school را تغییر دادم.
در اون بازی ، دیوارهایی بود که جلو می آمد و یک مربع را باید از میان دیوارها رد می کردیم.
کاری که من کردم ، به جای دیوارها ، عکسهایی را از انتهای صفحه به سمت چپ می فرستم.
تنها برخورد بین ماشین و اون صفحه قرمز است. ماشین ورژن ۶ دیگه با چیزی برخورد ندارد. هواپیما با قسمتهایی از فرودگاه برخورد داشت. ورژن های اول ماشین هم برخورد با اونها داشتند ولی حذف شد.

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

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

saalek110

Well-Known Member
ساختار کلی بازی:

همان طور که در بررسی قالب گفتیم. یک تابعی به صورت مکرر اجرا میشه ، که اسم اون را من uptade میگم.

در تابع update , کارهایی انجام می شود.
اول: ساختن اشیایی در انتهای راست زمین.
دوم: کاهش x اون اشیا تا به سمت چپ بیایند.
سوم: حرکت دادن و نشان دادن قهرمان.

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

saalek110

Well-Known Member
چند تا کلاس نیاز داریم؟

اینکه آیا هر آرایه ، یک کلاس می خواد یا همه آرایه ها می تونن از یک کلاس استفاده کنند... در بازی سایت w3school دیدیم که حتی چاپ فریم نامبر را هم با همون کلاس انجام می داد. ولی من یک کلاس اون بازی را تبدیل به دو کلاس کردم و چاپ فریم نامبر را هم خودم انجام دادم.

یعنی میشه بیاییم توسط یک کلاس به چندین آرایه سرویس بدهیم.
یک سری اشیا مستطیل هستند و یک سری عکس دارند. اگر بخواهیم با ی کلاس به این دو سرویس بدهیم باید مثل طراح سایت school بیاییم tpye تعریف کنیم.

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


ولی چند تا آرایه نیاز داریم؟

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

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

saalek110

Well-Known Member
در مورد رفتارهای کلاسهای دیگر:


در بازی تانک دیدید که من یک صفت به اسم health به دیوار اضافه کردم ، و وقتی تانک به یک دیوار برخورد می کرد ، صفت سلامت اون ۵۰ میشد، اولش ۱۰۰ بود. و موقع رسم تابع update کلاس ، اگر صفت سلامت ۵۰ بود ، اون دیوار را قهوه ای رسم می کرد.

فکر کنم میشه تابع تخریب اضافه کرد به کلاس ، و موقع برخورد اتفاقاتی پشت سر هم بیافتد. مثلا قطعاتی به اطراف پرت شود.
 

saalek110

Well-Known Member
چگونگی تکمیل بازی:

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

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

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

saalek110

Well-Known Member
مقایسه اسپریت شیت با فایل gif:

ممکن است اون فایل gif خوان کیفیت خوبی نداشته باشه ، برنامه های متعددی برای این کار هست. شاید بعدا کار کردیم.(ادیت بعدا: من برای هر شی یک groove ساخته بودم و برنامه سنگین شده بود ، ولی حالا برای هر عکس فقط یک groove ساختم و بهتر شد. شاید اشتباه از من بود نه اون gif خوان)

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

جدیدترین ارسال ها

بالا