Godot Engine Eğitim Serisi - Bölüm 6: 2D Oyun Projesine Hazırlık ve Oyuncu Karakteri
Godot ile 2D oyun geliştirme: ekran ayarları, AnimatedSprite2D, CollisionShape2D ve 8 yönlü hareket kodu. Türkçe eğitim.
Önceki bölümlerde Godot’nun temel yapı taşlarını öğrendiniz. Artık tüm bu bilgileri bir araya getirip “Dodge the Creeps!” adlı tam teşekküllü bir 2D oyun geliştirme zamanı! Bu oyunun temel mantığı oldukça basittir: Karakterinizi kontrol ederek rastgele yönlerden gelen düşmanlardan kaçmalı ve ekranda olabildiğince uzun süre hayatta kalarak skorunuzu artırmalısınız.
Bu ilk büyük adımımızda proje ayarlarını yapacak, oyuncu sahnesini inşa edecek ve hareket mekaniklerini kodlayacağız.
Serinin sonunda bu oyunu yapmış olacaksınız — hem de sıfırdan!
Proje Kurulumu ve Ekran Ayarları
İhtiyacınız olan Tasarım Görselleri
Öncelikle yeni bir Godot projesi oluşturun ve daha önce indirdiğiniz oyun varlıkları arşivindeki art/ ve fonts/ klasörlerini proje dizininizin (res://) içine sürükleyip bırakın.
Project Manager’da “New Project” butonuyla yeni proje oluşturuyoruz
Proje klasöründe art/ ve fonts/ klasörleri yerli yerinde
Oyunumuz dikey (portrait) modda oynanacak şekilde tasarlandığı için ekran boyutunu buna göre ayarlamanız gerekiyor:
Menüden Project > Project Settings yolunu izleyin ve sol sütundan Display > Window sekmesini açın.
Viewport Width (Genişlik) değerini
480, Viewport Height (Yükseklik) değerini ise720olarak ayarlayın.
Viewport boyutlarını 480x720 olarak ayarlıyoruz — dikey oyun penceresi
- Aynı sayfada aşağı inerek Stretch (Ölçekleme) ayarlarını bulun. Mode ayarını
canvas_items, Aspect ayarını isekeepyapın.
Stretch ayarları — oyunun farklı ekran boyutlarında tutarlı görünmesini sağlar
💡 Bilgilendirme: Bu stretch (ölçekleme) ayarları sayesinde oyun pencereniz farklı monitörlerde veya mobil cihazlarda yeniden boyutlandırıldığında oyun alanınızın orantısı bozulmadan tutarlı bir şekilde büyüyüp küçülecektir.
Oyuncu Sahnesini (Player) İnşa Etmek
Oyununuzun en önemli parçasını, yani oyuncu karakterini ayrı bir sahne olarak oluşturacağız. Böylece oyunun diğer parçaları hazır olmasa bile oyuncuyu bağımsız olarak test edebilirsiniz.
- Scene > New Scene ile yeni bir sahne oluşturun ve kök node olarak
Area2Dekleyin. Node’un adınıPlayerolarak değiştirin. NedenArea2D? Çünkü bu node, diğer nesnelerle (düşmanlarla) olan çarpışmaları ve üst üste gelmeleri algılamak için özel olarak tasarlanmıştır.
Scene sekmesinde “Other Node” ile Area2D ekliyoruz
Area2D, çarpışma algılamak için bir şekle ihtiyaç duyar — bunu ilerleyen adımda ekleyeceğiz
Playernode’una birAnimatedSprite2Dçocuk node’u ekleyin. Bu node görseli ve animasyonları yönetecektir.- Inspector panelinden Animation > Sprite Frames alanına tıklayıp New SpriteFrames seçeneğini işaretleyin. Açılan panelde
walkveupadında iki farklı animasyon oluşturun.
Inspector’da “New SpriteFrames” oluşturuyoruz
SpriteFrames paneli — animasyonları ve karelerini burada yönetiriz
art/klasöründeki görsellerdenplayerGrey_walk1veplayerGrey_walk2dosyalarınıwalkanimasyonuna,playerGrey_up1veplayerGrey_up2dosyalarını iseupanimasyonuna sürükleyin.
Her animasyona ait kareler panele eklendi
- Görseller oyun alanımız için biraz büyük kalacağından, Inspector’da
Node2Daltındaki Scale değerini(0.5, 0.5)yaparak karakteri yarı yarıya küçültün.
AnimatedSprite2D’nin ölçeği 0.5 olarak küçültüldü
Çarpışma Şeklini Eklemek
Area2D node’u, fiziksel sınırlarını bilmek için bir çarpışma şekline ihtiyaç duyar.
Playernode’una birCollisionShape2Dnode’u ekleyin.Inspector’dan Shape özelliğini
CapsuleShape2Dolarak seçin.- Kapsülü, ekrandaki sprite’ı (karakter görselini) tam olarak saracak şekilde boyutlandırın.
CapsuleShape2D, oyuncu sprite’ını kapsayacak şekilde ayarlandı
Yanlışlıkla çocuk node’ları hareket ettirmemek için kilitleme ayarı
- Sahneyi
player.tscnolarak kaydedin.
Player sahnesi tamamlandı: Area2D (kök), AnimatedSprite2D ve CollisionShape2D
Girdi (Input) Haritasını Ayarlamak
Karakteri klavye ile kontrol edebilmek için Godot’nun Input Map sistemini kullanacağız.
Project > Project Settings > Input Map menüsünü açın.
- Üstteki çubuğa sırasıyla
move_right,move_left,move_upvemove_downyazıp Add butonuna tıklayarak yeni eylemler oluşturun. - Her bir eylemin yanındaki ”+” ikonuna tıklayarak klavyenizdeki ok tuşlarını (veya dilerseniz W, A, S, D tuşlarını) bu eylemlere atayın.
Oyuncuyu Kodlamak: Hareket ve Animasyon
Sahne ve tuşlar hazır, şimdi onlara hayat verelim! Player node’una sağ tıklayıp bir Script ekleyin.
Değişkenler ve Hazırlık
Scriptinizin en üst kısmına karakterin hızını ve ekran boyutunu tutacak değişkenleri tanımlayın:
1
2
3
4
extends Area2D
@export var speed = 400
var screen_size
Kodun Satır Satır Açıklaması:
extends Area2D: Bu kod dosyasının sahnemizin kökü olanArea2Dnode’u için yazıldığını belirtir. Fiziksel örtüşmeleri (çarpışmaları) yakalayacağımız asıl yapı taşı budur.@export var speed = 400:speed(hız) adında bir değişken tanımlar ve saniyede 400 piksel gitmesi için değerini400yapar. Başındaki@exportanahtar kelimesi, bu değişkeni Godot editörünün sağ tarafındaki “Inspector” paneline taşır. Böylece oyunu test ederken kodu açmadan hızı kolayca değiştirip deneyebilirsiniz.var screen_size: Ekranın çözünürlük bilgisini hafızada tutmak için oluşturduğumuz başıboş bir değişkendir. Oyun motoru çalışınca ekran boyutunu öğrenip bu kutunun içine koyacağız.
Oyun başladığında ekran sınırlarını öğrenmek için _ready() fonksiyonunu kullanalım:
1
2
func _ready():
screen_size = get_viewport_rect().size
Kodun Satır Satır Açıklaması:
func _ready():: Script (yani oyuncu karakterimiz) oyuna ilk eklendiğinde Godot tarafından bir kere çağrılan açılış/hazırlık fonksiyonumuzdur.screen_size = get_viewport_rect().size:get_viewport_rect()kodu, oyunun oynandığı asıl pencerenin (viewport) dikdörtgen boyutlarını getirir..sizediyerek bunun sadece x (genişlik) ve y (yükseklik) değerlerini alırız ve bunu yukarıda boş olarak oluşturduğumuzscreen_sizeadlı değişkenin içine kaydederiz. Artık oyun ekranının ne kadar büyük olduğunu biliyoruz.
Hareket Döngüsü
Şimdi her karede çalışacak olan _process(delta) fonksiyonunu yazarak karakteri hareket ettireceğiz.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func _process(delta):
var velocity = Vector2.ZERO # Varsayılan olarak oyuncu hareketsizdir
if Input.is_action_pressed("move_right"):
velocity.x += 1
if Input.is_action_pressed("move_left"):
velocity.x -= 1
if Input.is_action_pressed("move_down"):
velocity.y += 1
if Input.is_action_pressed("move_up"):
velocity.y -= 1
if velocity.length() > 0:
velocity = velocity.normalized() * speed
$AnimatedSprite2D.play()
else:
$AnimatedSprite2D.stop()
position += velocity * delta
position = position.clamp(Vector2.ZERO, screen_size)
Kodun Satır Satır Açıklaması:
func _process(delta):: Oyun boyunca sürekli çalışan ana döngü fonksiyonumuz. Hareket gibi sürekli tekrarlanması gereken eylemler burada yapılır.var velocity = Vector2.ZERO # Varsayılan olarak oyuncu hareketsizdir: Karakterimizin baktığı yönü ve miktarını belirten hız (velocity) değişkenini başta sıfırlıyoruz. Hiçbir tuşa basılmıyorsa karakter durur.if Input.is_action_pressed("move_right"):ve sonrası: Eğer kullanıcı “move_right” (bizim atadığımız sağ ok tuşu) tuşuna basılı tutuyorsavelocity‘nin x (yatay) eksenini1artır (sağa git); “move_left” (sol ok) tuşuna basıyorsa x eksenini1azalt (sola git) diyoruz. Aynı mantıkla aşağı “move_down” basılınca y (dikey) eksenini1artırır, yukarı “move_up” basılınca y eksenini1azaltır.if velocity.length() > 0:: “Eğer hız vektörünün uzunluğu sıfırdan büyükse” yani oyuncu herhangi bir tuşa basıp harekete geçtiyse bu bloğa girer.velocity = velocity.normalized() * speed:normalized()çarpraz (hem üst hem sağ) gidildiğinde oyuncunun düz gitmesine göre 1.4 kat daha hızlı gitmesi hatasını düzeltir. Yönü bozmadan uzunluğu 1’e eşitler. Ardından bunu kalıcı hızımız olanspeed(400) ile çarparız.$AnimatedSprite2D.play(): Karakter hareket ettiğine göre, ona eklediğimizAnimatedSprite2Danimasyon oynatıcısını çalıştır (play()) diyoruz ki yürüme taklidi yapsın.else:: Yukarıdaki “eğer karakter hızlandıysa” durumunun tersidir. “Hayır, hiç hızı yoksa / duruyorsa” bu bloğa girer.$AnimatedSprite2D.stop(): Karakter durduğu için oynayan animasyonu durdurur.position += velocity * delta: Oyuncunun şu anki bulunduğu konuma (position), ulaştığımız nihai hızı (velocity) geçen zamanla (delta) çarparak ekleriz.position = position.clamp(Vector2.ZERO, screen_size): Bu son derece kritik bir satırdır. Karakterinposition‘ını alır ve onu iki değer arasına hapseder (clamp). İlk değerVector2.ZEROyani x:0, y:0 olan ekranın en sol-üst köşesi. İkinci değer en başta belirlediğimizscreen_sizedeğişkeni, yani ekranın en sağ-alt köşesi. Böylece oyuncu sınırlar dışına çıkamaz.
Bu kodda ne yaptık?
- Tüm basılan tuşlara göre
velocity(hız) vektörünü hesapladık. - Çapraz giderken (örneğin aynı anda sağa ve yukarı) karakterin %41 daha hızlı gitmesini önlemek için
velocity.normalized()kullanarak vektörü 1 birime sabitledik ve hızımızla çarptık. position += velocity * deltasatırıyla saniyedeki kare hızından (FPS) bağımsız bir hareket sağladık.- En önemlisi,
clamp()fonksiyonunu kullanarak karakterin pozisyonunun ekran sınırları dışına çıkmasını engelledik.
Animasyonları Yöne Göre Değiştirmek
Karakterimiz hareket ediyor ancak animasyonları hep aynı yöne bakıyor. _process() fonksiyonunun en sonuna şu kod bloğunu ekleyin:
1
2
3
4
5
6
7
if velocity.x != 0:
$AnimatedSprite2D.animation = "walk"
$AnimatedSprite2D.flip_v = false
$AnimatedSprite2D.flip_h = velocity.x < 0
elif velocity.y != 0:
$AnimatedSprite2D.animation = "up"
$AnimatedSprite2D.flip_v = velocity.y > 0
Kodun Satır Satır Açıklaması:
if velocity.x != 0:: Eğer x (yatay) ekseninde bir hız varsa(!= 0)sıfıra eşit değilse, yani oyuncu sağa ya da sola gidiyorsa.$AnimatedSprite2D.animation = "walk": Animasyon oynatıcıya yukarıda tasarladığımız “walk” yani yan yürüyüş animasyonuna geçmesini söyler.$AnimatedSprite2D.flip_v = false: Animasyonun dikey (vertical) olarak ters dönmemesi / düz olması gerektiğini kesinleştirir.$AnimatedSprite2D.flip_h = velocity.x < 0: Animasyon sağ tarafa doğru bakarak çizilmiştir. Eğer karaktervelocity.x < 0ise yani hızı sıfırın altında (eksiye/sola) doğru gidiyorsaflip_hyatay çevirme (horizontal) değerinitrueyaparız. Sağa gidiyorsa (hızı pozitifse) bu şart sağlanmaz vefalsedönerek görseli çevirmez.elif velocity.y != 0:: Eğer yatayda hareket yoksa ama dikeyde (y ekseni) hareket varsa bu sefer bu bloğa girer.$AnimatedSprite2D.animation = "up": Karakter yukarı veya aşağı gittiği için onu arkasından gördüğümüz “up” isimli animasyona geçer.$AnimatedSprite2D.flip_v = velocity.y > 0: Dikeydeki animasyonlarımızın ikisi de yukarı doğru yürüyecek şekilde çizilmiş halde. Eğer oyuncu aşağıya doğru gidiyorsa (velocity.y > 0şartı “aşağı” gidişi temsil eder vetruedöndürür) animasyonuflip_vile dikeyde takla attırarak ters (aşağı) bakmasını sağlar.
Bu kod sayesinde; karakter sağa veya sola giderken “walk” animasyonu çalışacak ve sola gidiyorsa flip_h ile yatayda ters çevrilecektir. Yukarı veya aşağı giderken ise “up” animasyonu çalışacak, aşağı gidiyorsa flip_v ile dikeyde ters dönecektir.
Bölüm Özeti
Harika bir iş çıkardınız! Bu bölümde;
- Dikey bir oyun için ekran ve ölçekleme ayarlarını yapılandırdınız.
Area2D,AnimatedSprite2DveCollisionShape2Dkullanarak kendi oyuncu sahnenizi inşa ettiniz.- Godot’nun Input Map sistemini kullanarak kontrolleri bağladınız.
- GDScript ile pürüzsüz bir 8 yönlü hareket kodu yazıp, ekrandan çıkmayı engelleyen matematiksel fonksiyonları (
normalized,clamp) kullandınız.
Konuyla ilgili Youtube videosu aşağıdadır…
Sıradaki Adım
Bir sonraki bölümde oyununuza asıl heyecanı katacak olan Düşman Yapay Zekası ve Spawner (Oluşturucu) sistemini kuracağız. Görüşmek üzere!