← Tüm projeler

Çok oyunculu 3B web oyunu

MoonLite

MoonLite ücretsiz, çok oyunculu, 3B bir "gece parkı": yabancılar ortak bir zaman çizelgesinde birlikte müzik yapar, açık havada film izler, go-kart yarışır, bowling ve satranç oynar. Netcode'dan ses motoruna, sunuculardan hukuki metinlere kadar hepsini tek başıma geliştirdim ve ilk commit'ten halka açık yayına yaklaşık üç haftada çıkardım.

Rol
Tek başıma: tasarım, yazılım, ses, altyapı, güvenlik
Zaman
Haziran 2026 – günümüz · Temmuz 2026'dan beri yayında
Platform
Her modern tarayıcı (Windows, macOS, Linux, iOS, Android) · Electron + Steam sürümü

Problem

Kalabalık 3B odalar genelde aynı şekilde çöker: bir oyuncu hareket eder, sunucu herkese söyler, herkes hareket eder, sunucu yine herkese söyler. Olay başına dağıtım, oda büyüklüğünün karesiyle büyür.

Daha kötüsü, kalabalığın trafiği asla aksamaması gereken tek şeyle aynı kanalı paylaşır: müzik. Bir emoji fırtınası bir mikser komutunu geciktirebiliyorsa ürün bozuktur. Üstelik hepsinin bağımsız bir stüdyonun karşılayabileceği donanımda çalışması gerekiyordu.

Önemli kararlar

  1. 01

    Asla aynı kuyruğu paylaşmayan üç trafik düzlemi

    Kaybolmaması gereken durum için güvenilir bir kontrol düzlemi, kayıplı ikili bir konum düzlemi (8 baytlık konum paketleri, 15 Hz sunucu tick'i, ilgi alanı ayıklama ve delta snapshot'lar) ve toplu gönderilen bir tepki düzlemi. Sıkışma anında kayıplı trafik düşürülür, kontrol trafiği asla. Sunucunun olay başına işi, istemcilerin ne kadar yüklendiğine değil tick hızına bağlı.

  2. 02

    Ağ üzerinden hiç kare göndermeyen mini oyunlar

    On iki etkinliğin tamamı (satranç, bilardo, bowling, pinball, go-kart, lunapark araçları, senkron sinema...) tarayıcının ve sunucunun paylaştığı saf, determinist step(durum, girdiler) fonksiyonları. Ağda sadece zaman damgalı girdiler gidiyor; sonradan katılan birinin tüm durumu 54 bayta kadar iniyor. Ek kazanç: simülasyonlar bir kütüphane gibi test ediliyor ve testler gerçek hataları yakaladı.

  3. 03

    Medya baytları sunucuya hiç uğramıyor

    Ses kanalları içerik adresli (SHA-256): önce yerel IndexedDB önbelleğinden, sonra çıkış ücreti olmayan Cloudflare R2'den geliyor. Ortak bir transport saati tüm istemcilerde çalmayı hizalı tutuyor. Bunun için önce tam bir WebRTC eşler arası katman yazdım, sonra sildim: mobil ağlarda NAT aşma nadiren çalışıyordu, oyuncuların IP adreslerini sızdırıyordu ve R2 zaten maliyeti sıfırlamıştı.

  4. 04

    Sıfırdan bir tarayıcı ses motoru

    Ableton tarzı otomatik warp'lı çok kanallı mikser, Web Worker'larda perde koruyan WSOLA zaman esnetme, efekt hatlı bir AudioWorklet wavetable synth ve dalga formu klipleri, piyano rulosu ve ortak düzenleme içeren beat ızgaralı bir DAW.

  5. 05

    Üretim, güvenlik ve operasyon uçtan uca

    Cloudflare Pages ve ~68 rotalı bir Worker API (D1, KV, R2), drain tabanlı kademeli dağıtım ve istemci otomatik güncellemesi olan çoklu VPS relay filosu, Google OAuth, CSP/HSTS, Cloudflare Access arkasında denetim kayıtlı yönetim paneli ve hibrit post-kuantum şemayla (X25519 + ML-KEM-768) uçtan uca şifreli mesajlaşma. Tehdit modelini ve EN/TR GDPR–KVKK hukuki metinlerini de ben yazdım.

Sonuçlar

480
eşzamanlı oyuncu, aylık 4 €'luk sunucuda
~2 ms
tam yükte en kötü tick (bütçe: 66 ms)
0
yük testlerinde kopan bağlantı
~53k
satır strict TypeScript, tek başıma
418
otomatik test
900 → 12
sahne toplulaştırmasıyla draw call

Öğrendiklerim

  • Hangi trafiğin düşürülebileceğine, hangisinin asla düşürülemeyeceğine karar ver ve onlara ayrı borular ver.
  • Simülasyonu saf bir fonksiyona koy ve bir kütüphane gibi test et. Netcode hatalarının çoğu, üstüne gecikme binmiş simülasyon hatalarıdır.
  • Daha büyük bir sunucu almadan önce gerçek makinede, gerçek yoldan ölç. Benim "ölçek" sorunum bir oda limiti ayarı çıktı.
  • En gurur duyduğun parçayı silmeye hazır ol. P2P katmanını kaldırmak ürünü daha iyi yaptı.

Çok oyunculu 3B web oyunu

MoonLite

MoonLite kapak görseli: yıldızlı gökyüzünde dolunay

1 / 3

İletişim

Aklınızda bir proje ya da pozisyon mu var?

Freelance projelere ve tam zamanlı rollere açığım, uzaktan ya da İstanbul'da. İhtiyacınızı birkaç cümleyle yazın; genelde bir gün içinde dönerim.