گودو گیم دو، بلاگ بازی سازی با انجین گودو Godot

گودو گیم دو، بلاگ آموزشی و اطلاع رسانی انجین بازی سازی گودو (Godot) است. در این بلاگ مطالب زیادی درباره انجین گودو و بازی سازی یاد میگیرید.

تابع clamp در انجین گودو برای محدود کردن یک متغیر

سلام به همه دوستداران گودو. یه مدتی نبودم. تو این مدت مهمترین اتفاقی که افتاده اینه که ورژن 4.2 گودو منتشر شد(و من هم تو این آموزش ازش استفاده میکنم) که تو بعضی زمینه ها نسبت به ورژن قبلی بهبود داشت. و خبر خوب دیگه این که فروم یا انجمن گودو به روز شد که جای خیلی خوبیه برای سوال پرسیدن و معاشرت کردن با دیگر توسعه دهندگان گودو. اینم آدرسش :

 https://forum.godotengine.org

با یه آموزش کاربردی دیگه اومدم. اول مسئله رو مطرح میکنم. وقتی میخواید یه متغیرو بین دوتا مقدار حداقل و حداکثر، یا کمینه و بیشینه محدود کنید، چه کار میکنید؟ خوب، اولین گزینه ای که به ذهن آدم میاد اینه که در تابع proccess  یا physics_proccess از چند تا دستور شرطی استفاده کنه و بگه: اگه مقدار متغیر از x کمتر شد، تو اون رو برابر مثلا 0 قرار بده و اگه از فلان مقدار بیشتر شد، تو این رو برابر یا 1000 قرار بده. این ایرادی نداره و احتمالا کار میده. ولی همیشه اولین راه حل، بهترین راه حل نیست. راه های بهتری هم هست. این راهی کی میخوایم ازش صحبت کنیم، تابع clamp ئه. 

تابع clamp یک متغیر رو بین دوتا مقدار کمینه و بیشینه نگه میداره و اجازه نمیده از اون حدود تجاوز کنه. یک بار برای همیشه بیاید و clamp رو یاد بگیرید و همیشه ازش استفاده کنید. این قدر برای همه چیز شرط if نزنید(خطاب به خودم!).

توی پروژه کوچیکی که برای مثال این مطلب استفاده میکنم، یک آبجکت داریم که با دکمه بالا و پایین حرکت میکنه ولی از بالا و پایین تصویر، اون طرف تر نمیره. 

اول scenetree رو لوازم مورد نیاز رو براتون میذارم و بعد کد، و کد رو توضیح میدم. 

صحنه ما از یک node2D که سرشاخه است و یک scene به نام animal  تشکیل شده. صحنه animal، خودش شامل یک نود character2d به عنوان سرشاخه و دوتا نود زیر مجموعه که یکی sprite2d و دیگری collisionshape2d ئه و هر دو برای ساخت یک character2d میشه گفت ضروری هستن. 

 و حالا صحنه animal و چینش صفحه بازی. من animal رو آوردم وسط صفحه و رنگ پس زمینه رو به آبی روشن تغییر دادم. 

این از پیش نیازهای پروژه.

حالا دقت کنید که animal  یه اسکریپت داره. کد این اسکریپت به شرح زیره:

(خطایی توی تصویر هست، برای این که حرکت درست باشه جای 250 و منفی 250 باید عوض شه)

به ترتیب شماره گذاری توضیح میدم:

  1. یک متغیر از نوع vector2 به نام movement تعریف کردم.
  2. در تابع پیش ساخته physics_proccess دو تا شرط برای حرکت رو به بالا و رو به پایین نوشتم. به این صورت که وقتی کلید بالای کی برد فشرده شد، متغیر movement برابر بشه با مقداری که میبینید که  x اش صفره و y اش 250. و اون رو ضربدر delta کردم.و همین کار برای دکمه پایین کی برد. دقت کنید هنوز حرکتی صورت نگرفته.
  3. اینجا گفتم که position نود مورد نظر هر چی که هست با مقدار movement جمع بشه که بسته به دکمه بالا یا پایین، یا مقدارش کم میشه ( حرکت رو به بالا) یا مقدارش زیاد میشه (حرکت رو به پایین). به خاطر این که در گودو y رو به پایین مقدارش افزایش پیدا میکنه. و بعد هم تابع move_and_slide رو استفاده کردم که از توابع نود character2d ئه و عملا تغییر پوزیشن رو اعمال میکنه.
  4. میرسیم به خط طلایی که مقدار global_position بین 0 و عرض تصویر بازی(get_viewport)، محدود میکنه. 

   اول نتیجه بهتون نشون میدم و بعد چند نکته میگم:

تابع clamp  به چند صورت استفاده میشه. میشه به طور ساده ازش استفاده کرد که در این حالت تابع، سه تا ورودی میگیره: متغیر مورد نظر ، مقدار حداقل، مقدار حداکثر. 

یا این که مثل من روی یک مقدار که از نوع vector2 ئه به کارش ببرید. چون نوع vector2 خودش تابع clamp برای تعریف شده. در این صورت متغیر وکتور2 خودتون رو مینویسید و بعد clamp و بعد مقدار حداقل و حداکثر رو وارد میکنید. 

