Orvix Engine
Oyun Geliştirme Rehberi: Sıfırdan Uzmanlığa
Hoş Geldiniz, Geleceğin Oyun Geliştiricisi!
Bu eşsiz rehber, Orvix Engine'in muazzam gücünü derinlemesine keşfetmen ve kendi dijital evrenlerini yaratmaya başlaman için tasarlandı. Sıfırdan bir fikirle başlayıp onu işlevsel, optimize edilmiş ve yayınlanmaya hazır bir oyuna dönüştürme yolculuğunda, seni adım adım ileri taşıyacağız. Her bir bölüm, temel prensiplerden en ileri seviye tekniklere kadar uzanan kapsamlı bir bilgi akışı sunuyor. Kemerini bağla, çünkü oyun geliştirme sanatının zirvesine çıkmaya hazırlanıyorsun!
Bu İleri Düzey Eğitimde Neler Öğreneceksin?
Orvix Engine'in karmaşık dünyasını basitleştirerek, seni gerçek bir oyun geliştirme uzmanı yapacak şu anahtar konulara odaklanacağız:
- Temel Modüler Yapılandırma: Node ve Scene'lerin derinlemesine anlaşılması, sahne ağacı optimizasyonu ve oyun objelerinin hiyerarşik yönetimi.
- GDScript'in İleri Düzey Kullanımı: GDScript'in tüm potansiyelini keşfetme, sinyal/slot mekanizmasının gücü, custom sinyaller ve daha fazlası.
- Dinamik Dünya Tasarımı: TileMap ile katmanlı ve performanslı seviye oluşturma, 3D dünyalar için temeller ve kamera sistemlerinin incelikleri.
- Görsel ve İşitsel Şaheserler: Parçacık efektlerinin sanatı, sofistike ses yönetimi ve arayüz (GUI) tasarımının incelikleri.
- Optimizasyon ve Yayınlama Sanatı: Oyununuzu son kullanıcıya ulaştırmadan önce performansı zirveye taşıma, hata ayıklama stratejileri ve çoklu platforma yayınlama süreçleri.
- Gelişmiş AI ve Oyun Mekanikleri: Karmaşık yapay zeka davranışları, durum makineleri ve oyun içi fizik etkileşimlerinin derinlemesine analizi.
- Shader Programlama: GLSL (OpenGL Shading Language) ile özel görsel efektler ve materyal manipülasyonları oluşturma.
Bölüm 1: Oyun Geliştirmeye Başlangıç | Temel Kavramlara Derin Dalış
Oyun geliştirme maceranıza hoş geldiniz! Orvix Engine, Düğümler (Nodes) ve Sahneler (Scenes) etrafında dönen modüler bir mimariye sahiptir. Bu bölüm, bu temel yapı taşlarını ve editör arayüzünü derinlemesine anlamanızı sağlayacak.
1.1 Proje Yönetimi ve Yapılandırma Stratejileri
Orvix Engine'i ilk başlattığınızda, sizi güçlü bir Proje Yöneticisi karşılar. Burası, tüm oyun projelerinizin merkezi komuta odasıdır. Projelerinizi verimli bir şekilde düzenlemek, farklı versiyonlar arasında geçiş yapmak ve yeni fikirler için alan açmak için Proje Yöneticisi'ni ustaca kullanmak, geliştirme sürecinizin temelini oluşturur.
Yeni Bir Proje Oluşturma: İlk Adımınız
Proje Yöneticisi'ndeki parlak "Oluştur Yeni Proje" (Create New Project) butonuna tıklayarak yeni bir maceraya atılabilirsiniz. Bu aşamada, projenize sadece akılda kalıcı bir isim vermekle kalmayacak, aynı zamanda tüm oyun varlıklarınızın, kod dosyalarınızın ve sahne tanımlarınızın güvenle saklanacağı stratejik bir disk konumu seçmelisiniz. Projenin adını belirlerken, gelecekteki genişlemeleri ve olası modüler yapıları düşünerek kısa, açıklayıcı ve benzersiz bir isim seçmek akıllıca olacaktır.
Orvix Proje Dosya Yapısı: Bir Mimarın Gözünden
Her Orvix projesi, titizlikle organize edilmiş, mantıksal bir dosya yapısına sahiptir. Bu yapı, hem küçük prototipler hem de milyonlarca satır kodu barındıran devasa AAA oyunları için ölçeklenebilirliği sağlar. En kritik ve sıkça karşılaşacağınız dosya türleri şunlardır:
- `.tscn` (Sahne Dosyaları): Bunlar, oyun dünyanızın ve içindeki tüm interaktif objelerinizin (düğümlerin) hiyerarşik yapısını, pozisyonlarını, ayarlarını ve ilişkilerini içeren omurgalardır. Her seviye, her karakter, her menü kendi `.tscn` dosyasında bir sahne olarak kaydedilir. Bu, oyunun modülerliğini sağlar.
- `.ovx` (OrvixScript Kod Dosyaları): Oyununuzun kalbi ve beyni! GDScript'e benzeyen, Orvix Engine'e özel bu güçlü betik dili, oyununuzun tüm mantığını, karakter davranışlarını, düşman yapay zekasını, kullanıcı etkileşimlerini ve özel mekaniklerini bu `.ovx` uzantılı dosyalarda barındırır. Okunabilirliği ve esnekliği sayesinde hızlı prototipleme ve karmaşık sistem geliştirme için idealdir.
- `project.orvix` (Proje Konfigürasyon Dosyası): Oyun motorunun projenizi tanımasını sağlayan, tüm global ayarların (başlangıç sahnesi, giriş haritaları, fizik katmanları, otomatik yüklemeler vb.) saklandığı ana konfigürasyon dosyasıdır. Bu dosyayı düzenlerken dikkatli olmalısınız.
- Görsel Varlıklar (`.png`, `.jpg`, `.tga`): Karakterler, arka planlar, arayüz elementleri, efektler... Oyununuzun görsel kimliğini oluşturan tüm dokular ve Spriteler.
- Ses Varlıkları (`.ogg`, `.wav`, `.mp3`): Oyun müziği, ses efektleri, diyaloglar... Oyunun işitsel atmosferini zenginleştiren tüm ses dosyaları.
1.2 Oyun Dünyasının Temel Bileşenleri: Düğümler (Nodes) ve Sahneler (Scenes)
Orvix Engine'in temel felsefesi, her şeyin küçük, yeniden kullanılabilir ve hiyerarşik nesneler etrafında dönmesidir. Bu nesneleri "Düğüm" (Node), bu düğümlerin mantıksal olarak bir araya gelmiş halini ise "Sahne" (Scene) olarak adlandırırız. Bu yapı, oyununuzun karmaşıklığını yönetmek için inanılmaz bir esneklik sunar.
Düğüm (Node) Nedir? Detaylı Bakış
Düğüm, Orvix Engine'deki en küçük, atomik yapı taşıdır. Ancak bu basit tanım, onun ne kadar güçlü olduğunu tam olarak yansıtmaz. Bir düğüm, oyununuzdaki belirli bir görevi veya işlevi yerine getiren herhangi bir objedir. Örneğin:
- Bir `Camera2D` düğümü, oyunun görsel penceresini kontrol eder.
- Bir `PointLight2D` düğümü, oyun dünyasına ışık saçar.
- Bir `Sprite2D` düğümü, ekranda bir 2D görseli (karakter, arka plan elemanı vb.) gösterir.
- Bir `AudioStreamPlayer2D` düğümü, oyun içi sesleri veya müziği çalar.
- Bir `CharacterBody2D` düğümü, hareket eden bir karakterin fiziksel davranışını yönetir.
Her düğüm, kendi benzersiz özellik setine (konum, rotasyon, boyut, renk vb.) ve kendi özel davranışlarını tanımlayabileceğiniz bir betiğe (`.ovx` dosyası) sahip olabilir. Düğümler, birbiriyle ilişkili bir "ağaç" yapısında düzenlenir. Bir düğümün altına başka düğümler ekleyerek hiyerarşiler oluşturursunuz. Örneğin, bir karakter düğümünün altına bir kamera düğümü eklediğinizde, kamera karakterle birlikte hareket eder.
Sahne (Scene) Nedir? Modüler Geliştirmenin Kalbi
Bir sahne, bir veya daha fazla düğümün mantıksal olarak bir araya getirilmiş, hiyerarşik bir koleksiyonudur. Bir sahne, oyununuzun belirli bir "parçasını" temsil eder:
- Oyunun bir seviyesi (level) bir sahne olabilir.
- Ana oynanabilir karakteriniz bir sahne olabilir.
- Bir düşman tipi bir sahne olabilir.
- Oyunun ana menüsü veya ayarlar ekranı bir sahne olabilir.
Sahnelerin gücü, onların "yeniden kullanılabilir" olmasında yatar. Bir karakter sahnesi tasarladınız ve test ettiniz. Şimdi bu karakteri oyununuzun farklı seviyelerine veya birden fazla düşman olarak farklı sahnelerde kolayca örnekleyerek ekleyebilirsiniz. Bu modüler yapı, kod tekrarını azaltır, hata ayıklamayı kolaylaştırır ve büyük oyunları daha yönetilebilir hale getirir.
1.3 Editör Arayüzü ve 2D/3D Görünüm Alanı (Viewport)
Orvix Engine'in sezgisel editörü, oyununuzu görsel olarak inşa etmeniz ve test etmeniz için tasarlanmış, güçlü bir iş istasyonudur. Editörü açtığınızda, oyununuzun kalbi olan Görünüm Alanı (Viewport) ile karşılaşırsınız.
2D Görünüm Alanı (Canvas): Piksel Sanatçısının Tuvali
Özellikle 2D oyun geliştirme modunda çalışırken, bu alana "Canvas" (Tuval) denir. Canvas, oyunun tüm 2D objelerinin yerleştirildiği, sınırsız ve esnek bir çalışma alanı gibidir. Karakterlerinizi, dinamik arka planlarınızı, etkileşimli nesnelerinizi ve kullanıcı arayüzü elementlerinizi bu tuval üzerine sürükleyip bırakarak oyun dünyanızı titizlikle görsel olarak oluşturursunuz. Burada, piksel hassasiyetinde konumlandırma ve ölçekleme yaparak oyununuzun estetiğini mükemmelleştirebilirsiniz.
3D Görünüm Alanı (Spatial View): Sanal Gerçekliğin Mimarisi
3D oyun geliştirme modunda ise, Görünüm Alanı "Spatial View" (Uzamsal Görünüm) olarak işlev görür. Burada, objeleri üç boyutlu uzayda konumlandırır, ışık kaynaklarını yerleştirir, kameraları ayarlar ve oyun dünyanızın derinliğini inşa edersiniz. 3D Viewport, gerçek zamanlı gölgeler, yansımalar ve post-processing efektleriyle oyununuzun nasıl görüneceğini anında gösterir.
Kilit Paneller: İş Akışınızın Anahtarları
Orvix Editör'ü, verimli bir iş akışı için tasarlanmış bir dizi hayati panelle çevrilidir:
- İnceleyici (Inspector) Paneli: Editörün genellikle sağ üst köşesinde konumlanır. Sahne ağacında seçtiğiniz herhangi bir düğümün tüm ayarlarını, özelliklerini (pozisyon, rotasyon, boyut vb.) ve betiğe bağlı özel değişkenlerini buradan anlık olarak değiştirebilirsiniz. Bu, objelerinizi ince ayar yapmak ve davranışlarını özelleştirmek için vazgeçilmez bir araçtır.
- Dosya Sistemi (FileSystem) Paneli: Genellikle sol altta yer alır. Projenizin tüm varlıklarını (görseller, ses dosyaları, fontlar, 3D modeller, scriptler vb.) yönettiğiniz merkezi bir depolama alanıdır. Varlıkları içe aktarabilir, klasörler halinde düzenleyebilir ve sahnelerinize sürükleyerek kolayca kullanabilirsiniz.
- Sahne (Scene) Paneli: Editörün sol üstünde bulunur. Açık olan sahnenin düğüm hiyerarşisini gösterir. Düğümleri ekleyebilir, silebilir, yeniden adlandırabilir ve ebeveyn-çocuk ilişkilerini bu panel üzerinden düzenleyebilirsiniz. Oyununuzun yapısını görsel olarak buradan takip edersiniz.
- Çıktı (Output) Paneli: Genellikle alt kısımda yer alır. Oyun çalışırken `print()` komutlarıyla gönderdiğiniz mesajları, hata ayıklama bilgilerini ve uyarıları gösterir. Hata ayıklama sürecinde vazgeçilmezdir.
1.4 İlk Oyununu Yarat: Klavyeyle Hareket Eden Bir Karakter
Şimdiye kadar öğrendiğimiz tüm temel bilgileri bir araya getirerek, klavye girdileriyle kontrol edebileceğiniz, etkileşimli bir karakter oluşturalım. Bu basit proje, Orvix Engine'deki oyun geliştirme döngüsünün ilk pratik uygulaması olacak.
Adım 1: Oyuncu Karakteri Sahnesini Oluşturma (Modüler Yaklaşım)
Yeni bir sahne başlatın ve kök düğüm olarak `CharacterBody2D` (2D oyunlar için fiziksel karakterler) ekleyin. Bu düğüm, fizik motorunun algılamasını ve çarpışmalarını yönetmek için temeldir. Düğümün adını "Oyuncu" olarak değiştirin ve bu sahneyi `Oyuncu.tscn` adıyla projenizin `res://oyuncular/` klasörüne (eğer yoksa oluşturun) kaydedin.
- `Sprite2D` Ekleme: "Oyuncu" düğümünün altına bir `Sprite2D` düğümü ekleyin. Bu düğüm, karakterinizin görsel temsilini sağlar. İnceleyici panelinde, `Texture` (Doku) özelliğine karakterinize ait bir görsel (örneğin bir `player.png` dosyası) sürükleyip bırakarak karakterinizin ekranda görünmesini sağlayın.
- `CollisionShape2D` Ekleme: `Sprite2D` düğümünün altına bir `CollisionShape2D` düğümü ekleyin. Bu düğüm, karakterinizin fiziksel çarpışma alanını tanımlar. İnceleyici panelinden, `Shape` (Şekil) özelliğine bir `RectangleShape2D` (kutu şekli) veya `CapsuleShape2D` (kapsül şekli) atayın ve boyutunu karakter görselinize uyacak şekilde ayarlayın. Bu, karakterinizin oyun dünyasındaki fiziksel etkileşimlerini sağlar.
Adım 2: GDScript ile Karakter Hareketi Programlama (GDScript'in İlk Temelleri)
"Oyuncu" düğümüne sağ tıklayarak veya düğümü seçip üst menüden "Attach Script" (Betiği Bağla) seçeneğiyle yeni bir GDScript dosyası (`Oyuncu.ovx`) oluşturun ve aşağıdaki kodu içine yazın. Bu kod, klavye yön tuşlarından gelen girdiyi okuyacak ve `CharacterBody2D`'nin `velocity` (hız) özelliğini kullanarak karakteri fizik motoruyla hareket ettirecektir.
# Oyuncu.cs - Bu script, bir CharacterBody2D düğümüne eklendi.
extends CharacterBody2D
# Karakterin hareket hızını bir değişken olarak tanımlıyoruz.
# '@export' anahtar kelimesi, bu değişkeni İnceleyici panelinde düzenlenebilir yapar.
@export var hiz = 250.0 # Piksel/saniye cinsinden hız
# '_physics_process' fizik motoru tarafından kare başına sabit bir zamanda çağrılır.
# Bu, tutarlı fizik hareketleri için önemlidir.
func _physics_process(delta: float):
# Klavyeden yön girdisini alalım.
# 'Vector2.ZERO' boş bir 2D vektördür (0,0).
var yon_girisi = Vector2.ZERO
# Her bir yön tuşu için girdiyi kontrol et.
# 'ui_right', 'ui_left', 'ui_down', 'ui_up' varsayılan giriş eylemleridir.
if Input.is_action_pressed("ui_right"):
yon_girisi.x += 1.0
if Input.is_action_pressed("ui_left"):
yon_girisi.x -= 1.0
if Input.is_action_pressed("ui_down"):
yon_girisi.y += 1.0
if Input.is_action_pressed("ui_up"):
yon_girisi.y -= 1.0
# Yön girdisi normalize edilir (büyüklüğü 1 olur) ve hız ile çarpılır.
# Bu, çapraz hareketlerin daha hızlı olmamasını sağlar.
# 'velocity' CharacterBody2D'nin dahili bir değişkenidir.
velocity = yon_girisi.normalized() * hiz
# Karakteri fizik motoruyla hareket ettir ve çarpışmaları algıla.
# 'move_and_slide()' yöntemi, karakteri hızına göre hareket ettirir
# ve yüzeyler boyunca kaydırır.
move_and_slide()
Adım 3: Oyunu Oynatma ve İlk Zaferin!
Yeni bir ana sahne oluşturun (örneğin `MainGame.tscn`). Bu sahne, oyununuzun genel çerçevesini oluşturacaktır. `Oyuncu.tscn` sahnesini, Dosya Sistemi panelinden sürükleyip ana sahnenizin Sahne paneline bırakarak "Oyuncu" karakterinizi ana oyuna ekleyin. Şimdi, editörün üst kısmındaki "Oynat" (Play) butonuna basarak veya `F5` tuşuna basarak oyununuzu çalıştırın. Klavyenizdeki yön tuşlarını kullanarak karakterinizi Canvas üzerinde sorunsuz bir şekilde hareket ettirebileceksiniz. Tebrikler! Oyun geliştirme yolculuğunuzda ilk büyük adımı attın ve kendi ilk etkileşimli oyun mekaniğini tamamladın!
Bölüm 2: Dinamik Etkileşimler | Sinyallerin Gücü ve Kullanıcı Arayüzü
Oyunlar sadece hareketli görsellerden ibaret değildir; aynı zamanda etkileşimlerden ibarettir. Orvix Engine'in temelinde yatan **Sinyal (Signal) Sistemi** ve **Kullanıcı Arayüzü (GUI)** mimarisi, oyun dünyanızdaki dinamik tepkileri ve oyuncu etkileşimlerini yönetmenizi sağlar. Bu bölümde, bu güçlü mekanizmaları nasıl kullanacağınızı detaylıca inceleyeceğiz.
2.1 Çarpışma Sinyalleri ile Gelişmiş Etkileşimler
Sinyaller, Orvix'teki düğümler arası iletişimin omurgasıdır. Bir düğüm belirli bir olay gerçekleştirdiğinde bir sinyal yayar, diğer düğümler ise bu sinyali dinleyerek (bağlayarak) o olaya göre tepki verir. Bu, kodu daha temiz, daha modüler ve daha az bağımlı hale getirir. En yaygın sinyallerden biri, fiziksel çarpışmalardan tetiklenen sinyallerdir.
Adım 1: "Para" Toplanabilir Nesnesini Oluşturma Sahnesi
Yeni bir sahne başlatın ve kök düğüm olarak `Area2D` ekleyin. `Area2D` düğümü, fiziksel kurallara göre hareket etmeyen, ancak diğer fiziksel nesnelerle çarpışmaları (veya onlara giriş/çıkışları) algılayabilen alanlar oluşturmak için idealdir. Bu düğüme "Para" adını verin ve sahneyi `Para.tscn` olarak `res://varliklar/` klasörüne (oluşturun) kaydedin.
- `Sprite2D` Ekleme: "Para" düğümünün altına bir `Sprite2D` düğümü ekleyin ve İnceleyici panelinde `Texture` (Doku) özelliğine bir para görseli (`coin.png`) atayın.
- `CollisionShape2D` Ekleme: `Sprite2D` altına bir `CollisionShape2D` düğümü ekleyin ve para görselinizin boyutuna uygun bir şekil (örneğin `CircleShape2D` veya `RectangleShape2D`) atayarak paraya bir çarpışma alanı tanımlayın. Bu alan, başka bir fiziksel nesne bu alana girdiğinde `Area2D`'nin sinyal yaymasını sağlayacaktır.
Adım 2: Para Sinyali ve GDScript Kod Mantığı
"Para" düğümüne bir GDScript (`Para.ovx`) ekleyin. Bu script, bir oyuncuyla çarpıştığında özel bir sinyal yayacak ve ardından kendini sahneden kaldırarak "toplandı" efektini verecektir. Bu, nesne tabanlı programlamanın ve sinyal/slot mekaniğinin güzel bir örneğidir.
# Para.ovx - Bu script, bir Area2D düğümüne eklendi.
extends Area2D
# "para_alindi" adında, 'puan' adında bir argüman taşıyan özel bir sinyal tanımla.
signal para_alindi(puan: int)
# '_on_body_entered' fonksiyonu, bu Area2D'ye fiziksel bir 'body' (CharacterBody2D veya RigidBody2D gibi)
# girdiğinde otomatik olarak çağrılır. Editörden sinyali bağlayarak oluşturulabilir.
func _on_body_entered(body: Node2D):
# Çarpışan nesnenin 'Oyuncu' karakterimiz olup olmadığını kontrol ediyoruz.
# 'body.name' yerine gruplar kullanmak daha sağlam bir yöntemdir.
if body.name == "Oyuncu":
# "para_alindi" sinyalini yayıyoruz ve 100 puan değerini argüman olarak gönderiyoruz.
# Bu sinyali dinleyen tüm düğümler bu olayı alacaktır.
emit_signal("para_alindi", 100)
# Parayı sahneden güvenli bir şekilde sil (sonraki fizik adımında silinir).
queue_free()
Bu kodu yazdıktan sonra, editörde "Para" düğümünü seçin. Sağdaki **"Düğüm"** panelini (Inspector'ın yanında) açın, `Area2D` altındaki "body_entered" sinyaline çift tıklayın. Açılan pencerede, script'inizin bağlı olduğu düğümü (Para) ve metodu seçerek `_on_body_entered` fonksiyonunu otomatik olarak oluşturabilir ve sinyali bağlayabilirsiniz.
Adım 3: Oyuncu Scriptinde Sinyali Dinleme ve Puan Entegrasyonu
Ana sahnede (veya `Oyuncu.tscn` içindeki "Oyuncu" düğümüne bağlı olan) `Oyuncu.ovx` script'inizi açın. Şimdi, "para_alindi" sinyalini dinlemek ve toplanan paralarla oyuncunun puanını güncellemek için aşağıdaki kodu script'inize ekleyin. Ayrıca, bu puanı oyun boyunca erişilebilir kılmak için global bir "OyunYönetimi" (Globals) singleton'ı kullanacağız.
# Oyuncu.ovx - Oyuncu karakterinin script'ine eklenir.
extends CharacterBody2D
# ... (Önceki hareket kodu burada kalır) ...
# '_ready' fonksiyonu düğüm sahne ağacına girdiğinde bir kez çağrılır.
func _ready():
# 'Para' sahnelerinin nerede olduğunu varsayıyoruz (örneğin ana sahnede örneklenmişlerse).
# Tüm 'Para' düğümlerini bulup onların 'para_alindi' sinyallerini bu oyuncuya bağlıyoruz.
# Alternatif olarak, 'Para' düğümü oluşturulduğunda bu bağlantıyı yapabilirsiniz.
# Bu, sinyalleri dinamik olarak bağlamanın bir yoludur.
get_tree().get_nodes_in_group("toplanabilir_objeler").for_each(
func(toplanabilir):
if toplanabilir is Area2D and toplanabilir.has_signal("para_alindi"):
toplanabilir.para_alindi.connect(_on_Para_para_alindi)
)
# Önemli: 'Para' düğümlerinizi editörde bir gruba eklemeyi unutmayın (örn. "toplanabilir_objeler")!
# 'Para' düğümünün 'para_alindi' sinyali yayıldığında bu fonksiyon çağrılır.
func _on_Para_para_alindi(puan: int):
# Global singleton'daki puanı güncelleyin.
GlobalGameManager.artir_puan(puan) # GlobalGameManager, Project Settings -> AutoLoad'a eklenmeli.
print("Toplanan Puan: ", GlobalGameManager.puan)
# Oyuncuya ses veya görsel geribildirim ekleyebilirsiniz.
Bu kodla, oyuncu bir parayla çarpıştığında, para kendini yok edecek ve `GlobalGameManager` adlı global bir singleton'daki (projenizin herhangi bir yerinden erişilebilir) `puan` değişkenini güncelleyecektir. Konsolda puanınızın arttığını göreceksiniz. Bu, sinyal sisteminin temel gücüdür!
2.2 Kullanıcı Arayüzü (GUI) ve Akış Yönetimi
Oyunun menüleri, skoru, envanteri, diyalog kutuları ve diğer tüm etkileşimli elemanları kullanıcı arayüzü (GUI) ile oluşturulur. Orvix Engine, bu amaçla özel **Kontrol (Control)** düğümleri ve düzenleyiciler sunar. GUI, oyunun çekirdek mekaniklerinden ayrı bir katmanda çalışarak esneklik ve performans sağlar.
Adım 1: Basit Bir Başlangıç Menüsü Sahnesini Oluşturma
Yeni bir sahne başlatın ve kök düğüm olarak bir `Control` düğümü ekleyin. Bu, tüm UI elementleri için temel bir kapsayıcıdır. Bu sahneyi `MainMenu.tscn` olarak `res://ui/` klasörüne kaydedin. Ardından, bu `Control` düğümünün altına bir `CanvasLayer` düğümü ekleyin. `CanvasLayer`, GUI elemanlarının her zaman 2D veya 3D oyun dünyasının üzerinde, kendi bağımsız render katmanında çizilmesini sağlar, bu da ölçekleme ve görünürlük sorunlarını önler. `CanvasLayer`'ın altına sırasıyla şu UI düğümlerini ekleyin:
- `Panel` veya `ColorRect`: Menü için basit bir arka plan oluşturur. İnceleyici panelinden rengini ve boyutunu ayarlayabilirsiniz. Genellikle ekranı kaplaması için `Layout -> Full Rect` seçeneği kullanılır.
- `Label`: Menü başlık metnini (örneğin "Orvix Macerası" veya "Oyun Adınız") gösterir. Fontunu, boyutunu, rengini ve hizalamasını İnceleyici'den özelleştirebilirsiniz.
- `Button`: Oyunu başlatmak için bir "Başla" veya "Oyna" butonu oluşturur. Butonun metnini ve görsel stilini (normal, hover, basılı durum) `Theme` kaynakları ile detaylıca özelleştirebilirsiniz.
- (İsteğe Bağlı) `OptionButton` / `CheckButton`: Oyun ayarları veya seçenekleri için karmaşık arayüz elemanları ekleyebilirsiniz.
Bu düğümleri Canvas'ın (2D Viewport) tam ortasına yerleştirmek için, kapsayıcı `Control` düğümünün `Layout` özelliğini `Center Container` veya ilgili `Anchor` ve `Margin` ayarlarını kullanabilirsiniz.
Adım 2: Butona İşlev Kazandırma ve Sahne Geçişleri
Butonun "pressed" sinyaline tıklayarak (Düğüm panelinden veya scriptten bağlayarak), butona basıldığında çalışacak bir fonksiyon oluşturun. Bu fonksiyonu kullanarak oyun akışını ana oyun sahnesine geçirebiliriz. Sahne geçişleri, oyunun farklı bölümleri arasında sorunsuz bir deneyim sunmak için kritik öneme sahiptir.
# MainMenu.ovx - Bu script, ana menü sahnesindeki ana Control düğümüne eklendi.
extends Control
# `@onready` ile düğümlere daha güvenli referanslar alınır.
# '$' işareti, Sahne ağacında bir düğüm yolu anlamına gelir.
@onready var basla_butonu = $"VBoxContainer/BaslaButonu" # Butonunuzun Sahne yolunu doğru ayarlayın.
# '_ready' fonksiyonu, düğüm sahne ağacına girdiğinde bir kez çağrılır.
func _ready():
# Butonun 'pressed' sinyalini bu scriptteki bir fonksiyona bağlıyoruz.
basla_butonu.pressed.connect(_on_BaslaButonu_pressed)
# '_on_BaslaButonu_pressed' fonksiyonu, "Başla" butonuna basıldığında tetiklenir.
func _on_BaslaButonu_pressed():
print("Oyun başlatılıyor! Ana Oyun Sahnesi'ne geçiliyor...")
# 'get_tree().change_scene_to_file()' ile mevcut sahneyi değiştiriyoruz.
# 'res://' prefix'i projenin kök dizinini ifade eder.
get_tree().change_scene_to_file("res://AnaOyunSahnesi.tscn")
Bu kodla, "Başla" butonuna tıklandığında oyunun akışı "AnaOyunSahnesi" adlı sahneye sorunsuz bir şekilde geçiş yapacaktır. Bu, bir ana menüden oyuna veya bir seviyeden diğerine geçiş yapmanın en temel ve yaygın yoludur. Gelecekte, sahne geçişlerine animasyonlar veya yükleme ekranları da ekleyebilirsiniz.
2.3 Giriş Haritalaması ve Dinamik Kontroller
Oyuncu girdileri (klavye, fare, gamepad) oyununuzla etkileşimin temelidir. Orvix Engine'in **Giriş Haritalaması (Input Map)** sistemi, bu girdileri daha soyut ve yönetilebilir "Aksiyonlar"a dönüştürmenizi sağlar. Bu, farklı cihazlar için kontrol şemalarını kolayca özelleştirebileceğiniz anlamına gelir.
Giriş Haritalaması Kurulumu
Orvix Editör'de: **Proje > Proje Ayarları > Giriş Haritası (Input Map)** sekmesine gidin. Burada yeni aksiyonlar (örneğin "ates_et", "zipla", "envanter_ac") tanımlayabilir ve bu aksiyonlara farklı tuşları veya fare düğmelerini atayabilirsiniz. Örneğin, "ates_et" aksiyonuna hem fare sol tuşunu hem de klavyeden `Space` tuşunu atayabilirsiniz. Bu, kontrol esnekliği sağlar.
Girdiyi Kodda Kullanma
Oyun içinde bu aksiyonları kontrol etmek için `Input` singleton'ını kullanırsınız. Önceki `Oyuncu.ovx` script'imizdeki hareket kontrolünü bu sisteme uyarlayabiliriz:
# Oyuncu.ovx - Geliştirilmiş Giriş Yönetimi
extends CharacterBody2D
@export var hiz = 250.0
func _physics_process(delta: float):
var yon_girisi = Vector2.ZERO
# Giriş eylemlerini kullanarak daha temiz ve esnek kod.
# Kullanıcı bu aksiyonlara dilediği tuşu atayabilir.
if Input.is_action_pressed("move_right"): # "move_right" gibi yeni aksiyonlar tanımlayın.
yon_girisi.x += 1.0
if Input.is_action_pressed("move_left"):
yon_girisi.x -= 1.0
if Input.is_action_pressed("move_down"):
yon_girisi.y += 1.0
if Input.is_action_pressed("move_up"):
yon_girisi.y -= 1.0
velocity = yon_girisi.normalized() * hiz
move_and_slide()
# Bir aksiyonun yalnızca bir kez basılmasını kontrol etme (örneğin zıplama veya ateş etme)
if Input.is_action_just_pressed("ates_et"): # "ates_et" aksiyonu tanımlanmış olmalı
print("Ateş edildi!")
# Mermi oluşturma fonksiyonunu burada çağırabilirsiniz.
Bu yöntem, oyuncuların kendi kontrol şemalarını özelleştirmelerine olanak tanır ve gelecekte farklı platformlara (gamepad gibi) uyum sağlamayı kolaylaştırır.
Bölüm 3: Oyununu Geliştir | Seviye Tasarımı, Kamera ve Temel Yapay Zeka
Oyunun temel etkileşimlerini sinyaller ve GUI ile kurduktan sonra, sıra oyun dünyasını inşa etmeye geliyor. Bu bölümde, hızlı ve verimli seviye tasarımı için **TileMap** düğümünü, oyuncu hareketini takip eden bir **Kamera** sistemini ve oyununuza meydan okuma ekleyecek basit bir **Düşman Yapay Zekası** geliştirmeyi öğreneceksin.
3.1 Hızlı Seviye Oluşturma: TileMap (Döşeme Haritası)
TileMap, 2D oyunlarda seviye tasarlamanın en güçlü, en hızlı ve en verimli yoludur. Tek tek Sprite'ları manuel olarak yerleştirmek yerine, önceden hazırlanmış bir **TileSet** (döşeme kümesi) kullanarak haritanı sanki bir ressamın fırçasıyla boyar gibi oluşturabilirsin. Bu, büyük ve karmaşık seviyeleri inanılmaz bir hızla inşa etmene olanak tanır.
Adım 1: TileMap Düğümünü Kurma ve TileSet Oluşturma
Ana oyun sahnene (`AnaOyunSahnesi.tscn`) bir `TileMap` düğümü ekle. Bu düğüm, tüm harita döşemelerini içerecektir. Ardından, İnceleyici panelinde (Inspector) `TileMap` düğümünü seçiliyken, `Tile Set` özelliğine tıklayarak yeni bir `TileSet` kaynağı oluştur. Bu `TileSet`'e, haritanı oluşturan tüm görsel dosyalarını (örneğin zemin, duvar, platform görselleri) sürükleyip bırakarak döşemelerini (Tiles) tanımlayabilirsin. Her bir döşeme için çarpışma şekillerini, yansımaları veya özel verileri de ayarlayabilirsin.
Adım 2: Seviyeyi Tasarlama: Sanal Bir Ressam Gibi
`TileMap` düğümünü seçtiğinde, editörün üst kısmında özel TileMap düzenleme araçları belirecektir. Buradan farklı fırça araçlarını (tekli fırça, dikdörtgen, çizgi vb.) seçerek veya kütüphanendeki döşemeleri tek tek seçerek oyun haritanı Canvas (2D Görünüm Alanı) üzerine özgürce çizebilirsin. Fiziksel objeler (duvarlar, zeminler) için `Collision` (Çarpışma) katmanlarını da bu aşamada tanımlayabilirsin, böylece karakterlerin bu objelerle doğru bir şekilde etkileşim kurar.
3.2 Dinamik Kamera Takibi ve Viewport Yönetimi
Oyun dünyası genellikle oyuncu karakterinin hareketine göre kaymalıdır, böylece oyuncu her zaman ekranın merkezinde kalır ve çevresini görebilir. Bunu sağlamak için `Camera2D` düğümünü kullanacağız. `Camera2D`, oyun dünyasının belirli bir kısmını "görüntüleyen" ve bu görüntüyü oyuncunun ekranına yansıtan bir objektif gibidir.
Adım 1: Kamera Düğümünü Ekleme ve İlişkilendirme
Ana sahnedeki "Oyuncu" düğümünün (veya takip etmek istediğin herhangi bir düğümün) altına bir `Camera2D` düğümü ekle. Bu, kameranın her zaman karakterle aynı konumda olmasını, yani karakteri otomatik olarak takip etmesini sağlayacaktır. Bu hiyerarşik ilişki, kamera kodunu yazma ihtiyacını ortadan kaldırır.
Adım 2: Kamera Ayarları ve Optimizasyonlar
`Camera2D` düğümünü seç ve İnceleyici panelinden **"Current"** (Aktif) özelliğini işaretle. Bu, Orvix Engine'e oyun başlarken bu kamerayı kullanmasını söyler. Ayrıca, kameranın davranışını özelleştirmek için birçok ayar bulunur:
- Limitler (Limit): Kameranın belirli bir alanın dışına çıkmasını engellemek için sol, sağ, üst ve alt limitleri ayarlayabilirsin. Bu, seviyenin kenarlarını gizlemek için kullanışlıdır.
- Zoom (Yakınlaştırma): Kameranın yakınlaştırma seviyesini (`Zoom` özelliği) değiştirerek farklı oyun anları için görsel dinamizm sağlayabilirsin.
- Sürtünme (Drag Margin): Karakterin hareket ettiği yönde kameranın ne kadar gecikmeli takip edeceğini belirleyebilirsin. Bu, daha yumuşak ve akıcı kamera hareketleri için önemlidir.
- Vibra (Vibration): Oyun içindeki olaylara (patlamalar, hasar alma) tepki olarak kamerayı titretebilirsin, bu da oyunun etkisini artırır.
3.3 Basit Bir Düşman Yapay Zekası: Oyuncu Takibi
Oyununa biraz daha meydan okuma ve dinamizm eklemek için, oyuncuyu takip eden basit bir düşman oluşturalım. Bu, oyununuzda temel bir yapay zeka davranışının nasıl programlanacağını anlamanızı sağlayacak.
Adım 1: Düşman Karakteri Sahnesini Oluşturma
Yeni bir sahne oluştur ve ana düğüm olarak `CharacterBody2D` ekle. Adını "Düşman" olarak değiştir ve bu sahneyi `Düşman.tscn` olarak `res://dusmanlar/` klasörüne (oluşturun) kaydet. Karakterin görseli ve çarpışma şekli için bir `Sprite2D` ve `CollisionShape2D` eklemeyi unutma, tıpkı oyuncu karakterinde yaptığın gibi.
Adım 2: Düşman Yapay Zekası Kodu: Oyuncu Peşinde!
"Düşman" düğümüne bir GDScript (`Düşman.ovx`) ekle ve aşağıdaki kodu yaz. Bu kod, düşmanın her fizik adımında oyuncunun konumunu tespit etmesini ve ona doğru hareket etmesini sağlar. Ayrıca, düşmanı bir "düşmanlar" grubuna ekleyerek daha sonra mermilerle veya diğer etkileşimlerle kolayca hedef alabileceğiz.
# Düşman.ovx - Bu script, bir CharacterBody2D düğümüne eklendi.
extends CharacterBody2D
@export var hiz = 120.0 # Düşmanın hareket hızı
var oyuncu: CharacterBody2D = null # Oyuncu düğümünü tutacak değişken (tip ipucu)
# _ready fonksiyonu, düğüm sahne ağacına girdiğinde bir kez çağrılır.
func _ready():
# Oyuncu düğümünü sahne ağacında "oyuncular" grubundan buluyoruz.
# Oyuncuyu sahneye eklediğinizde bu gruba eklemeyi unutmayın!
oyuncu = get_tree().get_first_node_in_group("oyuncular")
if oyuncu is null:
print("Hata: 'oyuncular' grubunda oyuncu bulunamadı!")
queue_free() # Oyuncu yoksa düşmanı sil
# _physics_process, fiziksel hesaplamalar için sabit aralıklarla çağrılır.
func _physics_process(delta: float):
if oyuncu:
# Oyuncunun global pozisyonunu al ve ona doğru bir yön vektörü oluştur.
# 'normalized()' vektörün büyüklüğünü 1 yapar, sadece yönü korur.
var yon = (oyuncu.global_position - global_position).normalized()
# Hız vektörünü ayarla (yön x hız).
velocity = yon * hiz
# Düşmanı hareket ettir ve çarpışmaları yönet.
move_and_slide()
else:
# Oyuncu yoksa veya henüz bulunamadıysa düşmanı durdur.
velocity = Vector2.ZERO
move_and_slide()
# Oyuncuyu düşman grubuna eklemeyi unutma: Oyuncu düğümünü seç > Inspector > Node tab > Groups > "oyuncular" grubunu ekle.
# Ayrıca, düşmanı da "düşmanlar" grubuna ekleyebilirsin.
Önemli Not: Bu kodun doğru çalışması için, ana sahnenize eklediğiniz "Oyuncu" düğümüne **"oyuncular"** adında bir grup atamanız gerekir. Bunu, "Oyuncu" düğümünü editörde seçip, İnceleyici panelindeki "Düğüm" (Node) sekmesine giderek "Gruplar" (Groups) bölümünden yapabilirsiniz. Aynı şekilde, "Düşman" düğümlerinizi de "düşmanlar" adında bir gruba eklemek, gelecekteki mermi isabetleri gibi etkileşimleri kolaylaştıracaktır.
Bölüm 4: Profesyonel Dokunuşlar | Silah Mekanikleri, Efektler ve Ses Yönetimi
Oyunun temel seviye tasarımını ve yapay zekayı öğrendikten sonra, sıra onu aksiyon ve duyusal geri bildirimlerle doldurmaya geldi. Bu rehber sayfasında, oyununu daha çekici ve dinamik hale getirmek için mermi sistemleri, etkileyici partikül efektleri ve sürükleyici bir ses yönetimi gibi önemli konuları ele alacağız.
4.1 Mermi Sistemi Oluşturma ve Çarpışma Yönetimi
Oyuncunun düşmanlara veya diğer etkileşimli nesnelere saldırmasını sağlamak, birçok oyun türünün en temel mekaniklerinden biridir. Orvix Engine'de güçlü ve esnek bir mermi sistemi oluşturmak oldukça basittir, çünkü fizik motoru ve sinyal sistemi bunu destekler.
Adım 1: "Mermi" Sahnesini Oluşturma (Yeniden Kullanılabilir Obje)
Yeni bir sahne başlatın ve kök düğüm olarak `RigidBody2D` ekleyin. `RigidBody2D` düğümü, fizik kurallarına (yerçekimi, kuvvetler vb.) göre hareket eden nesneler için idealdir, ancak mermilerde genellikle yerçekimini kapatırız. Adını "Mermi" olarak değiştirin ve sahneyi `Mermi.tscn` olarak `res://savunma/mermiler/` klasörüne (oluşturun) kaydedin.
- `Sprite2D` Ekleme: Merminizin görseli için (örneğin `bullet.png`) bir `Sprite2D` düğümü ekleyin. Merminin ucunun sağa baktığından emin olun, çünkü başlangıç yönünü `Vector2.RIGHT` olarak ayarlayacağız.
- `CollisionShape2D` Ekleme: Merminin çarpışma alanını tanımlayan bir şekil (örneğin `RectangleShape2D` veya `CapsuleShape2D`) atayın. Mermiye uygun küçük bir çarpışma alanı olmalı.
- `Area2D` Ekleme (İsteğe Bağlı ama Önerilir): Eğer merminin sadece hasar vermekle kalmayıp, belirli alanlara girdiğinde de sinyal yaymasını istiyorsanız (örneğin, bir patlayıcı mermi), merminin altına bir `Area2D` düğümü ekleyebilirsiniz.
Merminin `RigidBody2D` düğümünü seçiliyken, İnceleyici panelinde `Mode` özelliğini `Character` veya `Kinematic` yerine `Rigid` olarak bırakın, ancak `Gravity Scale` (Yerçekimi Ölçeği) değerini `0` olarak ayarlayın. Ayrıca, `Physics Material` (Fizik Materyali) ayarlarını kontrol edin ve `Friction` (Sürtünme) ile `Bounce` (Sekme) değerlerini `0` olarak ayarlayarak merminin düz bir çizgide hareket etmesini sağlayın.
Mermi Kodu: Ateşleme ve Hasar Mekaniği
"Mermi" düğümüne bir GDScript (`Mermi.ovx`) ekleyin. Bu kod, merminin bir kez oluşturulduğunda kendi başına hareket etmesini ve bir nesneye çarptığında (özellikle bir düşmana) ne olacağını belirler. Hasar verme ve kendini silme mekanizmalarını içerecektir.
# Mermi.ovx - Bu script, bir RigidBody2D düğümüne eklendi.
extends RigidBody2D
@export var hiz = 800.0 # Merminin hızı (piksel/saniye)
@export var hasar_miktari = 10 # Merminin verdiği hasar
@export var yasam_suresi = 3.0 # Merminin ne kadar süre sonra kendiliğinden silineceği (saniye)
# '_ready' fonksiyonu, düğüm sahne ağacına girdiğinde bir kez çağrılır.
func _ready():
# Mermiyi 'mermiler' grubuna ekleyin, böylece düşmanlar tarafından algılanabilir.
add_to_group("mermiler")
# Mermiye hareket yönünde (düğümün rotasyonu) bir başlangıç hızı ver.
# 'linear_velocity' bir RigidBody2D'nin dahili bir özelliğidir.
linear_velocity = Vector2.RIGHT.rotated(rotation) * hiz
# Merminin belirli bir süre sonra kendini yok etmesini sağlayan bir zamanlayıcı başlat.
var timer = get_tree().create_timer(yasam_suresi)
timer.timeout.connect(queue_free) # Zamanlayıcı bittiğinde mermiyi sil.
# '_on_body_entered' sinyali, mermi başka bir fiziksel nesneye çarptığında tetiklenir.
# Bu sinyali Editörden, Mermi düğümünün CollisionShape2D'sinden veya RigidBody2D'sinden bağlayabilirsiniz.
func _on_body_entered(body: Node):
# Çarpışılan nesnenin 'hasar_al' adında bir metodu olup olmadığını kontrol et.
# Bu, düşmanlar, kırılabilir objeler vb. için geçerli olacaktır.
if body.has_method("hasar_al"):
body.hasar_al(hasar_miktari) # Hasar ver.
# Çarptıktan sonra mermiyi sahneden sil.
queue_free()
# Editörde mermi düğümünü seçin ve RigidBody2D panelindeki 'body_entered' sinyalini script'e bağlayın.
# Eğer Area2D eklediyseniz, Area2D'nin 'body_entered' veya 'area_entered' sinyallerini de kullanabilirsiniz.
Önemli Notlar:
- Mermi, başlangıçta döndüğü yöne doğru hareket edecektir. Oyuncu scriptinde mermi oluştururken `mermi_örneği.rotation = global_rotation` yaparak oyuncunun baktığı yöne doğru ateş etmesini sağlayabilirsiniz.
- Düşman karakterinizin scriptinde `hasar_al(miktari: int)` adında bir metod oluşturmanız gerekmektedir, böylece mermiden hasar alabilir.
Oyuncu Scriptinde Mermi Ateşleme Fonksiyonu
Şimdi, `Oyuncu.ovx` script'inize geri dönün ve oyuncunun bir tuşa bastığında (örneğin "ates_et" aksiyonu) mermi oluşturup fırlatmasını sağlayan kodu ekleyin. Bu, dinamik sahne oluşturma ve örnekleme kavramını da içerir.
# Oyuncu.ovx - Mermi ateşleme özelliği eklendi
extends CharacterBody2D
# ... (Önceki hareket ve puanlama kodu burada kalır) ...
# Mermi sahnesinin ön yüklemesi (pre-load). Bu, mermiyi hafızaya alır ve hızlıca örneklemeyi sağlar.
const MermiSahnesi = preload("res://savunma/mermiler/Mermi.tscn") # Kendi mermi sahnenizin yolunu girin!
# Merminin ortaya çıkacağı konum (örneğin, silahın ucu).
# Editörde Oyuncu düğümünün altına bir Marker2D düğümü ekleyip adını "MermiCikisNoktasi" yapın.
@onready var mermi_cikis_noktasi = $"MermiCikisNoktasi"
func _physics_process(delta: float):
# ... (Hareket kodu) ...
# "ates_et" aksiyonuna basıldığında mermi ateşle.
if Input.is_action_just_pressed("ates_et"):
ates_et()
# 'ates_et' fonksiyonu, bir mermi örneği oluşturur ve onu sahneye ekler.
func ates_et():
# Mermi sahnesinden yeni bir örnek oluştur.
var yeni_mermi = MermiSahnesi.instantiate()
# Merminin global pozisyonunu ve rotasyonunu oyuncunun mermi çıkış noktasına ayarla.
yeni_mermi.global_position = mermi_cikis_noktasi.global_position
yeni_mermi.rotation = global_rotation # Oyuncunun baktığı yöne doğru ateş etmesini sağlar.
# Mermiyi ana sahnenin bir çocuğuna ekle (örn. get_parent() veya get_tree().current_scene).
get_parent().add_child(yeni_mermi)
# Oyunun ana Node'una eklemek daha iyi bir yöntem olabilir:
# get_tree().get_current_scene().add_child(yeni_mermi)
Bu kodla, `ates_et` aksiyonuna basıldığında, oyuncunun konumunda yeni bir mermi oluşacak ve ateşleme sesini çalacak (eğer eklediysen). Bu, dinamik olarak nesne oluşturmanın ve sahne ağacına eklemenin temel yoludur.
4.2 Görsel Şölen: Partikül Sistemleri (CPUParticles2D / GPUParticles2D)
Görsel efektler (FX), oyunun canlı, tepkisel ve sürükleyici hissetmesini sağlayan en önemli unsurlardan biridir. Bir patlama, duman bulutu, karakterin ayak izi tozu veya sihirli parıltılar gibi efektler için Orvix Engine'in güçlü **Partikül Sistemlerini** kullanacağız. 2D için `CPUParticles2D` (CPU tabanlı, daha basit) veya `GPUParticles2D` (GPU tabanlı, daha performanslı ve karmaşık efektler için) düğümlerini kullanabiliriz.
Adım 1: Partikül Efekti Düğümünü Ekleme ve Temel Ayarlar
Merminin çarpışma noktasında bir patlama efekti veya oyuncunun ateş ettiğinde namludan çıkan duman efekti yaratmak için, ilgili sahnelerinize (örneğin "Mermi" sahnesine veya "Oyuncu" sahnesindeki mermi çıkış noktasına) bir `CPUParticles2D` düğümü ekle. Ardından, İnceleyici panelinde, partikül sisteminin özelliklerini kapsamlı bir şekilde özelleştirebilirsin:
- `Amount` (Miktar): Aynı anda ekranda bulunacak partikül sayısı. Performans ve görsel kalite arasında denge kurmak önemlidir.
- `Texture` (Doku): Partiküllerin görseli (örneğin küçük bir parıltı, duman resmi).
- `Emission Shape` (Yayılım Şekli): Partiküllerin hangi şekilden (örneğin, daire, küre, kutu, tek nokta) yayılacağını belirler. Patlama için daire, duman için tek nokta idealdir.
- `Lifetime` (Yaşam Süresi): Her bir partikülün ekranda ne kadar süre kalacağı (saniye). Efektin ne kadar kalıcı olacağını belirler.
- `Direction` (Yön) & `Spread` (Yayılma): Partiküllerin hangi yöne ve ne kadar açıyla yayılacağını belirler.
- `Speed` (Hız), `Gravity` (Yerçekimi), `Linear Accel` (Doğrusal Hızlanma): Partiküllerin hareket dinamiklerini kontrol eder.
- `Color` (Renk) ve `Scale` (Boyut) Rampaları: Partiküllerin yaşam süreleri boyunca renklerini ve boyutlarını animasyonlu olarak değiştirebilirsin. Örneğin, bir patlama partikülü başlangıçta sarıdan kırmızıya dönüp küçülerek kaybolabilir.
Partikül sistemleri oldukça esnektir ve sadece birkaç ayar değişikliğiyle alevden suya, sihirli parıltılardan yoğun dumana kadar her türlü efekti yaratabilirsin. **`One Shot`** özelliğini açarak, sistemin sadece bir kez tetiklenmesini (örneğin bir patlama için) ve ardından durmasını sağlayabilirsin.
Partikül Efektini Kodla Tetikleme
Partikül sistemini bir olayla (örneğin mermi çarpışması) tetiklemek için, genellikle `emitting` (yayılım) özelliğini `true` yaparak başlar ve ardından kısa bir süre sonra kendini silmesini sağlarsın. Partikül sistemlerini sahneye dinamik olarak ekleyip silmek daha verimlidir.
# Mermi.ovx - Partikül efekti tetikleme örneği
extends RigidBody2D
# ... (Diğer değişkenler ve fonksiyonlar) ...
# Patlama partikül sahnesinin ön yüklemesi.
const PatlamaEfektiSahnesi = preload("res://efektler/PatlamaEfekti.tscn") # Kendi patlama sahnenizin yolu
func _on_body_entered(body: Node):
# Hasar verme kodu...
# Patlama efektini oluştur ve oyna.
var patlama_efekti = PatlamaEfektiSahnesi.instantiate()
patlama_efekti.global_position = global_position # Merminin pozisyonunda oluşur
get_tree().get_current_scene().add_child(patlama_efekti)
# Eğer partikül sistemi 'One Shot' değilse, manuel olarak başlat.
if !patlama_efekti.one_shot:
patlama_efekti.emitting = true
# Partikül efekti bittiğinde kendini silmesi için bir zamanlayıcı ayarla (eğer 'One Shot' değilse ve 'Autostart' kapalıysa)
# Genellikle partikül efekti sahneleri 'One Shot' açık ve 'Autostart' açık olarak ayarlanır
# ve 'Lifetime' süresinden sonra otomatik silinmeleri için bir 'Timer' eklenir.
var efekti_sil_timer = get_tree().create_timer(patlama_efekti.lifetime + 0.5) # Küçük bir gecikme ekleyerek bitmesini bekle
efekti_sil_timer.timeout.connect(patlama_efekti.queue_free)
queue_free() # Mermiyi sil
Bu kodla, mermi herhangi bir şeye çarptığında dinamik bir patlama efekti oluşacak ve ardından hem mermi hem de efekt sahneden silinecektir.
4.3 Oyun Sesleri: Atmosferi Yaratma ve Duyusal Geri Bildirim
Ses, oyunun atmosferini güçlendiren, oyuncuya önemli geri bildirimler sağlayan ve genel deneyimi inanılmaz derecede zenginleştiren, genellikle göz ardı edilen ama en önemli unsurlardan biridir. Orvix Engine, ses dosyalarını yönetmek ve çalmak için güçlü **AudioStreamPlayer** düğümleri ve Audio Bus sistemi sunar.
Adım 1: Ses Düğümlerini Ekleme (2D, 3D ve Global)
Orvix'te üç ana ses düğümü vardır:
- `AudioStreamPlayer`: Genel sesler veya GUI sesleri gibi, 2D veya 3D uzayda belirli bir konuma bağlı olmayan sesler için kullanılır (örneğin ana menü müziği, buton tıklamaları).
- `AudioStreamPlayer2D`: 2D oyun dünyasındaki belirli bir konuma bağlı sesler için kullanılır (örneğin düşmanın adımları, merminin çarpması). Kamera uzaklaştıkça sesin şiddeti azalır.
- `AudioStreamPlayer3D`: 3D oyun dünyasındaki belirli bir konuma bağlı sesler için kullanılır. Uzamsal ses efektleri yaratır.
Oyununuzun arka plan müziği için ana sahnenize bir `AudioStreamPlayer` düğümü ekle ve ses dosyanı (örneğin `.ogg`, `.wav` veya `.mp3`) İnceleyici panelindeki "Stream" özelliğine sürükle. `Autoplay` özelliğini aktif ederek oyun başladığında müziğin otomatik olarak çalmasını sağlayabilirsin. Ses efektleri (örneğin mermi sesi, patlama sesi) için ise her etkileşimli objeye (oyuncu, düşman, mermi) veya efekt sahnesine birer `AudioStreamPlayer2D` düğümü eklemelisin.
Adım 2: Koduyla Ses Oynatma ve Yönetimi
Bir sesi kod ile oynatmak oldukça basittir. Genellikle ilgili `AudioStreamPlayer` düğümüne bir referans alırsın ve ardından `play()` metodunu çağırırsın:
# Oyuncu.ovx - Ateş sesi örneği
extends CharacterBody2D
# ... (Önceki kodlar) ...
# Ateş sesi için AudioStreamPlayer2D düğümüne referans al.
# Bu düğümü Oyuncu sahnesinin altına eklemeyi unutmayın!
@onready var ates_sesi = $"AtesSesiPlayer" # Düğüm yolunuza göre ayarlayın.
# 'ates_et' fonksiyonu içindeki ses çalma.
func ates_et():
# ... mermi oluşturma kodları ...
# Sesi baştan başlat ve çal.
ates_sesi.play()
Bu basit komutla, oyunundaki aksiyonlara anında ses tepkileri ekleyebilirsin. Daha karmaşık ses yönetimi için Orvix'in `Audio Bus` sistemini kullanabilirsin. Bu sistemle müzik, ses efektleri ve diyalog seslerini ayrı ayrı kontrol edebilir, ses seviyelerini ayarlayabilir ve efektler (yankı, gecikme) ekleyebilirsin. Bu, oyunun genel ses dengesini ve kalitesini artırır.
Bölüm 5: Uzmanlık Seviyesi | Orvix Engine Geliştirme Sanatının Zirvesi
Tebrikler! Orvix Engine ile oyun geliştirme yolculuğunuzun bu aşamasına ulaştınız. Artık temel konularda yetkinliğe ulaştığınıza göre, bir oyunun "oynanabilir bir demodan" tam teşekküllü, optimize edilmiş ve yayınlanmaya hazır bir ürüne dönüşmesi için bilmeniz gereken en önemli 20 konuyu detaylı bir şekilde öğreneceksin. Her başlık altında hem teorik bilgi hem de pratik GDScript kod örnekleri bulacaksın.
5.1 GDScript'in Derinlikleri: Temiz ve Verimli Kodlama Sanatı
GDScript, basitliği ve esnekliği sayesinde hızlı prototipleme için mükemmeldir. Ancak, büyük projelerde temiz, sürdürülebilir ve verimli kod yazmak için dilin daha ileri düzey özelliklerini bilmek gerekir.
-
Sınıflar (Classes) ve Otomatik Yükleme (AutoLoad) ile Global Yönetim
Bir projenin büyümesiyle birlikte kodun yönetilebilir olması kritik hale gelir. Kendi özel sınıflarınızı oluşturarak kodu mantıksal, bağımsız parçalara ayırabilirsiniz.
class_nameanahtar kelimesi, bir script dosyasını global bir sınıf olarak tanımlamanızı sağlar, böylece editörde otomatik tamamlamadan yararlanabilirsiniz. "AutoLoad" (Otomatik Yükleme) ise, bu sınıflardan birini veya bir sahneyi, oyunun açılışında otomatik olarak yükleyerek her yerden erişilebilir bir singleton'a (tekil örnek) dönüştürür. Bu, oyunun ana durumunu (skor, can, seviye), envanterini, ses ayarlarını veya herhangi bir global yönetimi yapmak için mükemmel bir desendir.# GlobalGameManager.ovx (Project Settings -> AutoLoad'a "GlobalGameManager" adıyla eklenmeli) extends Node # 'class_name' ile global bir sınıf olarak tanımla. Editörde otomatik tamamlama sağlar. class_name GlobalGameManager var puan = 0 var oyuncu_can_sayisi = 3 var oyun_bitti = false # Puanı artıran metod func artir_puan(ek_puan: int): puan += ek_puan print("Toplam Puan: ", puan) # Buradan UI'daki puan etiketine sinyal yayabilirsiniz. # Oyunu bitiren metod func oyunu_bitir(): oyun_bitti = true print("Oyun Bitti! Final Puanı: ", puan) # Menüye geçiş veya oyun sonu ekranı açma gibi işlemleri burada yapabilirsiniz.Kullanım Örneği:
# Herhangi bir script dosyasında extends CharacterBody2D func _on_dusman_olduruldu(): # Global singleton'a doğrudan erişim (GlobalGameManager olarak adlandırdığımızı varsayarsak) GlobalGameManager.artir_puan(100) GlobalGameManager.oyuncu_can_sayisi -= 1 -
Enums (Sabit Listeler) ile Kod Okunabilirliğini Artırma
Oyun geliştirirken, belirli durumları, tipleri, nesne hallerini veya modları temsil etmek için sabit listeler (enums) kullanmak, kodunuzu sadece daha okunabilir hale getirmekle kalmaz, aynı zamanda hata yapma olasılığını da ciddi şekilde azaltır. Örneğin, bir düşmanın durumunu bir metin (`"bekle"`) veya rastgele bir sayı (`0`) yerine, daha anlamlı ve otomatik tamamlamayla desteklenen bir enum ile ifade edebilirsiniz. Bu, büyük kod tabanlarında tutarlılık sağlar.
# Düşman.ovx - Enum Kullanımı extends CharacterBody2D # Düşman durumları için enum tanımlama. GDScript'te bu, aslında sabit int değerleridir. enum Durum { BEKLE, YURUME, SALDIRMA, OLME, KACMA } var mevcut_durum = Durum.BEKLE # Varsayılan başlangıç durumu func _physics_process(delta: float): # 'match' ifadesi, durum makineleri için idealdir. match mevcut_durum: Durum.BEKLE: # Bekleme davranışları: Animasyon durdur, hareket etme, etrafı gözlemle. velocity = Vector2.ZERO # Oyuncuyu algılarsa durumu değiştir. if algila_oyuncu(): mevcut_durum = Durum.YURUME Durum.YURUME: # Yürüme davranışları: Hedefe doğru ilerle, yürüme animasyonunu oyna. # ... (hareket kodu) ... if saldiri_menzilinde(): mevcut_durum = Durum.SALDIRMA elif can < 20: mevcut_durum = Durum.KACMA # Düşük can durumunda kaçma Durum.SALDIRMA: # Saldırı davranışları: Saldırı animasyonu, hasar verme mantığı. velocity = Vector2.ZERO # Saldırırken durabilir if !saldiri_menzilinde(): mevcut_durum = Durum.YURUME # Menzil dışına çıkarsa takip etmeye devam et Durum.OLME: # Ölme davranışları: Ölüm animasyonu oyna, düşmanı sahneden sil. # ... (ölüm efekti veya zamanlayıcı) ... queue_free() # Düğümü sil. Durum.KACMA: # Kaçma davranışları: Oyuncudan uzaklaş, koşma animasyonunu oyna. # ... (ters yöne hareket kodu) ... # Yardımcı fonksiyonlar (örnek) func algila_oyuncu() -> bool: return true # Gerçek algılama mantığı buraya gelir func saldiri_menzilinde() -> bool: return false # Gerçek menzil kontrolü buraya gelir -
Özel Sinyaller (Custom Signals) ve Karmaşık Sinyal Bağlantıları
Orvix'in dahili düğüm sinyalleri (örneğin `body_entered`, `pressed`) haricinde, kendi özel sinyallerinizi de tanımlayabilirsiniz. Bu, bileşenler arasındaki iletişimi daha esnek, "gevşek bağlı" (loosely coupled) ve olay odaklı hale getirir. Bir sınıf bir olay hakkında sinyal yayar, diğer sınıflar ise bu sinyale abone olarak (connect) bu olaya göre tepki verir. Bu, UI ve oyun mekanikleri arasında ayrım yaparken veya karmaşık sistemler arasında bilgi akışını yönetirken çok güçlüdür.
# Oyuncu.ovx - Can Değişimi ve Özel Sinyal extends CharacterBody2D # 'can_degisti' adında bir sinyal tanımla. Bu sinyal, yeni can değerini argüman olarak yayacak. signal can_degisti(yeni_can: int) signal oldu() # Oyuncu öldüğünde yayılacak sinyal var can = 100: # 'setget' gibi davranan property setter'ı. 'can' değişkeni değiştiğinde tetiklenir. set(yeni_can): can = clampi(yeni_can, 0, 100) # Canı 0-100 arasında sınırla. emit_signal("can_degisti", can) # Can değişti sinyalini yay. if can == 0: emit_signal("oldu") # Can 0 olursa ölüm sinyalini yay. # Hasar alma metodu func hasar_al(miktari: int): self.can -= miktari # Setter otomatik olarak tetiklenecek. print("Oyuncu canı: ", can) # UI elementinde canı güncelleme örneği (örneğin bir HealthBar script'inde) # HealthBar.ovx'e eklenmeli: # extends ProgressBar # @onready var oyuncu = $"../Oyuncu" # Oyuncuya referans al # func _ready(): # oyuncu.can_degisti.connect(self._on_oyuncu_can_degisti) # max_value = oyuncu.can # Max değeri ayarla # func _on_oyuncu_can_degisti(yeni_can): # value = yeni_can # ProgressBar'ın değerini güncelle
5.2 Optimizasyon ve Performans Teknikleri: Akıcı Oyunlar İçin Sırlar
Büyük ve karmaşık oyunlarda performans sorunları kaçınılmazdır. Orvix Engine, bu sorunları tespit etmenize ve gidermenize yardımcı olacak güçlü araçlar sunar. Oyuncuların takılmadan, akıcı bir deneyim yaşamasını sağlamak için optimizasyon sanatını öğrenmelisin.
-
Performans Profilleyici (Profiler) ve Hata Ayıklama (Debugger): Performans Dedektifleri
Oyununuzun neden yavaşladığını veya takıldığını anlamak, optimize etmek için ilk ve en kritik adımdır. Orvix'in yerleşik **Profiler'ı**, CPU ve GPU kullanımını, bellek tahsisatını, çizim çağrılarını ve fiziksel işlemlerin harcadığı süreyi gerçek zamanlı olarak izlemenizi sağlar. Bu, darboğazları (bottleneck) tespit etmeniz için size somut veriler sunar. Örneğin, hangi script'in çok zaman harcadığını veya hangi sahnenin çok fazla poligon içerdiğini görebilirsiniz. **Hata Ayıklayıcı (Debugger)** ise, kodunuzu adım adım çalıştırarak değişken değerlerini anlık olarak görmenizi, kesme noktaları (breakpoints) ayarlayarak kodun belirli noktalarda durmasını sağlamanızı ve çağrı yığınını (call stack) incelemenizi sağlar. Bu ikili, karmaşık performans sorunlarını ve mantıksal hataları bulmak için vazgeçilmezdir.
-
`_process` ve `_physics_process` Arasındaki Kritik Fark: Akış Kontrolü
Performans optimizasyonunun en temel kurallarından biri, doğru fonksiyonu doğru amaç için kullanmaktır. `_process(delta)` fonksiyonu, oyunun her **çizim karesinde (frame)** çalışır ve ekran yenileme hızıyla (FPS) ilişkilidir. Görsel güncellemeler, giriş okumaları ve zamanla değişen animasyonlar için idealdir. `_physics_process(delta)` ise saniyede **sabit bir kez** (varsayılan olarak 60 kez) çalışır ve fiziksel hesaplamalar, çarpışma algılamaları ve hareket kodları için kullanılmalıdır. Karakter hareketlerini, çarpışmaları, yerçekimi etkileşimlerini ve fiziksel etkileşimleri daima `_physics_process` içinde yapın. Bu ayrım, oyununuzun farklı sistemlerde tutarlı fiziksel davranış sergilemesini ve gereksiz hesaplamalardan kaçınmasını sağlar.
-
Bellek Yönetimi ve Kaynak Yüklemesi: Akıllı Hafıza Kullanımı
Özellikle mobil cihazlar ve düşük sistemler için bellek yönetimi hayati önem taşır. Gereksiz kaynakları (dokular, sesler, sahneler) yüklemekten kaçının. Artık ihtiyaç duymadığınız düğümleri ve kaynakları `queue_free()` (düğümler için) veya `ResourceLoader.load()/unload()` (kaynaklar için) kullanarak sahneden kaldırın. `preload()` yerine `load()` kullanmak, kaynakları yalnızca ihtiyaç duyulduğunda yüklemenizi sağlar. Nesne havuzlama (object pooling) gibi teknikler, sık sık oluşturulan ve yok edilen nesneler (mermiler, düşmanlar) için performansı ciddi şekilde artırabilir.
5.3 Gelişmiş Düğüm Sistemleri: Karakter ve Sahne Yönetiminde Ustalık
Orvix Engine'in düğüm tabanlı yapısı, karmaşık oyun mekaniklerini bile modüler ve yönetilebilir hale getirmenize olanak tanır. İşte daha dinamik ve esnek oyunlar oluşturmak için kullanabileceğiniz bazı ileri düzey düğüm sistemleri:
-
Animasyon Ağacı (AnimationTree) ile Karmaşık Animasyon Akışı
Basit
AnimationPlayerdüğümü, tekli animasyonları oynatmak için yeterlidir. Ancak, bir karakterin yürüme, koşma, zıplama, bekleme gibi farklı animasyon durumları arasında yumuşak ve mantıksal geçişler yapması gerektiğindeAnimationTreedüğümü devreye girer. Bu düğüm, bir **durum makinesi (state machine)** veya **karışım ağacı (blend tree)** kullanarak animasyonları görsel olarak bir ağaç yapısında bağlamanızı, geçiş koşullarını (örneğin hız > 0 ise koşmaya geç) ve geçiş sürelerini ayarlamanızı sağlar. Böylece kodunuzda sadece karakterin durumunu değiştirerek doğru animasyonun otomatik olarak oynatılmasını sağlayabilirsiniz. -
Durum Makineleri (State Machines) ile Karakter ve Düşman Kontrolü
Durum makineleri, bir objenin (karakter, düşman, oyun durumu) farklı davranışlarını organize etmenin en güçlü ve ölçeklenebilir yollarından biridir. Örneğin, bir düşman "Bekleme" durumundayken oyuncuyu arar, "Takip" durumundayken oyuncuya doğru ilerler ve "Saldırı" durumundayken ona saldırır. Her durum için ayrı bir kod parçası yazmak yerine, hepsini tek bir durum makinesi altında yönetebilirsiniz. Bu, kod tekrarını azaltır ve davranışları kolayca değiştirebilmenizi sağlar. GDScript'teki `enum`'lar ve `match` ifadeleri ile kolayca durum makineleri oluşturabilirsiniz (örneğini yukarıda vermiştik).
# Gelişmiş Düşman Durum Makinesi Örneği extends CharacterBody2D enum State { IDLE, PURSUE, ATTACK, DEAD, PATROL } # Yeni durumlar eklendi var state = State.IDLE var player: Node2D = null var hiz = 100.0 var saldiri_menzili = 50.0 var goruntu_menzili = 300.0 func _ready(): player = get_tree().get_first_node_in_group("oyuncular") # Eğer düşman devriye gezecekse, bir Patrul noktası veya yolu ayarlanabilir. func _physics_process(delta: float): match state: State.IDLE: velocity = Vector2.ZERO # Oyuncuyu algılarsa takip et. if player and global_position.distance_to(player.global_position) < goruntu_menzili: state = State.PURSUE else: # Boşta gezinme veya rastgele hareket. pass State.PURSUE: # Oyuncuyu takip et. if player: var direction = (player.global_position - global_position).normalized() velocity = direction * hiz move_and_slide() if global_position.distance_to(player.global_position) < saldiri_menzili: state = State.ATTACK elif global_position.distance_to(player.global_position) > goruntu_menzili: state = State.IDLE # Oyuncu menzilden çıkarsa dur else: state = State.IDLE State.ATTACK: velocity = Vector2.ZERO # Saldırı mantığı, animasyon, hasar verme. if global_position.distance_to(player.global_position) >= saldiri_menzili: state = State.PURSUE # Menzil dışına çıkarsa tekrar takip et. State.DEAD: # Ölüm animasyonu, skor verme, sahneden silme. queue_free() State.PATROL: # Devriye gezme mantığı (belirli noktalara gitme) pass # Daha karmaşık devriye kodu buraya gelir. # hasar_al metodu (Düşmanın canını yönetmek için) var can = 50 func hasar_al(miktari: int): can -= miktari print("Düşman canı: ", can) if can <= 0: state = State.DEAD -
Tween ile Akıcı ve Dinamik Geçişler
Bir objenin bir özellik değerini (konum, rotasyon, boyut, renk, opaklık) belirli bir süre içinde yumuşak ve kontrol edilebilir bir şekilde değiştirmek için
Tweendüğümünü veya `create_tween()` metodunu kullanın. Bu, menülerin zarif bir şekilde açılması/kapanması, bir objenin ekranda titreşmesi, karakterin bir noktaya kayması veya UI elementlerinin animasyonlu olarak görünmesi gibi birçok görsel efekt için idealdir. `Tween`'ler, farklı geçiş türleri (linear, sine, elastic, bounce) ve kolaylık fonksiyonları (ease-in, ease-out, ease-in-out) ile özelleştirilebilir.# Butona basıldığında pencereyi açma animasyonu veya karakter zıplama extends Control # UI için # extends CharacterBody2D # Karakter için @onready var pencere_paneli = $"AyarlarPaneli" # Animasyon yapılacak düğüm func _on_ac_buton_pressed(): # Mevcut tween'i durdur (varsa), çakışmayı önler. if get_tree().has_group("active_tweens"): # Kendi tween grubunuzu oluşturabilirsiniz. var active_tweens = get_tree().get_nodes_in_group("active_tweens") for t in active_tweens: if t.get_target() == pencere_paneli: t.kill() var tween = create_tween() tween.set_trans(Tween.TRANS_ELASTIC) # Yaylı geçiş tween.set_ease(Tween.EASE_OUT) # Yavaş başlayıp hızlanır, sonra yavaşlar. # Pencerenin konumunu 0.8 saniyede (100, 100) pozisyonuna yumuşakça getir. tween.tween_property(pencere_paneli, "position", Vector2(100, 100), 0.8) # Pencerenin opaklığını da aynı anda değiştir (paralel animasyon) tween.tween_property(pencere_paneli, "modulate:a", 1.0, 0.5) # Görünür hale getir. # Animasyon bittikten sonra bir fonksiyon çağırabilirsin. tween.finished.connect(func(): print("Pencere animasyonu bitti!"))
5.4 Oyun Fiziği ve Çarpışma Mekanikleri: Gerçekçilik ve Kontrol
Oyununuzdaki fiziksel etkileşimler, oyuncuya gerçekçi bir deneyim sunmak için kritik öneme sahiptir. Orvix Engine'in güçlü fizik motoru, çarpışmaları, hareketleri ve etkileşimleri hassas bir şekilde kontrol etmenizi sağlar.
-
Fizik Katmanları (Physics Layers) ve Maskeleri (Masks): Gelişmiş Çarpışma Filtreleme
Oyununuzdaki farklı objelerin (oyuncu, düşman, mermi, zemin, duvar, toplanabilir eşyalar) hangi gruplara ait olduğunu ve hangi gruplarla çarpışacağını veya etkileşimde bulunacağını belirlemek için fizik katmanlarını ve maskelerini kullanmak hayati öneme sahiptir. **Katman (Layer)**, bir objenin "hangi katmanda var olduğunu", **Maske (Mask)** ise "hangi katmandaki objeleri algılayacağını veya onlarla çarpışacağını" belirler. Bu, gereksiz çarpışma hesaplamalarını önleyerek performansı ciddi şekilde artırır ve fizik etkileşimlerini hassas bir şekilde kontrol etmenizi sağlar. Örneğin, mermilerin sadece düşmanlarla çarpışmasını, oyuncunun sadece zeminle çarpışmasını sağlayabilirsiniz.
-
`RayCast2D` ve `RayCast3D` ile Işın Gönderimi: Hassas Algılama
RayCast2D(2D için) veya `RayCast3D` (3D için) düğümü, belirli bir yöne sanal bir "ışın" (veya çizgi) göndererek bu ışının bir şeye çarpıp çarpmadığını kontrol etmenizi sağlar. Bu, düşmanın önündeki engelleri tespit etmek (yol bulma için), bir karakterin zemine basıp basmadığını kontrol etmek (platform oyunlarında zıplama için hayati), interaktif bir objeyi işaret etmek veya düşmanın görüş alanını kontrol etmek gibi birçok senaryoda kullanılır. Sonuç olarak çarptığı objeyi ve çarpışma noktasını alabilirsiniz.# Oyuncunun zemine basıp basmadığını kontrol eden raycast örneği extends CharacterBody2D # '@onready' ile editörden bağlı olan RayCast2D düğümüne referans al. @onready var zemin_ray = $"ZeminRayCast2D" # Oyuncu düğümünün altında olmalı ve doğru pozisyonda. # _physics_process içinde raycast'i kontrol et. func _physics_process(delta: float): # Raycast'i güncelle (eğer aktif değilse veya sürekli güncellenmesi gerekiyorsa). zemin_ray.force_raycast_update() if zemin_ray.is_colliding(): var collider = zemin_ray.get_collider() # Çarptığı düğümü al. if collider and collider.is_in_group("zeminler"): # Çarptığı nesnenin "zeminler" grubunda olup olmadığını kontrol et. print("Zemine bastı! Collider: ", collider.name) # Zıplama veya diğer zemin bazlı eylemleri burada tetikleyebilirsiniz. elif collider and collider.is_in_group("platformlar"): print("Platforma bastı!") else: print("Havada!") -
`Area2D` ve `Area3D` ile Bölge Algılaması: Çarpışmasız Etkileşimler
Area2D(2D için) veya `Area3D` (3D için) düğümleri, fiziksel bir çarpışma olmadan, bir objenin belirli bir "bölgeye" girip girmediğini algılamanızı sağlar. `RigidBody` veya `CharacterBody` gibi düğümler fiziksel olarak birbirine çarpar ve tepki verirken, `Area` düğümleri sadece bir nesnenin alanına girdiğini veya çıktığını algılar ve ilgili sinyalleri yayar (`body_entered`, `body_exited`, `area_entered`, `area_exited`). Bu, toplama objeleri (altın, iksir), tetikleyiciler (kapı açma, sahne değiştirme), düşmanın menzili (oyuncuyu algılama) veya tehlikeli bölgeler (zehirli havuz) için idealdir. Sinyal sistemi ile birlikte kullanıldığında çok güçlüdür.
5.5 Kullanıcı Arayüzü (GUI) Mimarisi: Profesyonel ve Esnek Arayüzler
Bir oyunun kullanıcı arayüzü (GUI), oyuncu deneyiminin ayrılmaz bir parçasıdır. Orvix Engine'in sağlam GUI sistemi, her cihazda harika görünen, responsive ve etkileşimli arayüzler oluşturmanıza olanak tanır.
-
`Control` Düğümlerinin Esnekliği: Responsive UI Tasarımı
Orvix'te tüm arayüz elemanları `Control` düğümleridir. Bu düğümlerin **`Anchor` (Çapa)**, **`Margin` (Kenar Boşluğu)** ve **`Size Flags` (Boyut Bayrakları)** gibi güçlü özelliklerini kullanarak, farklı ekran boyutlarına ve çözünürlüklere otomatik olarak uyum sağlayan responsive arayüzler oluşturabilirsiniz. `Anchor`'lar, bir UI elementinin ekranın belirli bir kenarına, köşesine veya merkezine göre konumlanmasını sağlarken, `Size Flags`'ler bir elementin ebeveynine göre ne kadar genişleyip daralacağını belirler. Bu, oyununuzun farklı cihazlarda (mobil, tablet, masaüstü) sorunsuz çalışmasını ve her zaman harika görünmesini sağlar.
-
Özel Temalar (Custom Themes) ve Stil Yönetimi: Tek Tuşla Yeniden Tasarım
Oyununuzun tüm UI öğelerinin (butonlar, paneller, kaydırıcılar, metin kutuları) görünümünü ve hissini tek bir yerden yönetmek için **`Theme`** kaynaklarını kullanın. Bu, her bir UI düğümünün rengini, fontunu, kenarlığını veya boyutunu tek tek ayarlamak yerine, projeniz için global bir stil rehberi oluşturmanızı sağlar. Bir `Theme` kaynağı oluşturup içine farklı UI elementleri için stiller tanımlayabilirsiniz (örneğin, tüm butonların varsayılan rengi, fontu, hover efekti). Bu, oyununuzun markalaşma tutarlılığını sağlar ve tasarım değişikliklerini saniyeler içinde tüm arayüze uygulamanıza olanak tanır. GUI üzerinde hızla yineleme yapmak için vazgeçilmezdir.
-
İstemci Tarafı Sinyalleri ve Kullanıcı Etkileşimleri: UI'ya Hayat Verme
`Control` düğümleri, kullanıcı etkileşimlerini (tıklama, üzerine gelme, fare tekerleği, klavye girişi) tetiklemek için kendi zengin sinyal setine sahiptir. Bu sinyalleri (`pressed`, `mouse_entered`, `value_changed` vb.) scriptlerinize bağlayarak butonlara işlevsellik, kaydırıcılara tepkiler veya metin kutularına veri girişi yeteneği katın. Bu, oyuncu ile oyun arasındaki ana etkileşim yoludur. Örneğin, bir "Ayarlar" butonuna basıldığında bir ayarlar panelinin açılmasını veya bir "Çıkış" butonuna basıldığında oyunun kapanmasını sağlayabilirsiniz.
5.6 Oyun Verileri ve Kalıcı Depolama: Kaydetme ve Yükleme Sistemleri
Oyuncuların ilerlemesini kaydetmek ve daha sonra devam etmelerine izin vermek, modern bir oyun için temel bir özelliktir. Orvix Engine, bu verileri güvenli ve verimli bir şekilde yönetmek için çeşitli araçlar sunar.
-
Kalıcı Veri Kaydı ve Yüklemesi: Oyun Durumunu Saklama
FileAccesssınıfını kullanarak, oyuncu verilerini (puan, envanter, seviye ilerlemesi, ayarlar, kilidi açılmış özellikler) yerel dosyalara kaydetmeyi ve daha sonra bu verileri yüklemeyi öğrenin. **JSON** (JavaScript Object Notation) formatı, okunabilirliği ve platformlar arası uyumluluğu nedeniyle genellikle tercih edilir. Daha hassas veya büyük veriler için ikili (binary) formatlar da kullanılabilir. Oyunun kaydedilmesi ve yüklenmesi, oyuncu deneyimi için temel bir özelliktir ve oyuncuların oyununuzla uzun süre bağlı kalmasını sağlar. Verileri `user://` dizinine kaydetmek, kullanıcının sistemine özel bir dizinde güvenli ve yazılabilir bir konum sağlar.# Oyun Verilerini JSON Formatında Kaydetme ve Yükleme extends Node # Bu script bir GameManager veya AutoLoad'a eklenebilir. const KAYIT_DOSYASI_YOLU = "user://savegame.json" func oyunu_kaydet(): # Kaydedilecek verileri bir Dictionary'de toplarız. var veri = { "puan": GlobalGameManager.puan, "can": GlobalGameManager.oyuncu_can_sayisi, "son_seviye": GlobalGameManager.mevcut_seviye, "envanter": GlobalGameManager.oyuncu_envanteri # List, Dictionary olabilir } # Dosyayı yazma modunda aç. Hata durumunu kontrol et. var dosya = FileAccess.open(KAYIT_DOSYASI_YOLU, FileAccess.WRITE) if dosya: # Dictionary'yi JSON string'ine dönüştür ve dosyaya yaz. dosya.store_string(JSON.stringify(veri)) dosya.close() print("Oyun Başarıyla Kaydedildi!") else: print("Hata: Kayıt dosyası yazılamadı!") func oyunu_yukle(): # Dosyanın varlığını kontrol et. if !FileAccess.file_exists(KAYIT_DOSYASI_YOLU): print("Kayıt dosyası bulunamadı, yeni oyun başlatılıyor.") return false # Dosyayı okuma modunda aç. var dosya = FileAccess.open(KAYIT_DOSYASI_YOLU, FileAccess.READ) if dosya: # Dosya içeriğini oku. var json_string = dosya.get_as_text() # JSON string'ini bir GDScript nesnesine (Dictionary) dönüştür. var parse_result = JSON.parse_string(json_string) if parse_result is Dictionary: # Başarılı ayrıştırma kontrolü var veri = parse_result # Global değişkenleri veya oyun durumunu yüklenen verilerle güncelle. # .get() metodunu varsayılan değerle kullanarak hatalardan kaçının. GlobalGameManager.puan = veri.get("puan", 0) GlobalGameManager.oyuncu_can_sayisi = veri.get("can", 3) GlobalGameManager.mevcut_seviye = veri.get("son_seviye", 1) GlobalGameManager.oyuncu_envanteri = veri.get("envanter", {}) print("Oyun Başarıyla Yüklendi!") dosya.close() return true else: print("Hata: Kayıt dosyası içeriği geçersiz veya bozuk.") dosya.close() return false else: print("Hata: Kayıt dosyası okunamadı!") return false
5.7 Görsel Şaheserler: Shader'lar ile Grafik Büyüsü
Shader'lar, bir materyalin veya sahnenin piksel piksel nasıl çizileceğini belirleyen küçük programlardır. Kendi shader'larınızı yazarak, oyununuzda standart görsellerle elde edemeyeceğiniz benzersiz, dinamik ve görsel açıdan çarpıcı efektler yaratabilirsiniz. Bu, oyununuzu görsel olarak bir üst seviyeye taşımanın en güçlü yollarından biridir.
-
ShaderKullanımı: Görsel Efektlerin Derinlikleri (GLSL ES)Orvix Engine'de shader'lar, OpenGL ES Shading Language (GLSL ES) söz dizimine benzer bir dil kullanılarak yazılır. Bir shader, genellikle bir `ShaderMaterial`'e atanır ve bir `Sprite2D`, `MeshInstance3D` veya hatta bir `Viewport`'a uygulanabilir. Yaygın kullanım alanları şunlardır:
- **Su Yansımaları ve Dalgalanmalar:** Gerçekçi veya stilize su efektleri.
- **Ekran Efektleri (Post-Processing):** Ekran titremesi (oyuncu hasar aldığında), renk düzeltmeleri (filtreler), bulanıklık veya film greni gibi efektler.
- **Özel Işıklandırmalar:** Cel shading, çizgi film benzeri gölgelendirme veya dinamik neon ışık efektleri.
- **Karakter Hasar Efektleri:** Karakterin hasar aldığında kırmızı yanıp sönmesi, şeffaflaşması veya dağılması.
- **Yanma veya Erime Efektleri:** Objelerin yanarak veya eriyerek kaybolması.
// shader_parlama.gdshader - Basit bir parlama/renklendirme shader'ı örneği shader_type canvas_item; // 2D objeler için (Sprite2D, Control vb.) // 3D objeler için 'shader_type spatial;' kullanılır. // Editörden ayarlanabilir uniform değişkenler. // 'hint_color' bir renk seçici, 'range_float' bir kaydırıcı sağlar. uniform vec4 parilti_renk: hint_color = vec4(0.0, 1.0, 1.0, 1.0); // Varsayılan turkuaz renk uniform float parilti_gucu: range_float(0.0, 5.0, 0.1) = 1.5; // Parlaklık gücü uniform float zaman_faktor = 0.0; # GDScript'ten güncellenebilir (örneğin _process içinde time değişkeni) // Fragment shader, her piksel için çalışır. void fragment() { // Pikselin orijinal rengini al. TEXTURE dahili bir değişkendir. // UV koordinatları doku üzerinde geçerli pikselin konumunu verir. vec4 renk = texture(TEXTURE, UV); // Şeffaf olmayan pikseller için efekti uygula. if (renk.a > 0.0) { // Orijinal rengin RGB kanallarına parıltı rengini gücüne göre ekle. renk.rgb += parilti_renk.rgb * parilti_gucu; // Zaman faktörünü kullanarak hafif bir animasyon ekle (örneğin titreşme). float dalgalanma = sin(zaman_faktor * 5.0 + UV.x * 10.0) * 0.1; renk.rgb += dalgalanma * parilti_gucu * 0.5; } // Son rengi piksele atıyoruz. COLOR, çıktının rengidir. COLOR = renk; }Bu shader'ı bir `Sprite2D`'ye uygulamak için: `Sprite2D`'yi seçin, İnceleyici panelinde `Material` özelliğine yeni bir `ShaderMaterial` atayın. Ardından `ShaderMaterial`'i seçip `Shader` özelliğine `.gdshader` dosyanızı sürükleyin. Artık uniform değişkenleri İnceleyici'den ayarlayarak shader'ı canlı olarak görebilirsiniz.
5.8 Proje Yönetimi ve Yayınlama: Oyununuzu Dünyaya Açma
Oyun geliştirmenin son aşaması, projeyi doğru bir şekilde yönetmek ve tamamlanmış ürünü oyunculara ulaştırmak. Bu süreç, sadece kod yazmaktan çok daha fazlasını içerir.
-
Git ile Versiyon Kontrolü ve Ekip Çalışması (Vazgeçilmez)
Profesyonel bir oyun geliştirme sürecinde, kodunuzu ve projenizin tüm varlıklarını yedeklemek, farklı versiyonlarını yönetmek ve ekip üyeleriyle sorunsuz bir şekilde çalışmak için **Git** gibi bir versiyon kontrol sistemi kullanmak kritik önem taşır. Orvix Engine, doğrudan Git entegrasyonuna sahiptir (Editör > Sürüm Kontrolü). Değişiklikleri takip etmek, eski versiyonlara geri dönmek, farklı özellikler üzerinde paralel çalışmak (branching) ve ekip üyeleri arasında kod çakışmalarını çözmek (merging) için Git'i öğrenmelisiniz. GitHub, GitLab veya Bitbucket gibi platformlar, projelerinizi depolamak ve yönetmek için popüler seçeneklerdir.
-
Hata Ayıklama (Debugging) ve Loglama Teknikleri: Sorun Giderme Sanatı
Oyununuzdaki hataları bulmak ve düzeltmek, geliştirme sürecinin büyük bir kısmını oluşturur. Orvix'in yerleşik **hata ayıklayıcı (debugger)** sekmesi, değişkenleri gerçek zamanlı olarak izlemenize, kodu durdurup adım adım çalıştırmanıza, kesme noktaları (breakpoints) ayarlamanıza ve çağrı yığınını (call stack) görmenize olanak tanır. Basit sorunları gidermek ve olayları izlemek için GDScript'teki `print()` fonksiyonunu kullanarak konsola mesajlar göndermek veya `push_warning()` / `push_error()` fonksiyonlarıyla özel uyarılar/hatalar oluşturmak harika bir başlangıçtır. Karmaşık hataları bulmak için hata ayıklayıcıyı etkin bir şekilde kullanmayı öğrenin.
-
Farklı Platformlara Derleme (Export): Hedef Kitlenize Ulaşın
Orvix Engine, oyununuzu farklı platformlara (Windows, macOS, Linux, Android, iOS, HTML5) kolayca derlemenizi sağlayan güçlü bir derleme (export) sistemine sahiptir. **Proje > Derle (Export)** menüsünden farklı platformlar için derleme ön tanımları (export presets) oluşturabilirsiniz. Her platform için özel ayarlar (örneğin çözünürlük, ikonlar, sıkıştırma, DRM) yapabilirsiniz. Hedef kitlenize ulaşmak ve oyununuzu farklı cihazlarda oynanabilir kılmak için bu adımı iyi anlamak ve her platform için test etmek önemlidir.
-
Son Kontroller, Optimizasyon ve Paketleme: Yayınlanmaya Hazırlık
Oyununuzu dünyaya yayınlamadan önce, son bir kez kapsamlı testler yapın. Tüm mekaniklerin doğru çalıştığından, hataların giderildiğinden ve oyunun akıcı olduğundan emin olun. Hata ayıklama kodlarını kaldırın, performansı tekrar test edin (profilleyici ile) ve son paketleme ayarlarınızı kontrol edin. Oyununuzun küçük boyutlu, hızlı yüklenebilir ve hedef platformun (Steam, Itch.io, Google Play Store, App Store) özel gereksinimlerini karşıladığından emin olun. Gerekirse kapalı veya açık beta testleri yaparak gerçek kullanıcılardan geri bildirimler toplayın ve bu geri bildirimleri değerlendirerek son rötuşları yapın. Oyununuzu en iyi şekilde sunmak için bu son adımlar hayati öneme sahiptir.
Tebrikler, Artık Bir Uzmansınız!
Bu devasa rehber serisi ile Orvix Engine'in temellerinden en ileri düzey uzmanlık konularına kadar birçok önemli konuyu derinlemesine öğrendin. Artık kendi hayalindeki oyunları tasarlayacak, programlayacak, optimize edecek ve dünyaya yayınlayacak bilgi ve beceriye sahipsin.
Unutma, oyun geliştirme sürekli bir öğrenme ve deneyimleme sürecidir. Kendi projelerine korkusuzca başla, Orvix topluluğuyla aktif olarak etkileşimde bulun, karşılaştığın her sorunu bir öğrenme fırsatına çevir ve her zaman yeni teknolojileri ve fikirleri denemekten çekinme. Senin gibi yetenekli geliştiricilerin yaratacağı yeni oyunları görmek için sabırsızlanıyoruz! Oyunlarını yaratmaya şimdi başla ve dijital dünyayı şekillendir!