🎮 جزوه آموزشی گودوت ۴.۷ – جلسه اول
🔰 شروع کار با گودوت
به اولین جلسه آموزشی گودوت خوش آمدید! در این جزوه، همه چیز را از صفر شروع میکنیم و با هم یک بازی ساده اما کامل میسازیم.
🧩 آشنایی با توابع (Functions) در گودوت
قبل از شروع پروژهها، باید بدانیم تابع (Function) چیست و چه انواعی در گودوت وجود دارد. تابع یک بلوک کد است که کار مشخصی را انجام میدهد. در گودوت، توابع با کلمه کلیدی func تعریف میشوند.
انواع توابع مهم در گودوت :
| نام تابع | کاربرد | نحوه نوشتن |
|---|---|---|
| _ready() | وقتی بازی را شروع می کنیم بازی را اجرا می کند | func _ready(): |
| _physics_process(delta) | هر فریم فیزیک (۶۰ بار در ثانیه) اجرا میشود. برای حرکت و برخورد مناسب است.در طول بازی ، بازی را دقیق اجرا میکند. | func _physics_process(delta: float) -> void: |
| _process(delta) | هر فریم (معمولاً ۶۰+ بار) اجرا میشود. برای انیمیشن و ورودیهای غیرفیزیکی.در طول بازی، بازی را بهینه اجرا می کند. | func _process(delta: float) -> void: |
| _input(event) | وقتی رویداد ورودی (کیبورد/ماوس) رخ میدهد، اجرا میشود.داده ها رو از کاربر دریافت میکنه و با استفاده از اونها بازی رو اجرا میکنه. | func _input(event: InputEvent) -> void: |
| _on_signal_name() | توابعی که به سیگنالها متصل میشوند (مثل برخورد). | func _on_body_entered(body: Node2D) -> void: |
- متغیر ها در گودوت با var نشان داده می شوند. در پایتون ما اسمشون رو مینوشتیم و برای هر var می تونیم یه اسم مشخص کنیم مثلا var num: int=10 و در خط بعدی سرخط می نویسیم func_ready()->void: و در خط بعدی با یک تب تورفتگی زیر readu می نویسیم print(num) و وقتی اجرا رو بزنیم ، برای ما چاپ میکند عدد ۱۰ را . این در خط اوش بایند باشه extends node20
- همه توابع باید با تو رفتگی (Indentation) صحیح نوشته شوند. یعنی بعد از func … : خط بعدی باید یک تب (Tab) یا چهار فاصله (Space) جلوتر باشد.
- در گودوت ، اگر تو رفتگی اشتباه باشد، کد اجرا نمیشود و خطای “indentation error” میدهد.
- برای حرکت از تابع _physics_process استفاده کنید، نه _process.
پروژه ۱ ایجاد صحنه و کاراکتر (CharacterBody2D)
در اولین پروژه، یک پروژه جدید در گودوت ایجاد میکنیم، یک صحنه میسازیم و یک کاراکتر ساده (به شکل یک مربع رنگی) به آن اضافه میکنیم. این کاراکتر هنوز حرکت نمیکند، فقط در صحنه نمایش داده میشود.
مراحل گامبهگام:
🔧 مرحله ۱: ایجاد پروژه جدید
- گودوت را باز کنید. در پنجره Project Manager، روی New Project کلیک کنید.
- نام پروژه را MyFirstGame بگذارید و یک پوشه خالی برای آن انتخاب کنید.
- روی Create & Edit کلیک کنید تا وارد محیط ویرایشگر شوید.
🖼️ مرحله ۲: ساخت صحنه اصلی
- در پنل Scene (سمت چپ)، روی دکمه + (Add New Node) کلیک کنید.
- در پنجره جستجو، عبارت CharacterBody2D را تایپ کرده و آن را انتخاب کنید. این گره پایه کاراکتر ما خواهد بود.
- روی Create کلیک کنید. نام گره را به Player تغییر دهید (با دوبار کلیک روی نام).
🎨 مرحله ۳: اضافه کردن ظاهر (Sprite2D)
- روی گره Player کلیک راست کرده و Add Child Node را انتخاب کنید.
- در جستجو، Sprite2D را پیدا کرده و ایجاد کنید.
- در پنل Inspector (سمت راست)، در بخش Texture، روی Load کلیک کنید و یک تصویر ساده (مثلاً یک مربع رنگی ۳۲×۳۲) انتخاب کنید. اگر تصویری ندارید، میتوانید از آیکون پیشفرض گودوت (icon.svg) استفاده کنید.
📦 مرحله ۴: اضافه کردن برخورد (CollisionShape2D)
- دوباره روی Player راست کلیک کرده و Add Child Node → CollisionShape2D را انتخاب کنید.
- در Inspector، در بخش Shape، روی [empty] کلیک کرده و New RectangleShape2D یا New CapsuleShape2D را انتخاب کنید .
- ابعاد مستطیل را حدوداً ۴۰×۴۰ پیکسل تنظیم کنید.
💾 مرحله ۵: ذخیره و تست
- صحنه را با Ctrl+S ذخیره کنید و نام آن را lv1.tscn بگذارید .
- روی فایل lv1.tscn در FileSystem راست کلیک کرده و Set as Main Scene را انتخاب کنید.
- کلید F5 را بزنید تا بازی اجرا شود. یک پنجره سفید با کاراکتر در وسط آن خواهید دید.
پروژه ۲ آموزش توابع و حرکت به چپ و راست
در این پروژه، با نحوه نوشتن تابع و تو رفتگی صحیح آشنا میشوید و به کاراکتر خود حرکت افقی (چپ و راست) با استفاده از کلیدهای A و D میدهیم.
مراحل گامبهگام:
📝 مرحله ۱: اتصال اسکریپت به کاراکتر
- روی گره Player کلیک راست کرده و Attach Script را انتخاب کنید.
- نام فایل را lv_1.gd بگذارید و روی Create کلیک کنید. ویرایشگر کد باز میشود.
✍️ مرحله ۲: نوشتن کد حرکت افقی با تو رفتگی صحیح
کد زیر را دقیقاً با تو رفتگی (Tab) که مشخص شده بنویسید. هر خط که با → مشخص شده، باید یک Tab جلوتر باشد.
extends CharacterBody2D
# سرعت حرکت افقی (پیکسل بر ثانیه)
@export var speed = 300
func _physics_process(delta: float) -> void:
# متغیر جهت حرکت افقی
var horizontal_input = 0
# تشخیص کلیدهای چپ و راست
if Input.is_action_pressed("ui_left"):
horizontal_input = -1
elif Input.is_action_pressed("ui_right"):
horizontal_input = 1
# اعمال سرعت به محور X
velocity.x = horizontal_input * speed
velocity.y = 0 # فعلاً عمودی حرکت نمیکنیم
# حرکت دادن کاراکتر و مدیریت برخورد
move_and_slide()
🧠 تحلیل خط به خط کد با تاکید بر تو رفتگی:
- خط ۱ (بدون تو رفتگی): extends CharacterBody2D – اعلان وراثت. همیشه در خط اول نوشته میشود.
- خط ۴ (بدون تو رفتگی): @export var speed = 300 – تعریف متغیر سرعت. در سطح اصلی اسکریپت (خارج از توابع) نوشته میشود.
- خط ۶ (بدون تو رفتگی): func _physics_process(delta: float) -> void: – شروع تابع. کولون (:) نشاندهنده شروع بدنه تابع است.
- خط ۷ (یک Tab جلوتر): var horizontal_input = 0 – این خط یک Tab جلوتر از خط قبلی است. یعنی داخل تابع است.
- خط ۱۰ (یک Tab جلوتر): if Input.is_action_pressed(“ui_left”): – باز هم یک Tab جلوتر.
- خط ۱۱ (دو Tab جلوتر): horizontal_input = -1 – این خط دو Tab جلوتر است. یعنی داخل شرط if قرار دارد.
- خط ۱۶ (یک Tab جلوتر): velocity.x = horizontal_input * speed – یک Tab جلوتر از تابع.
- خط ۱۹ (یک Tab جلوتر): move_and_slide() – یک Tab جلوتر از تابع.
- بعد از هر : (کولون) خط بعدی باید یک Tab جلوتر باشد.
- بعد از if، elif، else، for، while و func حتماً یک Tab جلوتر بروید.
- اگر تو رفتگی اشتباه باشد، گودوت خطای “indentation error” میدهد و کد اجرا نمیشود.
▶️ مرحله ۳: تست حرکت
- کد را ذخیره کنید (Ctrl+S).
- بازی را با F5 اجرا کنید. حالا با فشار دادن کلیدهای چپ و راست (جهتها) کاراکتر حرکت میکند.
پروژه ۳ اضافه کردن پرش با کلید Space
در این پروژه، قابلیت پرش را به کاراکتر اضافه میکنیم. با فشردن کلید Space (یا کلید بالا)، کاراکتر به سمت بالا میپرد. همچنین گرانش (Gravity) را به کد اضافه میکنیم تا کاراکتر به زمین برگردد.
مراحل گامبهگام:
✍️ مرحله ۱: افزودن کد پرش و گرانش
کد زیر را جایگزین اسکریپت قبلی کنید. به تو رفتگی دقت کنید.
extends CharacterBody2D
@export var speed = 300
@export var jump_strength = -500 # قدرت پرش (عدد منفی = بالا)
@export var gravity = 40 # شتاب گرانش
func _physics_process(delta: float) -> void:
# اعمال گرانش به سرعت عمودی
velocity.y += gravity
# حرکت افقی
var horizontal_input = 0
if Input.is_action_pressed("ui_left"):
horizontal_input = -1
elif Input.is_action_pressed("ui_right"):
horizontal_input = 1
velocity.x = horizontal_input * speed
# پرش (فقط زمانی که روی زمین هستیم)
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = jump_strength
# حرکت و برخورد
move_and_slide()
🧠 تحلیل خطهای جدید:
- خط ۵ (بدون تو رفتگی): @export var gravity = 40 – متغیر گرانش. هر فریم به سرعت عمودی اضافه میشود.
- خط ۹ (یک Tab جلوتر): velocity.y += gravity – این خط داخل تابع است. هر فریم، مقدار gravity به velocity.y اضافه میشود.
- خط ۲۰ (یک Tab جلوتر): if Input.is_action_just_pressed(“ui_accept”) and is_on_floor(): – شرط پرش. is_action_just_pressed یعنی فقط در لحظه فشار دادن دکمه (نه نگه داشتن). is_on_floor() یعنی کاراکتر روی زمین است.
- خط ۲۱ (دو Tab جلوتر): velocity.y = jump_strength – داخل شرط if قرار دارد. سرعت عمودی را برابر قدرت پرش میکند.
▶️ مرحله ۲: تست پرش
- کد را ذخیره کنید و بازی را اجرا کنید.
- با کلید Space (یا فلش بالا) کاراکتر میپرد و دوباره به زمین برمیگردد.
- اگر کاراکتر از صفحه خارج شد، در پروژه بعدی یک زمین (Floor) به صحنه اضافه میکنیم.
پروژه ۴ اضافه کردن زمین (Floor) و بهبود پرش
در این پروژه، یک زمین (سکوی جامد) به صحنه اضافه میکنیم تا کاراکتر روی آن بایستد. همچنین کد پرش را با متغیر کمکی برای جلوگیری از پرش دوباره در هوا بهبود میدهیم (مطابق کدهای تصاویر شما).
مراحل گامبهگام:
🖼️ مرحله ۱: ایجاد گره زمین (StaticBody2D)
- در پنل Scene، روی گره ریشه (Player) کلیک راست کرده و Add Child Node → StaticBody2D را انتخاب کنید. نام آن را Floor بگذارید.
- زیر Floor، یک گره CollisionShape2D اضافه کنید.
- در Inspector، برای Shape یک RectangleShape2D جدید بسازید و اندازه آن را ۱۰۰۰×۳۰ پیکسل تنظیم کنید.
- گره Floor را در پایین صفحه قرار دهید (با تغییر Position Y به حدود ۵۰۰).
- برای دیدن زمین، یک Sprite2D زیر Floor اضافه کنید و یک بافت ساده (مثلاً مستطیل سبز) به آن بدهید.
✍️ مرحله ۲: بهروزرسانی کد با متغیر پرش (مشابه تصاویر)
این کد شامل متغیر parresh (پرش) است که از پرش دوباره در هوا جلوگیری میکند.
extends CharacterBody2D
var sorat = Vector2(0, 0) # بردار سرعت (شبیه velocity)
var parresh = false # آیا در حال پرش هستیم؟
func _physics_process(delta: float) -> void:
# اگر در حال پرش نیستیم، گرانش اعمال کن
if parresh == false:
sorat.y += 40
# پرش (فقط روی زمین)
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
parresh = true
sorat.y = -500
# بعد از ۰٫۵ ثانیه، parresh را false کن
await get_tree().create_timer(0.5).timeout
parresh = false
# حرکت افقی
if Input.is_action_pressed("A"):
sorat.x = -200
elif Input.is_action_pressed("D"):
sorat.x = 200
else:
sorat.x = 0
# اعمال سرعت به کاراکتر
set_velocity(sorat)
move_and_slide()
🧠 تحلیل کد با تاکید بر تو رفتگی و متغیرها:
- خط ۴ (بدون تو رفتگی): var sorat = Vector2(0, 0) – متغیر سرعت (مشابه velocity).
- خط ۵ (بدون تو رفتگی): var parresh = false – متغیر وضعیت پرش. اگر true باشد، کاراکتر در حال پرش است.
- خط ۹ (یک Tab جلوتر): if parresh == false: – اگر در حال پرش نیستیم…
- خط ۱۰ (دو Tab جلوتر): sorat.y += 40 – گرانش اعمال میشود.
- خط ۱۳ (یک Tab جلوتر): if Input.is_action_just_pressed(“ui_accept”) and is_on_floor(): – شرط پرش.
- خط ۱۴ (دو Tab جلوتر): parresh = true – در حال پرش هستیم.
- خط ۱۵ (دو Tab جلوتر): sorat.y = -500 – سرعت عمودی (پرش).
- خط ۱۶ (دو Tab جلوتر): await get_tree().create_timer(0.5).timeout – ۰.۵ ثانیه صبر کن.
- خط ۱۷ (دو Tab جلوتر): parresh = false – بعد از ۰.۵ ثانیه، پرش تمام شد.
- دستور await در گودوت برای توقف موقت اجرا استفاده میشود.
- تابع get_tree().create_timer(0.5).timeout یک تایمر ۰.۵ ثانیهای میسازد و بعد از اتمام آن، اجرا ادامه مییابد.
- این روش برای جلوگیری از پرش دوباره در هوا استفاده میشود.
▶️ مرحله ۳: تست نهایی
- کد را ذخیره کنید و بازی را اجرا کنید.
- کاراکتر حرکت میکند، روی زمین میایستد و میپرد. بعد از پرش، تا ۰.۵ ثانیه نمیتواند دوباره بپرد.