نکته خیلی مهم:

برای این که اثر clamp اعمال بشه، حتما باید برابر با متغیر قرار بگیره. clamp خالی هیچ کاری نمیکنه.

توی تصویر ببینید من چجوری نوشتم.

خوب آموزش به پایان رسید. فکر کنید ببینید کجاها این به درد میخوره. مثلا یک بازی  space shooter  که پلیر سمت چپ تصویره و باید مهاجما رو از بین ببره و دامنه حرکتش از بالا تا پایین تصویره. یا فرض کنید میخواید سرعت یه آبجت از یه حدی فراتر نره.

امیدوارم این آموزش استفاده کنید و نظراتتون رو بهم بگید و سوال بپرسید.موفق باشید. 

  • 0 نظر
  • 0 پسند
    • danial abdl
    • 14:03 1402/09/28

    روش ساده سیو و لود داده ها در گودو در قالب یک پروژه ساده

    در این پست، روش ساده ای برای سیو و لود کردن داده‌ها توی انجین بازی سازی گودو ارائه میدم. برای این کار روشهای مختلفی وجود داره. این روشی که بهتون نشون میدم برای ذخیره یک داده است. یعنی هر تابع ذخیره و لود کردن، یک داده رو ذخیره و لود میکنه و برای سیو و لودهای ساده کاربرد داره. 

    آموزش رو در قالب یک پروژه کوچیک انجام میدیم و در آخر فایل پروژه رو براتون میذارم و میتونید دانلود کنید.

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

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

    پروژه ما در ابتدا این شکلی خواهد بود.

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

     بخش اتولود که فایل general رو قرار میدیم این شکلی میشه.

    لازمه که برای هر دو دکمه، سیگنال pressed  رو به نود سرشاخه وصل کنیم که با این کار داخل اسکریپت node2d، دوتا تابع برای دو دکمه ایجاد میشه. در اسکریپت node2d، یک متغیر به نام coin مثلا برای تعداد سکه میسازیم. توی تصویر بالا برای لیبل و یکی از دکمه ها متغیر ایجاد کردم که ضروری نبوده و لازم نیست شما انجام بدید. در ابتدا اسکریپت نود 2d به این صورته. 

    بعد توی اسکریپت general چندتا کار باید انجام بدیم. 

    • یک متغیر برای سکه ها (که قراره برای سیو و لود استفاده بشه) ایجاد کنیم که من برای این که با اون یکی متغیر اشتباه نگیریدش به نام G_coin ساختم. 
    • یک متغیر رشته ای برای ذخیره مسیر فایلی که متغیر ما قراره توش سیو بشه که اسمش رو گذاشتم coin_save_path. دقت کنید که در ابتدای این آدرس از "user" استفاده شده و به فرض در موبایل، این ادرس میشه فولدر اصلی گوشی شما یا به اصطلاح root. 
    • یک تابع برای سیو. در این تابع کاری که انجام میدیم اینه که یک فایل ایجاد میکنیم و اون رو برای ذخیره کردن یا WRITE باز میکنیم، و متغیر G_coin رو در اون ذخیره میکنیم. 
    • یک تابع برای لود کردن. در این تابع اول بررسی میکنیم که اگر فایلی که قراره ساخته بشه وجود داره(برای جلوگیری از خطا) متغیر ذخیره شده رو در متغیر G_coin قرار بده یا لود کنه.
    • یک تابع برای ریست کردن مقدار ذخیره شده. برای این که بتونید برنامتون رو بارها تست کنید. اسکریپت general به این شکل خواهد بوددقت کنید که برای ذخیره کردن در فایل WRITE استفاده میشه و برای لود کردن از READ. یک نکته دیگه این که من تابع reset_coins رو در تابع ready فراخوانی کردم، ولی فعلا به صورت کامنت درش آوردم تا فراخوانی نشه. بعدا درباره این توضیح میدم. 

    حالا باید در اسکریپت node2d تغییراتی ایجاد و اون رو تکمیل کنیم. اسکریپت در آخر اینجوری میشه:

    به این موارد توجه کنید:

    • وقتی دکمه افزایش عدد زده(button2) میشه، مقدار coin ده تا افزایش پیدا میکنه و متن لیبل هم به روز میشه، یعنی دوباره مقدار جدید میگیره. دقت کنید که کلمه score و علامت : به مقدار عدد سکه اضافه میشه. 
    • وقتی دکمه ذخیره (button) زده میشه، اول مقدار G_coin برابر با مقدار coin میشه. به این دلیل که ما مقدار coin رو تغییر دادیم. میخوایم مقدار G_coin  که قراره ذخیره بشه هم بروز بشه. و بعد تابع save_coin فراخوانی میشه و مقدار رو ذخیره میکنه. به طور کلی coin  در G_coin ذخیره میشه و بعد در فایل ذخیره میشه. 
    • در تابع ready  که در ابتدای برنامه لود میشه، قراره عمل لود کردن رو انجام بدیم. پس اول تابع load رو از general فراخوانی میکنیم. بعد مقدرا coin رو برابر با مقدار G_coin که تازه از فایل لود شده میکنیم. و در نهایت هم متن لیبل رو بروزرسانی میکنیم. چون تا مقدار جدید رو نمایش ندیم نمیتونیم بفهمیم که سیو و لود به درستی انجام شده یا نه. 

    حالا وقتی پروژه رو اجرا کنید باید با چنین چیزی روبرو بشید:

    میبینید که هر بار که عدد رو افزایش میدم و ذخیره میکنیم، وقتی که برنامه میبندیم و دوباره باز میکنیم، مقدار سکه ذخیره شده. 

    در نهایت اگه خواستید مقدار ذخیره شده رو ریست کنید یا صفر کنید، تابع reset_coin رو در ready از حالت کامنت خارج کنید و pass  رو کامنت کنید، یک بار برنامه رو اجرا کنید و خارج بشید. و دوباره reset_coin رو به حالت کامنت دربیارید و pass  رو از کامنت خارج کنید.به این شکل:

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

    فایل پروژه:

    دانلود

  • 0 نظر
  • 1 پسند
    • danial abdl
    • 16:00 1402/08/10

    متغیرهای سراسری و اتولود (autoload) در انجین بازی گودو

    در هر بازی متغیرها و داده‌هایی وجود داره که میخواید در تمام صحنه‌های بازی بهشون دسترسی داشته باشید. برای این منظور باید از اسکریپت‌هایی استفاده کنید که از همه اسکریپت‌ها و صحنه‌ها قابل دسترسی هستن. به این قابلیت در گودو میگن اتولود (autoload). کاری که باید کنید اینه که یه اسکریپت ایجاد کنید و اون رو اتولود کنید و در اسکریپت‌های دیگه بهش ارجاع میدید. اما چجوری؟

    در یه مثال ساده این رو بهتون نشون میدم. 

    اول از همه یه پروژه جدید ایجاد کنید و یه نود دوبعدی و یه لیبل زیر مجموعه‌اش ایجاد کنید. صحنه رو ذخیره کنید و نام main بهش بدید. این‌کارها رو در آموزش‌های قبلی یاد گرفتید. ساختار صحنه‌تون به این شکل خواهد بود.

     

    میخوایم اسکریپت اتولود رو بسازیم. در بخش filesystem روی res کلیک راست  و بعد گزینه create new و بعد script رو انتخاب کنید.اسمشو بذارید General یعنی عمومی یا سراسری. 

    حالا اسکریپت جنرال رو میخوایم اتولود کنیم. از مسیرsetting و بعد project setting، تب autoload رو انتخاب میکنیم. برای اضافه کردن اسکریپت به اتولود روی آیکون فولدر کلیک میکنیم، اسکریپت General رو انتخاب میکنیم و open  رو کلیک میکنیم. در نهایت سمت راست صفحه دکمه Add رو میزنیم تا اسکریپت به لیست اضافه بشه. 

    برای نشون داده استفاده از اتولود، به نود سرشاخه یه اسکریپت اضافه کنید. دقت کنید که حالا در کل پروژه 2 تا اسکریپت داریم. 

    توی این قسمت میخوایم داخل اسکریپ General یه متغیر ساده اضافه کنیم تا بتونیم توی اسکریپت main ازش استفاده کنیم و متن اون رو توی لیبل نشون بدیم. اینجا میخوام نحوه تایپ و کدنوشتن هم بهتون نشون بدم. گاهی اوقات وقتی بخشی از کلمه رو تایپ میکنید، برنامه به شما کلمه رو پیشنهاد میده و با کلید Enter میتونید انتخابش کنید. یه متغیر به نام text میسازم و مقدارشو (متنشو) میذارم "General text". متنها همیشه در کدنویسی گودو بین دوتا علامت " قرار میگیرن.  

    حالا توی اسکریپت main از متغیری که توی اسکریپت general هست استفاده میکنیم. دقت کنید که هر چندتا اسکریپت دیگه هم داشتیم و حتی اگه  در صحنه های دیگه هم بودن، میتونستیم به متغیرهای General دسترسی داشته باشیم. 

    کاری که توی این کد انجام میشه اینه که در فانکشن یا تابع ready ، به لیبل ارجاع میدم و متنشو برابر با متن متغیر text  از اسکریپت general  میکنم.( تابع ready یکی از تابع های پیش ساخته گودوئه و هر اسکریپتی در شروع صحنه، تابع ready رو اجرا میکنه. )

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

    در نهایت وقتی صحنه رو اجرا کنیم، داخل لیبل متن General text نشون داده میشه. 

    فایده اتولود اینه که شما رو از دوباره‌کاری بی نیاز میکنه. فرض کنید 10 تا صحنه داشتید که میخواستید اون متن رو توی همشون نشون بدید. باید در هر 10 تا صحنه متغیری میساختید. ولی با این روش یک بار نوشتید و میتونید 10 بار یا بیشتر استفاده کنید. 

    درآخر کدها رو میذارم تا داشته باشید.

    ...

  • 0 نظر
  • 0 پسند
    • danial abdl
    • 20:28 1402/07/23