BareEngine: C++ ile Sıfırdan Oyun Motoru Yazmak
Her şey 10 yıl önce başladı. Metin2 private server'lar, Knight Online emülatörleri, oyun sunucu toplulukları... 11 yaşında bir çocuk, bir oyunun nasıl çalıştığını anlamaya çalışıyordu. Packet'ları sniff ediyor, server emülatörleri yazıyor, C++ öğreniyordu.
O çocuk bendim.
Ve şimdi, 21 yaşında, aynı çocuğun hayalini gerçekleştiriyorum: BareEngine — kendi oyun motorum.
Neden kendi oyun motorun?
Hazır motorlar var: Unity, Unreal, Godot. Neden sıfırdan bir tane daha?
Çünkü benim istediğim şeyi yapmıyorlar.
Benim istediğim şey şu: bir editör açayım, birkaç model yerleştireyim, birkaç script yazayım, ve oyun sunucusu da otomatik oluşsun. Editör ve sunucu aynı toolchain'in parçası olsun. Unity'de bunu yapmak için Mirror, FishNet, Netcode for GameObjects gibi üçüncü parti kütüphaneler gerek. Ben bunu native istiyorum.
Ayrıca, Metin2 ve Knight Online gibi oyunların kendine has bir "hissi" var. Kamera açısı, karakter kontrolü, combat sistemi, UI — bunların hepsi belli bir tarzda. Bu tarzı modern engine'lerde yakalamak zor. Çünkü onlar FPS veya açık dünya RPG'leri için optimize edilmiş.
Ben Metin2 tarzı MMORPG'ler için optimize edilmiş bir motor istiyorum. O yüzden kendim yazıyorum.
Mimari
BareEngine üç ana bileşenden oluşuyor:
┌──────────────────────────────────────────┐
│ BareEditor (GUI) │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ │
│ │ World │ │ Asset │ │ Script │ │
│ │ Editor │ │ Browser │ │ Editor │ │
│ └─────────┘ └──────────┘ └──────────┘ │
├──────────────────────────────────────────┤
│ BareEngine (Core) │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ │
│ │Renderer │ │ Physics │ │ Audio │ │
│ │(OpenGL) │ │(Bullet) │ │(OpenAL) │ │
│ └─────────┘ └──────────┘ └──────────┘ │
├──────────────────────────────────────────┤
│ BareServer (Sunucu) │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ │
│ │Network │ │ Game │ │ DB │ │
│ │(ENet) │ │ Logic │ │(SQLite) │ │
│ └─────────┘ └──────────┘ └──────────┘ │
└──────────────────────────────────────────┘
BareEditor: ImGui tabanlı masaüstü editör. World editörü (terrain, obje yerleştirme), asset browser (model, texture, ses), script editörü (Lua entegrasyonu). Editörün kendisi editör öncelikli — yani ürün editör, oyun çıktısı yan ürün.
BareEngine (Core): Renderer (OpenGL), fizik motoru (Bullet Physics), ses (OpenAL). Hepsi C++ ile, hepsi native.
BareServer: Oyuncuların bağlandığı sunucu. ENet (reliable UDP), game logic (C++), veritabanı (SQLite). Sunucu, editörden export edilen dünya dosyasını okuyor.
Editör-first felsefesi
Çoğu oyun motoru "engine-first"tir. Önce motoru yazarsın, sonra editörü eklersin. Ben tersini yapıyorum.
BareEngine'de editör, motorun bir arayüzü değil — editör ürünün kendisi. Oyun yapımcısı editörü açar, dünyasını inşa eder, "Build"e basar, oyun çıkar. Tıpkı RPG Maker gibi. Ama RPG Maker'dan farklı olarak:
- Multiplayer native (MMORPG'ler için)
- Performans odaklı (C++, OpenGL)
- Script edilebilir (Lua)
- Açık kaynak
Hedef kitle: Metin2, Knight Online, Silkroad tarzı oyunların private server toplulukları. Bu topluluklar yıllardır emülatörlerle, reverse-engine edilmiş server dosyalarıyla uğraşıyor. Onlara "kendi oyununu yap" diyen bir araç vermek istiyorum.
Teknik kararlar
Neden ImGui?
Editör için ImGui (Dear ImGui) kullanıyorum. Qt değil, wxWidgets değil, ImGui.
Sebebi: ImGui immediate mode. Her frame GUI'yi sıfırdan çiziyorsun. Bu, oyun motoru editörleri için mükemmel çünkü:
- Render state ile GUI state aynı yerde
- Debugging kolay (her şey o an hesaplanıyor)
- Performanslı (gereksiz state yok)
- Portable (OpenGL, Vulkan, DirectX hepsinde çalışıyor)
Dezavantajı: "güzel" görünmüyor. Varsayılan ImGui teması... işlevsel diyelim. Ama bunu dert etmiyorum. Editör güzel görünmek zorunda değil, işlevsel olmak zorunda.
Neden Bullet Physics?
PhysX değil, Havok değil, Bullet. Sebebi: açık kaynak ve MMORPG'ler için yeterli. MMORPG fiziği, FPS fiziği gibi değildir. Ragdoll yok, destrucible environment yok. Sadece collision detection, basit rigid body, karakter kontrolü. Bullet bunların hepsini fazlasıyla yapıyor.
Neden ENet?
MMORPG sunucuları için TCP değil, UDP tabanlı bir protokol lazım. Hareket input'ları, combat event'leri — bunların hepsi düşük latency gerektiriyor. TCP'nin head-of-line blocking'i burada ölümcül.
ENet, reliable UDP üzerine inşa edilmiş hafif bir kütüphane. Sıralı paket teslimatı, fragmentation, throttling — hepsi var. Ve en önemlisi: basit. Sadece bir .c dosyası. Bağımlılık yok.
Neden Lua?
C++ ile oyun mantığı yazmak... mümkün ama pratik değil. Her değişiklikte recompile. Lua ile yazınca:
- Hot-reload (sunucuyu kapatmadan script güncelle)
- Mod yapımcıları için erişilebilir
- C++'tan daha güvenli (crash yapsa bile sunucu çökmez)
Lua bindings için Sol3 kullanıyorum. C++ ve Lua arasındaki köprüyü birkaç satırda kuruyor.
Zorluklar
1. Editor-state senkronizasyonu. Editörde bir objeyi sürüklediğinizde, bu değişikliğin renderer'a, physics engine'e, network layer'a yansıması gerekiyor. Undo/redo yapınca hepsi geri alınmalı. Bu, command pattern ile çözülüyor ama implementasyonu detaylı.
2. Multiplayer senkronizasyonu. Bir oyuncu hareket ettiğinde, bu hareketin diğer oyunculara iletilmesi gerekiyor. Ama her hareketi gönderirseniz bant genişliği patlar. Client-side prediction + server reconciliation yapmanız gerek. Bu, FPS oyunlar için çözülmüş bir problem ama MMORPG'lerde ölçek farklı: yüzlerce oyuncu, binlerce entity.
3. Metin2 format uyumluluğu. Metin2'nin dosya formatları (.gr2 modeller, .dds texture'lar, .msm animasyonlar) dokümante edilmemiş. Reverse-engineering gerekiyor. Bu, zamanımın büyük kısmını alan kısım.
4. Cross-platform. Windows'ta geliştiriyorum ama Linux sunucularda çalışacak. OpenGL, ENet, Bullet — hepsi cross-platform. Ama build sistemi (CMake), dependency yönetimi (vcpkg), CI/CD — bunların hepsi platform başına özel konfigürasyon istiyor.
Şu anki durum
Proje çok erken aşamada. Şu an çalışanlar:
- OpenGL renderer (basic meshes, texture'lar)
- ImGui editör arayüzü (world outliner, property editor)
- ENet networking (bağlantı, mesajlaşma)
- Temel Lua scripting (
onPlayerJoin,onChatMessage)
Henüz çalışmayanlar (bir sonraki milestone):
- Asset import pipeline (
.fbx,.gltf) - Physics (collision detection)
- Animation system
- Database persistence (karakter kaydetme)
- Metin2 format parser'ları
Bu proje neden önemli?
BareEngine ticari bir ürün değil. Bir tutku projesi. 11 yaşındaki halime bir mektup gibi.
O çocuk, oyunların nasıl çalıştığını anlamak için packet'ları sniff ediyordu. Şimdi o çocuğa "işte böyle çalışıyor" diyebilecek bir şey inşa ediyorum. Açık kaynak. Herkes görsün, öğrensin diye.
Ayrıca, Türkiye'de oyun geliştirme büyüyor. Ama çoğu stüdyo Unity/Unreal kullanıyor. Düşük seviyede, "motor nasıl çalışır"ı anlayan az. BareEngine, bu bilgiyi açık kaynakla yaymanın bir yolu.
Deneyin
git clone https://github.com/Tuntii/BareEngine
cd BareEngine
# Build (CMake + vcpkg):
cmake -B build -S . --toolchain ...
cmake --build build --config Release
# Run editor:
./build/Release/BareEditor.exe
Henüz "oyun yapılabilir" durumda değil. Ama yolda. Her commit, 11 yaşındaki halime bir adım daha yaklaştırıyor.
Bu, serinin son yazısı değil. Sırada Mondie (agritech), alexander-storage (self-hosted S3), IntentScript (LLM task runner) ve daha fazlası var. Takipte kalın.