4.7 KiB
4.7 KiB
AGENTS.md
Git-Regeln
- Git-Commits nur auf explizite Anforderung des Users. Niemals eigenständig committen.
- Vor einem Commit:
git status,git diffundgit log --oneline -10prüfen; nur beabsichtigte Dateien stagen, keine Secrets. - Commit-Message kurz und im Stil des Repos (bisher englisch, imperative).
Build & Verifikation
cd web
npx tsc --noEmit # Typcheck (Pflicht nach Änderungen)
npm run build # tsc + vite build → web/dist
npm run dev # Dev-Server mit HMR
- Stack: Three.js 0.170 + TypeScript + Vite. Keine weiteren Laufzeit-Dependencies (kein Postprocessing verfügbar — Screen-Effekte als CSS-Overlays).
Makefile:make web/make dev/make build(Container-Build via Podman).- UI-Sprache: Deutsch (Skill-Namen, Level-up-Karten); Code-Kommentare bisher gemischt, Git-Messages englisch.
Architektur (web/src)
| Datei | Inhalt |
|---|---|
Game.ts |
Zentrale Klasse: State-Machine, Render-Loop (animate()), Input, UI-Verdrahtung, Spawning, Partikel-/Effekt-Arrays (bloodParticles, traps, gasClouds, slashEffects, projectiles), Hotbar |
Player.ts |
Blob-Spieler: Movement, Sprung, damage()/heal() (Schild-Absorption), Stats (applySkillSystem), Hurt-Feedback (Flash + Blut via game.onPlayerHurt) |
Enemy.ts |
Abstrakte Basis: body (THREE.Group), takeDamage (Sound + XP/Lifesteal via game.onDamageDealt), Fade-Death, Felder knockback, rootTime |
Skills.ts |
Alle Skill-Definitionen (SKILLS-Array: id, name, type, maxLevel, describe) + Level-Wertetabellen (z. B. auraRadius(level)). SkillSystem = XP/Level/Angebote. HOTBAR_SKILLS = aktive Skills in Erwerbs-Reihenfolge |
SkillIcons.ts |
SVG-Icons (64×64, Template-Strings) für die Level-up-Karten |
Weapon.ts |
Basis für aktive Skills: cooldown1-3 + reduceCooldowns() |
Sword.ts / Staff.ts |
Linksklick-Schwert (Bogen-Trefferzone via SwordTrail.ts), Rechtsklick-Feuerball + Teleport |
ChainLightning.ts |
Kettenblitz (Q-Slot) |
Trapper.ts |
Falle (skill1) + Gaswolke (skill2) |
Aura.ts / Boomerang.ts |
Passive Skills, lesen Level live aus game.skillSystem |
Trap.ts / GasCloud.ts |
Platzierbare Effekte; update(dt, game): boolean (false = entfernen), dispose() |
*Enemy*.ts (Spider, Ghost, Frog, Bat, BeeSwarm, Slime, Brute/Boss, Crab, Turret) |
Prozedurale Gegner-Modelle; je update(dt, game) |
SoundManager.ts |
Vorab geladene .ogg-Buffer (playSound(name, volume)); Sounds: damage, spawn, fireball, explosion, teleport, gameover, sword_hit1, spiderwalking |
MeshLoader.ts |
loadGLB(name) → web/public/models/*.glb; Texturen in web/public/textures/ |
Wichtige Konventionen & Fallstricke
- Blickrichtung = lokale +Z: Three.js
Object3D.lookAtrichtet +Z zum Ziel aus. Augen/Gesichter von Gegnern und Spieler müssen auf +Z liegen (sonst laufen sie rückwärts — war schon mal ein Bug bei Frosch/Golem/Brute/Slime/Bat/Crab). - UI-Overlays: Alle Panels liegen absolut in
#ui-overlay(pointer-events: none). Versteckte Panels brauchen drei Dinge:opacity: 0+pointerEvents: none+visibility: hidden. Achtung:.menu-button { pointer-events: auto }übersteuertpointer-events: nonedes Parents — ohnevisibility: hiddensind unsichtbare Buttons klickbar (verursachte „stille Neustarts" mitten im Spiel). Neues Panel → immervisibilitymitsetzen. - State-Machine:
menu | playing | levelup | gameover+ Flagpaused(ESC).animate()rendert bei Pause nur UI.showMenu()hat einen Guard (nur aus menu/gameover/pause). - Hotbar: Aktive Skills (Kettenblitz, Teleport, Falle, Gaswolke) werden beim Erwerb auf Q, E, 1, 2, 3, 4 verteilt (
HOTBAR_KEY_CODES). Dispatch übertriggerHotbarSkill(). Cooldown-Labels zeigen Taste + Name (syncSkillVisibility). - Skill-Arten: Aktive =
Weapon-Subklassen mit Cooldowns (UI-Balken inindex.html, Update inupdateUI). Passive = Stats inPlayer.applySkillSystemODER Game-seitige Objekte (Aura/Boomerang), die insyncSkillVisibilityerzeugt/zersstört und im Loop geupdated werden. - Effekt-Lifecycle: Neue Effekte mit eigenem
update(dt, game)-Rückgabewert (false = aufräumen) unddispose(); inGame.resetWorld()ALLES aufräumen (sonst Geister-Objekte nach „Nochmal spielen"). - Gegner-Festhalten:
enemy.rootTime > 0friertenemy.update()ein (sieheGame.updateEnemies) — so funktioniert die Falle, ohne jede Gegner-Klasse anzufassen. - Kontaktschaden (Gegner berührt Spieler) läuft in
Game.ts(Close-Encounter-Loop) mitcontactDps * dt; Dornen-Skill ebendort als Gegenschlag. playSounderzeugt pro Aufruf einen AudioBufferSourceNode — bei hochfrequenten Effekten (Aura-Ticks, Bumerang-Hits) ggf. throtteln.