14 puan yazan cybrshin 2026-01-04 | 9 yorum | WhatsApp'ta paylaş

Normalde claude code ve Cursor kullanıyordum ama geçen yıl işten ayrıldıktan sonra kasımdan itibaren antigravity’ye geçip her gün çeşitli oyuncak web servis projeleri yapıyordum. Derken aniden 3 gün önce (1/2) bir tower defense oyunu yapmayı denemek istedim.
Aslında web frontend geliştiricisiyim; uygulama olarak paketlemekle uğraşmak istemedim, sadece masaüstü tarayıcı ortamında çalışsın dedim. Canvas tabanlı davranışlar ve görsel dosya üretimi de çok zaman alacak gibi geldiği için, emojileri mümkün olduğunca fazla kullanalım fikriyle başladım.

Bir günde bitirmeyi planlamıştım ama yaparken eğlenceli gelince, şunu bunu düzeltip ekledikçe 3 gün sürmüş oldu. hıçkırık

Temel teknoloji yığını şöyle:

  • Frontend: Next.js 14+ (App Router), TypeScript, HTML5 Canvas
  • Backend: FastAPI, Python 3.9+, Pydantic
  • Database: Supabase (PostgreSQL)
  • Deployment: Vercel

Çeşitli düzenlemelerin ardından, oyun mantığı nihayet şu şekilde belirlendi.

Reklam

1. Kule saldırı gücü

Kuleler Merge ile seviye atladıkça menzil (Range) 10 artıyor, ancak saldırı gücü verimliliği denge için 1.8 kat olarak ayarlanıyor.

  • Formül: Damage = floor(BaseDamage * (1.8 ^ (Level - 1)))
    • Lv 1: 10
    • Lv 2: 18
    • Lv 3: 32
    • Lv 4: 57

2. Düşman çıkış düzeni (Wave Logic)

Tekdüzeliği azaltmak için çeşitli wave düzenleri uygulanıyor.

  • Normal wave (Horde Mix): Mevcut tier düşmanlar (%70) ile bir önceki tier düşmanlar (%30) karışık olarak çıkıyor.
  • Boss wave (Every 6th): Boss olarak çağın en güçlü düşmanından 1 tane çıkıyor ve etrafında minyonlar eşlik ediyor.
    • Boss wave’de düşman sayısı: Wave / 6 (6. wave’de 1 tane, 12. wave’de 2 tane...)
    Reklam

4. Altın ödülü (Active)

Düşmanları öldürdüğünüzde veya wave’i temizlediğinizde altın kazanıyorsunuz.

ps. Mobil ortamı özellikle düşünmedim. Touch event ekledim; Fold ya da tabletlerde iyi çalışıyor ama küçük ekranlar için pek düşünmedim~

ps. İyileştirme noktaları ve bug’ları yorumlarda bildirirseniz, fırsat buldukça yansıtırım.

https://tower.dsp.ai.kr/

9 yorum

 
roxie 2026-02-27

Hayır, bu hiç mantıklı değil... 700 wave mi...............???

 
cybrshin 2026-02-28

Mümkün haha

 
wancomplete 2026-01-07

Ben de yakın zamanda oyun yapmayı denerken https://verse8.io kullandım; görselleri ve hatta 2D sprite animasyonlarını bile doğrudan oluşturduğu için asset işine zaman harcamadan sadece oyun mantığına odaklanabildim. Üstelik platform üzerinden hemen dağıtıma da çıkılabildiği için ayrıca hosting düşünmek gerekmiyordu; gerçekten çok rahattı.

 
huiya 2026-01-06

Eğlenceli. Emojilerin aktif şekilde kullanılmış olması bana oldukça yeni hissettirdi.
Ben tower defense oyunlarını çok sık oynamadığım için bunun doğru bir görüş olup olmadığından emin değilim ama wave zamanı ile hazırlık zamanının ayrılmamış olması, wave geldiği anda bile kulelerin yerini değiştirebilmeyi biraz garip hissettiriyor.
Uç bir durumda, konumu sürekli değiştirerek her an saldırmalarını sağlamak mümkün olduğu için menzilin anlamsızlaştığını düşündürüyor.

 
cybrshin 2026-01-06

Keyifle oynadığınız için teşekkür ederim.
Ben de yaparken konumu değiştirmenin tuhaf olduğunu hissetmiştim, ama bunun bir bakıma bu oyunun güçlü yanı, dinamik ve kontrol edilebilir bir unsur olabileceğini düşündüğüm için olduğu gibi bıraktım.
Aslında hızlı taşımak istiyorsanız kuleleri merge etmeden bunu yapmak gerçekten çok zor.
Taşımaya ek bir ceza koyup koymamak gibi oyun dengesi konusu sanırım üzerinde düşünmeye devam edilmesi gereken bir nokta.

 
huiya 2026-01-07

Ah, demek ki hepsini zaten düşünmüşsünüz. Ben yeterince kapsamlı düşünememişim.

 
cybrshin 2026-01-07

Hayır. Görüşünüz için teşekkür ederim.

 
waylake 2026-01-04

Merhaba, keyifle oynadım; güvenlikle ilgili geri bildirim bırakıyorum.

  • Şu anda HMAC secret'ı (imzalama anahtarı) frontend'de açığa çıkmış durumda
    • Frontend'den doğrudan gold, wave, lives, towers değerleri değiştirilebiliyor

Vercel ve Supabase ücret planlarıyla ilgili bir sorun olabilir diye haber vermek istedim.

const state = {  
  towers: [],    
  gold: 9999,  
  wave: 1,       
  lives: 1       
};  
  
const state_raw = JSON.stringify(state);  
const user_id = "11111";  
const secret = "11111";  
  
(async () => {  
  const key = await crypto.subtle.importKey(  
    "raw",  
    new TextEncoder().encode(secret),  
    { name: "HMAC", hash: "SHA-256" },  
    false,  
    ["sign"]  
  );  
  const signatureBuffer = await crypto.subtle.sign(  
    "HMAC",  
    key,  
    new TextEncoder().encode(state_raw)  
  );  
  const signature = Array.from(new Uint8Array(signatureBuffer))  
    .map(b => b.toString(16).padStart(2, "0")).join("");  
    
  fetch("https://tower.dsp.ai.kr/api/sync";, {  
    method: "POST",  
    headers: {  
      "Content-Type": "application/json",  
      "Accept": "*/*"  
    },  
    body: JSON.stringify({  
      user_id,  
      state_raw,  
      signature  
    })  
  })  
  .then(res => res.text())  
  .then(console.log)  
  .catch(console.error);  
})();  
  
 
cybrshin 2026-01-04

Ah, teşekkürler~