14 Punkte von cybrshin 2026-01-04 | 9 Kommentare | Auf WhatsApp teilen

Ursprünglich habe ich claude code und Cursor verwendet, bin aber nach meinem Jobwechsel im vergangenen Jahr seit November auf antigravity umgestiegen und habe jeden Tag verschiedene kleine Toy-Webservice-Projekte gebaut. Vor plötzlich 3 Tagen (1/2) bekam ich dann Lust, einmal ein Tower-Defense-Spiel zu entwickeln.
Da ich ursprünglich Web-Frontend-Entwickler bin, war es mir zu umständlich, das Ganze noch als App zu verpacken. Deshalb sollte es einfach nur in einer Desktop-Browser-Umgebung laufen. Außerdem schien mir Canvas-basierte Abläufe und die Arbeit mit Bilddateien zu viel Zeit zu kosten, also startete ich mit der Idee, Emojis so weit wie möglich zu nutzen.

Eigentlich wollte ich an nur einem Tag fertig werden, aber beim Entwickeln hat es so viel Spaß gemacht, dass ich hier und da Dinge geändert und ergänzt habe — und am Ende wurden doch 3 Tage daraus. T_T

Der grundlegende Tech-Stack sieht wie folgt aus.

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

Nach verschiedenen Anpassungen wurde die Spiel-Logik am Ende wie folgt festgelegt.

1. Angriffskraft der Türme

Wenn ein Turm durch Merge im Level steigt, erhöht sich seine Reichweite (Range) jedes Mal um 10, die Effizienz der Angriffskraft wird jedoch aus Balance-Gründen auf das 1,8-Fache angepasst.

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

2. Gegner-Erscheinungsmuster (Wave Logic)

Um Monotonie zu vermeiden, werden verschiedene Wave-Muster angewendet.

  • Normale Waves (Horde Mix): Gegner des aktuellen Tiers (70 %) und des vorherigen Tiers (30 %) erscheinen gemischt.
  • Boss-Waves (Every 6th): Als Boss erscheint 1 stärkster Gegner des jeweiligen Zeitalters, eskortiert von kleinen Begleitgegnern.
    • Anzahl der Gegner in Boss-Waves: Wave / 6 (1 Gegner in Wave 6, 2 Gegner in Wave 12 ...)

4. Gold-Belohnung (Active)

Für das Besiegen von Gegnern oder das Abschließen einer Wave erhält man Gold.

PS: Die mobile Umgebung wurde nicht besonders berücksichtigt. Touch-Events habe ich zwar ergänzt, und auf Fold-Geräten oder Tablets funktioniert es gut, aber kleine Bildschirme habe ich kaum bedacht.

PS: Wenn ihr Verbesserungen oder Bugs in den Kommentaren hinterlasst, werde ich sie einarbeiten, sobald ich Zeit habe.

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

9 Kommentare

 
wancomplete 2026-01-07

Ich habe neulich auch beim Entwickeln eines Spiels https://verse8.io ausprobiert. Dort werden sogar Bilder und 2D-Sprite-Animationen direkt erstellt, sodass ich keine Zeit für die Asset-Erstellung aufwenden musste und mich nur auf die Spiel-Logik konzentrieren konnte. Außerdem konnte ich direkt auf der Plattform deployen, sodass ich mich nicht extra um Hosting kümmern musste, was wirklich sehr praktisch war.

 
huiya 2026-01-06

Macht Spaß. Dass Emojis aktiv eingesetzt werden, fühlt sich ziemlich neu an.
Ich spiele Tower-Defense-Spiele nicht besonders oft, daher weiß ich nicht, ob das wirklich ein treffender Einwand ist, aber es wirkt seltsam, dass Wave-Zeit und Vorbereitungszeit nicht getrennt sind und man deshalb selbst in dem Moment, in dem eine Wave kommt, die Position der Türme noch verändern kann.
Im Extremfall kann man die Position ständig wechseln und so in jedem Moment angreifen lassen, wodurch sich die Reichweite bedeutungslos anfühlt.

 
cybrshin 2026-01-06

Vielen Dank, dass ihr so viel Spaß damit hattet.
Auch ich fand beim Entwickeln, dass es etwas seltsam wirkt, die Position zu verschieben, aber ich hatte den Eindruck, dass genau das zugleich eine Stärke dieses Spiels und ein dynamisches, steuerbares Element sein kann, deshalb habe ich es so belassen.
Tatsächlich ist es wirklich schwer, schnell umzuziehen, wenn man die Türme nicht merged.
Ob man zusätzlich noch eine Strafe fürs Verschieben einführen sollte und Ähnliches scheint ein Punkt zu sein, über den ich beim Game-Balancing weiter nachdenken muss.

 
huiya 2026-01-07

Ach, Sie haben das also schon alles bedacht. Da war ich zu kurzsichtig.

 
cybrshin 2026-01-07

Nein. Vielen Dank für Ihre Meinung.

 
waylake 2026-01-04

Hallo, ich habe es mit viel Spaß gespielt. Ich gebe Ihnen ein sicherheitsbezogenes Feedback.

  • Der aktuelle HMAC-Secret (Signaturschlüssel) ist im Frontend offengelegt.
    • Im Frontend können gold, wave, lives und towers direkt verändert werden.

Ich informiere Sie darüber, weil es möglicherweise Probleme mit den Tarifen von Vercel und Supabase geben könnte.

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, danke~

 
roxie 2026-02-27

Nein, das ergibt doch keinen Sinn ... 700 Waves ...???

 
cybrshin 2026-02-28

Das ist möglich, haha.