Merhaba Oyun Geliştiricileri ve Meraklıları! Günümüzde oyun dünyası, sadece büyük stüdyoların değil, bağımsız geliştiricilerin de yeteneklerini sergileyebileceği bir oyun alanı sunuyor. Eğer siz de kendi oyun dünyanızı yaratmak ve oyun geliştirme serüvenine atılmak istiyorsanız, doğru yerdesiniz. Bu yazıda, oyun geliştirmenin kapılarını aralayan ve 2D oyunlarla tanışmamıza yardımcı olan Phaser 3 framework’ünü keşfedeceğiz.
Phaser 3 ile Tanışma: 2D Oyunların Büyülü Dünyasına Adım Atın
Phaser 3 Nedir?
Phaser 3, JavaScript tabanlı bir oyun geliştirme framework’üdür. 2D oyunlar oluşturmak için güçlü ve esnek bir araç seti sunar. Phaser, başlangıçta öğrenmesi kolay olmasıyla bilinir ve aynı zamanda profesyonel oyun geliştiricilerinin ihtiyaçlarını karşılayacak kadar geniş bir özellik yelpazesi sunar.
Neden Phaser 3?
Phaser 3, açık kaynaklı olması, geniş topluluğu ve sürekli gelişen yapısıyla öne çıkar. Hem yeni başlayanlar hem de deneyimli geliştiriciler için uygun olmasıyla dikkat çeker. Ayrıca, tarayıcı tabanlı oyunlar için mükemmel performans sağlar.
2D Oyun Dünyasına Hoş Geldiniz
Phaser 3, özellikle 2D oyun geliştirme konusunda uzmanlaşmıştır. Basit platform oyunlarından karmaşık bulmaca oyunlarına kadar geniş bir yelpazede projeler oluşturabilirsiniz. Sprite’lar, animasyonlar, fizik motoru ve daha birçok özellikle 2D oyun dünyasını şekillendirmek için kullanılabilir.
Bu yazı dizisinin ilerleyen bölümlerinde, Phaser 3’ün temellerini öğrenerek kendi oyun projelerinizi nasıl hayata geçirebileceğinizi adım adım keşfedeceğiz. Öğrenmeye hazır mısınız?
Eğer cevabınız evetse, gelin birlikte Phaser 3 ile 2D oyun dünyasına giriş yapalım!
Umarım bu giriş yazısı sizin yazınıza iyi bir başlangıç olur. İyi yazılar dilerim!
Ortam Kurulumu
Phaser 3 ile 2D oyun geliştirmeye başlamadan önce, geliştirme ortamınızı kurmanız gerekiyor. İşte Phaser 3 kullanmak için temel gereksinimler:
- Bir Metin Düzenleyici (Text Editor): Bir metin düzenleyici seçmek, kodlarınızı yazmanız ve düzenlemeniz için önemlidir. Önerilen metin düzenleyiciler arasında Visual Studio Code, Atom veya Sublime Text gibi popüler araçlar bulunmaktadır.
- Web Tarayıcısı: Phaser 3, tarayıcı tabanlı oyunlar oluşturmak için tasarlanmıştır. Geliştirdiğiniz oyunu tarayıcıda ön izlemek ve test etmek için Chrome, Firefox, Safari veya Edge gibi bir tarayıcı kullanmanız gerekecek.
- Phaser 3 Kütüphanesi: Alttaki örnek Phaser 3 eklenilmiş index.html dosyası ile kütüphaneyi kullanmaya başlayabileceğiz.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Phaser 3 Get Started</title> </head> <body> <script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script> <!--Import phaser3 lib--> <script src="script.js"></script> <!--Import initial js file--> </body> </html> |
Bu temel gereksinimlere sahip olduktan sonra, Phaser 3 ile 2D oyun geliştirmeye başlamaya hazır durumdasınız demektir. Projenizin başlangıç aşamalarında, Phaser 3 resmi dokümantasyonu ve öğretici kaynakları size faydalı olacaktır. Bu makalede dosyaları çok parçalamayacağım, zira basit bir seviyede bir giriş makalesidir. Tek bir sahneye odaklanarak, okuyucuları sıkmadan temel konuları ele alarak makaleyi tamamlamayı amaçlıyorum. Eğer Phaser 3 ile oyun geliştirme konusunda ilgiliyseniz, bloguma abone olarak gelecek Phaser 3 ve diğer makalelerden haberdar olabilirsiniz.
Konfigürasyon Tanımı
Şimdi ise yavaş yavaş 2D oyun temellerini atalım ve işe konfigürasyon oluşturmak ile başlayalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 | const config = { type: Phaser.AUTO, width: 800, height: 600, physics: { default: 'arcade', arcade: { gravity: { y: 300 }, debug: false, }, }, scene: [] }; |
Bu kod, Phaser 3 oyun motorunu kullanarak bir oyun oluşturmak için gerekli olan temel yapıyı tanımlayan bir yapılandırmadır. Konfigürasyon ile ilgili tanımlayabileceğiniz diğer parametrelere Phaser 3 API Documentation – Class: Config (photonstorm.github.io) adresinden ulaşabilirsiniz. İşte bu yapılandırmanın ana öğeleri:
type: Phaser.AUTO
: Bu, Phaser’ın otomatik olarak WebGL veya Canvas renderleme türünü seçmesini sağlar. Tarayıcı WebGL’i destekliyorsa WebGL kullanılır, aksi takdirde Canvas kullanılır.width: 800
veheight: 600
: Oyunun genişliği ve yüksekliğini piksel cinsinden belirtir. Bu, oyun penceresinin boyutunu belirler.physics
: Oyun fizik motoru ayarlarını içerir. Bu örnekte, varsayılan fizik motoru ‘arcade’ olarak ayarlanmıştır. Arcade fizik motoru, basit 2D oyunları için kullanışlıdır.gravity: { y: 300 }
: Y eksenindeki yerçekimi miktarını belirtir. Bu, örneğin zıplama davranışını kontrol etmek için kullanılır.debug: false
: Fizik motorunun hata ayıklama modunu belirtir.true
olarak ayarlandığında, çarpışma kutuları ve fizik nesneleri gibi öğeleri gösterir.
scene: []
: Bu, oyunun içerdiği sahneleri belirtir. Örnekte boş bir dizi olarak bırakılmıştır, ancak gerçek bir oyun için sahne sınıflarını içerecek bir dizi olmalıdır. Sahneler, oyunun farklı bölümlerini temsil eder.
Bu temel yapılandırma, Phaser oyunlarını başlatmak için kullanılır. Gerçek bir oyun geliştirdiğinizde, bu yapılandırmayı ihtiyacınıza göre özelleştirebilir ve sahneleri ekleyebilirsiniz.
Sahne Oluşturma
Konfigürasyonu oluşturduktan sonra hemen bir Scene adını verdiğimiz sahne oluşturalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Game extends Phaser.Scene { constructor() { super({key:"game"}); // Bu sınıfın kurucu fonksiyonudur. Yapıcı fonksiyon, sınıf bir örneği oluşturulduğunda otomatik olarak çağrılır. super({key:"game"}) ifadesi, üst sınıfın (Phaser.Scene) kurucu fonksiyonunu çağırarak gerekli başlatma işlemlerini gerçekleştirir. Ayrıca, bu sahnenin benzersiz bir anahtar ("game" olarak belirtilmiş) ile tanımlandığını belirtir. Bu anahtar, sahneden diğer yerlerden erişim sağlamak için kullanılabilir. }; preload() { // Bu metod, oyun sahnesinin ön yükleme işlemleri için kullanılır. Örneğin, burada oyun içinde kullanılacak olan resimler, ses dosyaları gibi kaynaklar yüklenir. Ancak, bu örnekte bu fonksiyon boş bırakılmış. } create() { // Bu metod, oyun sahnesinin oluşturulduğu aşamadır. Oyunun başlatılması ve kullanıcı arayüzünün oluşturulması gibi işlemler burada gerçekleştirilir. Bu örnekte de bu fonksiyon boş bırakılmış. } update() { // Bu metod, oyun sahnesinin sürekli olarak güncellendiği aşamadır. Oyun mantığı, fizik hesaplamaları ve diğer dinamik güncellemeler bu fonksiyonda yer alabilir. Bu örnekte de bu fonksiyon boş bırakılmış. } }; |
Bu kodda, class Game extends Phaser.Scene
şeklinde bir sınıf oluşturuluyor ve bu sınıf, Phaser çerçevesinin Scene
sınıfından türemiştir. Phaser’da oyunun çeşitli bölümlerini temsil etmek için sahneler kullanılır, ve bu sınıf bir oyun sahnesini temsil eder ve ihtiyaca göre preload
, create
, ve update
metotlarına özel işlevsellik ekleyerek oyun mantığını oluşturabilirsiniz.
Oluşturulan Sahnenin Tanıtılması
Her sahnenin phaser sisteminden tanınması için, oluşturduğumuz config
nesnesi içinde bulunan scene
dizisine eklenmelidir. Bu durumu aşağıdaki örnek kodda görebilirsiniz.
1 2 3 4 | const config = { ... scene: [Game] }; |
Proje Yapısı Son Hali
Şimdiye kadar oluşturduğumuz dosyalar ile birlikte proje yapımız en basit hali ile şöyledir. Konu 101 seviyesinde bir anlatıma sahip olduğundan typescript, node_modules üzerinden kullanım, folder structure gibi konuların tamamı bu makalede es geçilmiştir. Makalenin sonraki serilerinde bu konulara tek tek değinilecektir.
📦 root
┣ 📜index.html
┣ 📜male.png
┗ 📜script.js
Not: male.png adındaki dosyaya makale devamından ulaşacaksınız.
Projenin Temel Hali
Projenin konfigürasyonu, sahne oluşturma ve game initialize gibi işlemlerin tamamını script.js içerisinde yaptık. Hemen script.js dosyasının son haline göz atalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | class Game extends Phaser.Scene { constructor() { super({ key: "game" }); // Bu sınıfın kurucu fonksiyonudur. Yapıcı fonksiyon, sınıf bir örneği oluşturulduğunda otomatik olarak çağrılır. super({key:"game"}) ifadesi, üst sınıfın (Phaser.Scene) kurucu fonksiyonunu çağırarak gerekli başlatma işlemlerini gerçekleştirir. Ayrıca, bu sahnenin benzersiz bir anahtar ("game" olarak belirtilmiş) ile tanımlandığını belirtir. Bu anahtar, sahneden diğer yerlerden erişim sağlamak için kullanılabilir. }; preload() { // Bu metod, oyun sahnesinin ön yükleme işlemleri için kullanılır. Örneğin, burada oyun içinde kullanılacak olan resimler, ses dosyaları gibi kaynaklar yüklenir. Ancak, bu örnekte bu fonksiyon boş bırakılmış. } create() { // Bu metod, oyun sahnesinin oluşturulduğu aşamadır. Oyunun başlatılması ve kullanıcı arayüzünün oluşturulması gibi işlemler burada gerçekleştirilir. Bu örnekte de bu fonksiyon boş bırakılmış. } update() { // Bu metod, oyun sahnesinin sürekli olarak güncellendiği aşamadır. Oyun mantığı, fizik hesaplamaları ve diğer dinamik güncellemeler bu fonksiyonda yer alabilir. Bu örnekte de bu fonksiyon boş bırakılmış. } }; const config = { type: Phaser.AUTO, width: 800, height: 600, physics: { default: 'arcade', arcade: { gravity: { y: 300 }, debug: false, }, }, scene: [Game] }; const game = new Phaser.Game(config); |
Oyuncu (Karakter) Tanımı
Şimdi gerçek bir oyun kodlamasına giriş yapmak için oyunda kullanmak üzere bir karaktere ihtiyacımız var.
Bu projenin GitHub deposunda bulunan ‘male.png’ adlı dosyayı alıp kullanacağız. Dosyanın içeriğinin bir kısmı aşağıdaki gibi. Karakterin her hareketi 80px/110px aralığına sıkıştırılmış durumda. İnternet üzerinde bulunan her oyuncu sprite nesnesi farklı boyutlarda kareler içerebiliyor. Bu nedenle 80px/110px, bir standart ölçü değildir. Kod tarafında bir oyuncu nesnesi oluşturduğumuzda, bu boyutları nasıl kullanacağımızı göreceğiz.
Preload Metodu Kullanımı
Şimdi ‘preload’ adlı fonksiyon içerisinde bir oyuncu nesnesi oluşturalım. Daha önce projenin ana dizinine eklediğimiz ‘male.png’ sprite nesnesi üzerinden oyuncu nesnesini oluşturacağız.
1 2 3 4 5 6 7 8 9 | class Game extends Phaser.Scene { player // <-- player nesnesini diğer lifecycle metodlarından erişebilmek için burada tanılmıyoruz. ... preload() { this.load.spritesheet('player', './male.png', { frameWidth: 80, frameHeight: 110 }); // <-- ve bu satırı tanımlayacağız } ... }; |
this.load.spritesheet
fonksiyonu, ‘player’ adlı bir sprite sheet yükler. Bu sprite sheet, “./male.png” dosyasından alınan görüntülerle oluşturulmuştur. frameWidth
ve frameHeight
ise her bir animasyon çerçevesinin genişlik ve yüksekliğini belirtir.
Create Metodu Kullanımı
Şimdi, oluşturduğumuz ‘player’ nesnesine fizik kuralları ve animasyonları tanımlamak için, create() metodunda işlem yapacağız.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | class Game extends Phaser.Scene { ... cursors // <-- Bu satırı ekleyeceğiz spaceKey // <-- Bu satırı ekleyeceğiz ... create() { this.player = this.physics.add.sprite(100, 300, 'player'); this.anims.create({ key: 'left', frames: this.anims.generateFrameNumbers('player', { start: 9, end: 10 }), frameRate: 10, repeat: -1, }); this.anims.create({ key: 'turn', frames: [ { key: 'player', frame: 0 } ], frameRate: 20, }); this.anims.create({ key: 'right', frames: this.anims.generateFrameNumbers('player', { start: 9, end: 10 }), frameRate: 10, repeat: -1, }); this.anims.create({ key: 'up', frames: [ { key: 'player', frame: 1 } ] , frameRate: 20, }) this.player.setCollideWorldBounds(true); this.cursors = this.input.keyboard.createCursorKeys(); this.spaceKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE); } }; |
Player Nesnesi Oluşturma:
1 | this.player = this.physics.add.sprite(100, 300, 'player'); |
Bu satırda, this.physics.add.sprite
fonksiyonu ile oyun sahnesine bir sprite (nesne) eklenir. Sprite, “player” adlı bir görüntüden (sprite sheet) oluşturulmuştur. Player nesnesinin oyun başladığındaki konumu (100, 300) koordinatlarında yer alır.
Animasyon Tanımları:
1 2 3 4 5 6 | this.anims.create({ key: 'left', frames: this.anims.generateFrameNumbers('player', { start: 9, end: 10 }), frameRate: 10, repeat: -1, }); |
Bu blok, “left” adlı animasyonu tanımlar. Bu animasyon, ‘player’ nesnesinin 9. ve 10. karelerini içerir. frameRate
animasyonun hızını belirtir ve repeat: -1
sonsuz döngü anlamına gelir.Diğer animasyon tanımları da benzer şekilde sağ, sol ve yukarı zıplama (up) animasyonları için yapılır.
Collision (Çarpışma) Ayarı:
1 | this.player.setCollideWorldBounds(true); |
Bu satır, player nesnesinin dünya sınırlarıyla çarpışmasını etkinleştirir. Yani, player nesnesi oyun sahnesi sınırlarına çarparsa, bu sınırlarda sabitlenir.
Klavye Kontrolleri:
1 2 | this.cursors = this.input.keyboard.createCursorKeys(); this.spaceKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE); |
Bu satırlar, oyun sahnesinde klavye tuşlarına erişimi sağlar. createCursorKeys
ile ok tuşlarına, addKey
ile SPACE tuşuna erişim sağlanır.
Özetle, create()
metodu kod parçacığı, bir oyuncu nesnesi oluşturur ve bu nesneye hareket animasyonları, çarpışma sınırları ve klavye kontrolleri ekler. Bu tip bir kod, bir karakterin temel hareketleri ve animasyonları için bir başlangıç noktasıdır.
Update Metodu Kullanımı
Şimdi, oyuncu için tanımlanan fizik kuralları ve animasyonlar, update()
metodu içinde belirlenen şartlara göre çalıştırılacak son aşamaya geçiyoruz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | class Game extends Phaser.Scene { ... update() { if (this.player.body.velocity.x < 0) { this.player.flipX = true; // Sola hareket ederken görüntüyü aynala } else if (this.player.body.velocity.x > 0) { this.player.flipX = false; // Sağa hareket ederken görüntüyü eski haline getir } if (this.cursors.left.isDown) { this.player.setVelocityX(-160); this.player.anims.play('left', true); } else if (this.cursors.right.isDown) { this.player.setVelocityX(160); this.player.anims.play('right', true); } else { this.player.setVelocityX(0); this.player.anims.play('turn'); } if (this.player.body.blocked.down && this.spaceKey.isDown || this.player.body.blocked.down && this.cursors.up.isDown) { this.player.setVelocityY(-330); this.player.anims.play('up', true); } } }; |
Bu kod parçacığı, oyuncu karakterinin hareketini ve animasyonlarını kontrol etmek için kullanılan bir bölümü içerir. Aşağıda her bir bölümü açıklıyorum:
Yön ve Animasyon Kontrolü:
1 2 3 4 5 | if (this.player.body.velocity.x < 0) { this.player.flipX = true; // Sola hareket ederken görüntüyü aynala } else if (this.player.body.velocity.x > 0) { this.player.flipX = false; // Sağa hareket ederken görüntüyü eski haline getir } |
Bu blok, oyuncu karakterinin x eksenindeki hızına (velocity) göre görüntüyü aynalama işlemi yapar. Eğer oyuncu sola hareket ediyorsa (velocity.x
negatifse), görüntüyü aynalar (flipX=true). Eğer oyuncu sağa hareket ediyorsa (velocity.x
pozitifse), görüntüyü eski haline getirir (flipX=false).
Klavye Tuşlarına Göre Hareket ve Animasyon Kontrolü:
1 2 3 4 5 6 7 8 9 10 11 12 | if (this.cursors.left.isDown) { this.player.setVelocityX(-160); this.player.anims.play('left', true); } else if (this.cursors.right.isDown) { this.player.setVelocityX(160); this.player.anims.play('right', true); } else { this.player.setVelocityX(0); this.player.anims.play('turn'); } |
Bu blok, klavye tuşlarına göre oyuncu karakterinin hareketini ve animasyonlarını kontrol eder. Sol ok tuşu basılırsa, oyuncu sola hareket eder ve “left” animasyonu oynatılır. Sağ ok tuşu basılırsa, oyuncu sağa hareket eder ve “right” animasyonu oynatılır. Hiçbir ok tuşu basılı değilse, oyuncunun hızı sıfırlanır ve “turn” animasyonu oynatılır.
1 2 3 4 | if (this.player.body.blocked.down && this.spaceKey.isDown || this.player.body.blocked.down && this.cursors.up.isDown) { this.player.setVelocityY(-330); this.player.anims.play('up', true); } |
Bu blok, oyuncu karakterinin zıplama kontrolünü sağlar. this.player.body.blocked.down
ifadesi oyuncunun yere temas edip etmediğini kontrol eder. Eğer oyuncu yere temas ediyorsa (blocked.down
), ve SPACE tuşu ya da yukarı ok tuşu (this.spaceKey.isDown || this.cursors.up.isDown
) basıldıysa, oyuncuya yukarı yönlü bir hız atanır ve “up” animasyonu oynatılır.
Özetle, update()
metodu kod parçacığı, oyuncu karakterinin klavye girişlerine tepki vermesini, hareket etmesini ve animasyonlarını oynamasını sağlayan temel kontrolleri içerir.
Demo
Proje
Projeye github üzerinden erişmek için buraya tıklayınız.
Mutlu Son
Tebrikler Seviye Atladınız!
Gülümseyen karakterimizle dolu bir sona ulaştık. Artık oyunumuz, neşeli bir şekilde sağa sola dönebilen ve neşeli sıçramalar yapan bir karaktere ev sahipliği yapıyor 😍 🚀
📚 Phaser 3 Kaynakları
📚 Benzer Makaleler
✍ Lütfen olumlu-olumsuz tüm görüşlerinizi bana yorum yada mail yolu ile iletmeyi ihmal etmeyin.
🔗 Sosyal medya kanallarından makaleyi paylaşarak destek olursanız çok sevinirim.
👋 Bir sonraki makalede görüşmek dileğiyle.