feat: Add audio assets, UI escape room polish, requirements, and INSTALL.md

This commit is contained in:
Maxi
2026-10-29 08:51:59 +01:00
parent c07c0e10b9
commit 3d30d0812a
17 changed files with 1367 additions and 180 deletions
+4 -3
View File
@@ -7,11 +7,12 @@
<link rel="icon" href="/static/favicon.ico">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Caveat:wght@500;700&family=MedievalSharp&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/static/css/escape.css?v=5.0">
<link href="https://fonts.googleapis.com/css2?family=Caveat:wght@500;700&family=Marck+Script&family=MedievalSharp&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/static/css/escape.css?v=6.0">
{% block head %}{% endblock %}
</head>
<body>
<audio id="bgm" src="/static/audio/music.mp3" loop preload="auto"></audio>
<!-- Minimalist & Mobile-Friendly Header -->
<header class="site-header">
<div class="header-inner">
@@ -282,7 +283,7 @@
</footer>
<script src="/static/js/audio.js?v=5.0"></script>
<script src="/static/js/inventory.js?v=5.0"></script>
<script src="/static/js/inventory.js?v=6.0"></script>
<script>
async function resetEscapeProgress() {
if (confirm("Möchtest du deinen Escape-Fortschritt und dein Inventar wirklich zurücksetzen?")) {
+114 -31
View File
@@ -39,13 +39,16 @@
<div class="brew-container">
<!-- Recipe Instruction Scroll -->
<div class="recipe-book">
<span id="stepBadge" class="recipe-step-badge">Schritt 1: Zutaten zugeben</span>
<span id="stepBadge" class="recipe-step-badge">Schritt 1: Zutaten dosieren</span>
<h3 id="stepInstruction" style="color: var(--gold); margin: 0.25rem 0; font-size: 1.25rem;">
Gib die 4 Essenzen in den Kessel!
Dosiere die 3 Essenzen nach Snapes Rezeptur!
</h3>
<p id="stepSubtext" style="color: var(--text-dim); font-size: 0.9rem; margin: 0;">
Tippe auf die Zutaten unten, um sie in den Kessel zu werfen.
<p id="stepSubtext" style="color: var(--text-dim); font-size: 0.9rem; margin: 0 0 0.4rem 0;">
Löse Snapes Rätselnotiz, um die Mengenangaben für Felix Felicis herauszufinden.
</p>
<button type="button" class="btn-subtle" style="font-size: 0.9rem; border-color: var(--gold); color: var(--gold); padding: 0.4rem 0.9rem;" onclick="openRecipeRiddleModal()">
📜 Snapes Rezeptur-Notiz öffnen
</button>
</div>
<!-- The SVG Cauldron Stage -->
@@ -125,36 +128,81 @@
</svg>
</div>
<!-- Step 1: Ingredient Shelf & Counter Bar -->
<div id="step1Wrapper" style="width: 100%; display: flex; flex-direction: column; align-items: center; gap: 0.6rem;">
<div style="font-size: 0.9rem; color: var(--gold); font-weight: bold;">
🧪 Essenzen im Kessel: <span id="totalIngredientsCount">0</span> / 4
<!-- Step 1: Ingredient Dosage Shelf & +/- Controls -->
<div id="step1Wrapper" style="width: 100%; display: flex; flex-direction: column; align-items: center; gap: 0.75rem;">
<div style="font-size: 0.95rem; color: var(--gold); font-weight: bold; text-align: center;">
⚗️ Dosiere die Essenzen laut Snapes Notiz:
</div>
<div id="ingredientsShelf" class="ingredients-shelf">
<button type="button" class="ingredient-btn" id="ingDragon" onclick="addIngredient('dragon')">
<span class="ing-icon">🐉</span>
<span class="ing-name">Drachenblut</span>
<span class="ing-count" id="countDragon">0 / 2</span>
</button>
<button type="button" class="ingredient-btn" id="ingMandrake" onclick="addIngredient('mandrake')">
<span class="ing-icon">🌿</span>
<span class="ing-name">Alraunenblatt</span>
<span class="ing-count" id="countMandrake">0 / 1</span>
</button>
<button type="button" class="ingredient-btn" id="ingStar" onclick="addIngredient('star')">
<span class="ing-icon">✨</span>
<span class="ing-name">Sternenstaub</span>
<span class="ing-count" id="countStar">0 / 1</span>
</button>
<div class="dose-grid">
<!-- Dragon Blood -->
<div class="dose-card">
<span style="font-size: 2.2rem;">🐉</span>
<strong style="color: var(--text-light); font-size: 0.85rem;">Drachenblut</strong>
<div class="dose-controls">
<button type="button" class="dose-btn" onclick="adjustDose('dragon', -1)">-</button>
<span id="doseValDragon" class="dose-val">0</span>
<button type="button" class="dose-btn" onclick="adjustDose('dragon', 1)">+</button>
</div>
</div>
<!-- Mandrake -->
<div class="dose-card">
<span style="font-size: 2.2rem;">🌿</span>
<strong style="color: var(--text-light); font-size: 0.85rem;">Alraune</strong>
<div class="dose-controls">
<button type="button" class="dose-btn" onclick="adjustDose('mandrake', -1)">-</button>
<span id="doseValMandrake" class="dose-val">0</span>
<button type="button" class="dose-btn" onclick="adjustDose('mandrake', 1)">+</button>
</div>
</div>
<!-- Star Dust -->
<div class="dose-card">
<span style="font-size: 2.2rem;">✨</span>
<strong style="color: var(--text-light); font-size: 0.85rem;">Sternenstaub</strong>
<div class="dose-controls">
<button type="button" class="dose-btn" onclick="adjustDose('star', -1)">-</button>
<span id="doseValStar" class="dose-val">0</span>
<button type="button" class="dose-btn" onclick="adjustDose('star', 1)">+</button>
</div>
</div>
</div>
<button type="button" id="brewVerifyBtn" class="btn-magical" style="padding: 0.85rem 1.8rem; font-size: 1.1rem; width: 100%; max-width: 340px;" onclick="verifyAndMixIngredients()">
🧪 Essenzen in den Kessel geben & prüfen
</button>
</div>
<!-- Step 2: Stir Control Panel -->
<div id="stirPanel" style="display: none; flex-direction: column; align-items: center; gap: 0.5rem; width: 100%;">
<button type="button" id="stirBtn" class="btn-magical" style="padding: 0.9rem 1.8rem; font-size: 1.15rem; width: 100%; max-width: 320px;" onclick="doStir()">
🥄 Kessel umrühren! (<span id="stirCount">0</span> / 3)
</button>
<span style="color: var(--text-dim); font-size: 0.85rem;">Tippe auf den Button, um den Sud umzurühren</span>
<!-- Step 2: Two-Way Stirring Gauge (Links ↺ und Rechts ↻) -->
<div id="stirPanel" style="display: none; flex-direction: column; align-items: center; gap: 0.75rem; width: 100%;">
<div class="stir-gauge-wrapper">
<div style="font-size: 0.95rem; color: var(--gold); font-weight: bold; text-align: center;">
🥄 Rühr-Takt: <span id="stirPhaseLabel" style="color: #4cc9f0;">↺ LINKS (Phase 1)</span>
</div>
<div class="stir-track">
<div class="stir-target-zone"></div>
<div id="stirIndicatorBar" class="stir-indicator-bar"></div>
</div>
<div style="display: flex; justify-content: space-between; width: 100%; font-size: 0.78rem; color: var(--text-dim);">
<span>Zu träge</span>
<span style="color: #2ecc71; font-weight: bold;">Ideal (40% - 75%)</span>
<span>Zu wild!</span>
</div>
<div style="font-size: 0.9rem; color: var(--text-light); font-weight: bold;">
Takt gehalten: <strong id="stirTimerVal" style="color: var(--gold);">0.0</strong> / 3.0s
</div>
</div>
<div class="stir-buttons-row">
<button type="button" id="btnStirLeft" class="stir-action-btn active-target" onclick="stirTap('left')">
<span style="font-size: 1.6rem;">↺</span>
<span>Linksherum</span>
</button>
<button type="button" id="btnStirRight" class="stir-action-btn" onclick="stirTap('right')">
<span style="font-size: 1.6rem;">↻</span>
<span>Rechtsherum</span>
</button>
</div>
<span style="color: var(--text-dim); font-size: 0.82rem; text-align: center;">
Tippe rhythmisch, um den Balken im grünen Idealbereich zu halten!
</span>
</div>
<!-- Step 3: Heat Control Panel -->
@@ -179,6 +227,41 @@
</button>
</div>
<!-- Snape Reprimand Modal -->
<div id="snapeReprimandModal" class="snape-reprimand-modal">
<div class="snape-card">
<div class="snape-avatar">🧙‍♂️</div>
<span style="display: inline-block; background: rgba(142, 68, 173, 0.25); border: 1px solid #8e44ad; color: #d2b4de; font-size: 0.8rem; font-weight: bold; padding: 0.2rem 0.75rem; border-radius: 20px; text-transform: uppercase;">
Professor Severus Snape
</span>
<h3 style="color: #e74c3c; margin: 0.5rem 0 0.2rem 0; font-size: 1.35rem;">Kläglicher Fehltritt!</h3>
<div id="snapeReprimandText" class="snape-quote-box">
»Kläglich. Sogar ein Bergtroll mit verbundenen Augen hätte die Mengen besser ergründet.«
</div>
<button type="button" class="btn-magical" style="padding: 0.75rem 1.6rem; font-size: 1.05rem;" onclick="closeSnapeModal()">
🧹 Kessel säubern (Evanesco) & neu ansetzen
</button>
</div>
</div>
<!-- Recipe Riddle Parchment Modal -->
<div id="recipeRiddleModal" class="snape-reprimand-modal">
<div class="snape-card" style="border-color: var(--gold); box-shadow: 0 0 45px rgba(229, 185, 72, 0.4);">
<div style="font-size: 3.2rem; margin-bottom: 0.3rem;">📜✨</div>
<h3 style="color: var(--gold); margin: 0.3rem 0; font-size: 1.4rem;">Snapes Felix-Felicis-Rezeptur</h3>
<div class="snape-quote-box" style="border-color: var(--gold);">
<em>»Drei Essenzen verlangt das flüssige Gold:<br><br>
• 🐉 <strong>Drachenblut:</strong> Die Köpfe des dreiköpfigen Wächters Fluffy (3 Tropfen)<br>
• 🌿 <strong>Alraunenblatt:</strong> Harrys treue Gefährten am Gryffindor-Tisch (Ron & Hermine = 2 Blätter)<br>
• ✨ <strong>Sternenstaub:</strong> Der eine Siegelring des Alchemisten (1 Prise)<br><br>
<strong>Rühren:</strong> 3 Sekunden gleichmäßig LINKS (↺), danach 3 Sekunden RECHTS (↻)! Zu hektisch oder zu heiß zerstört den Sud augenblicklich!«</em>
</div>
<button type="button" class="btn-magical" style="padding: 0.75rem 1.8rem; font-size: 1.05rem;" onclick="closeRecipeRiddleModal()">
➔ Verstanden, zum Kessel
</button>
</div>
</div>
<!-- Success Container -->
<div id="successPanel" style="display: none; text-align: center; margin-top: 1rem; width: 100%;">
<div class="dungeon-card" style="border-color: #2ecc71;">
@@ -199,5 +282,5 @@
{% endblock %}
{% block scripts %}
<script src="/static/js/brew.js?v=5.0"></script>
<script src="/static/js/brew.js?v=6.0"></script>
{% endblock %}
+21 -6
View File
@@ -12,12 +12,13 @@
</p>
</div>
<div class="canvas-wrapper">
<div class="canvas-wrapper" id="canvasWrapper">
<div class="game-hud">
<div>⏱️ Zeit: <strong id="timerVal">0s</strong></div>
<div>⭕ Ringe: <strong id="ringsVal" style="color: #ffd700;">0/12</strong></div>
<div>✨ Punkte: <strong id="scoreVal">0</strong></div>
<div id="comboVal" style="color: #00ffff; font-weight: bold; min-width: 80px;"></div>
<div>🧹 Zustand: <span id="livesVal" style="font-size: 1.1rem; letter-spacing: 2px;">💚💚💚</span></div>
<div id="comboVal" style="color: #00ffff; font-weight: bold; min-width: 60px;"></div>
</div>
<canvas id="broomCanvas" style="touch-action: none; -webkit-user-select: none; user-select: none; width: 100%; display: block;"></canvas>
@@ -26,14 +27,28 @@
<div id="broomStartOverlay" class="flight-start-overlay">
<div style="font-size: 2.8rem; margin-bottom: 0.3rem;">🧹✨⭕</div>
<h3 style="color: var(--gold); font-size: 1.45rem; margin: 0 0 0.4rem 0;">Bereit zum Abflug?</h3>
<p style="color: var(--text-light); font-size: 0.95rem; margin: 0 0 1.2rem 0; text-align: center; max-width: 300px;">
<p style="color: var(--text-light); font-size: 0.95rem; margin: 0 0 1.2rem 0; text-align: center; max-width: 320px;">
Fliege durch <strong>12 magische Ringe</strong>!<br>
Steuere per Daumen über das Spielfeld oder mit dem Steuerkreuz unten.
<span style="color: #e74c3c;">⚠️ Weiche wilden Klatschern (💣) und schwebenden Felsen (🪨) aus!</span><br>
Steuere per Daumen über das Feld oder mit dem Steuerkreuz.
</p>
<button type="button" id="startFlightBtn" class="btn-magical" style="padding: 0.85rem 2.2rem; font-size: 1.2rem;" onclick="startFlight()">
<button type="button" id="startFlightBtn" class="btn-magical" style="padding: 0.85rem 2.2rem; font-size: 1.2rem;">
⚡ Flug starten!
</button>
</div>
<!-- Crash / Game Over Overlay -->
<div id="broomCrashOverlay" class="flight-start-overlay hidden">
<div style="font-size: 2.8rem; margin-bottom: 0.3rem;">💥🧹😵</div>
<h3 style="color: #e74c3c; font-size: 1.45rem; margin: 0 0 0.4rem 0;">Klatscher-Volltreffer!</h3>
<p style="color: var(--text-light); font-size: 0.95rem; margin: 0 0 1.2rem 0; text-align: center; max-width: 300px;">
Dein Besen hat die Balance verloren und Madam Hooch pfeift zum Abbruch!<br>
Halte Abstand zu den wirbelnden Eisenbällen!
</p>
<button type="button" id="restartFlightBtn" class="btn-magical" style="padding: 0.85rem 2.2rem; font-size: 1.2rem;">
🔄 Erneut abheben!
</button>
</div>
</div>
<!-- Mobile Flight Cockpit & D-Pad -->
@@ -73,5 +88,5 @@
{% endblock %}
{% block scripts %}
<script src="/static/js/broom.js?v=5.0"></script>
<script src="/static/js/broom.js?v=6.0"></script>
{% endblock %}
+68 -7
View File
@@ -3,14 +3,75 @@
{% block title %}Die Prüfungen des Steins der Weisen · Hogwarts Escape{% endblock %}
{% block content %}
<div class="parchment-scroll">
<h1 class="parchment-title">⚡ Die Kammern des Steins der Weisen ⚡</h1>
<p class="riddle-poem" style="font-size: 1.3rem; margin: 0.5rem 0;">
"Die Falltür unter Fluffys Pfoten hat sich geöffnet.<br>
Tief unter den Kerkern von Hogwarts wachen uralte Zauber über das größte Geheimnis der Alchemie.<br>
Beweise deinen Scharfsinn, dein Geschick auf dem Besen und deine eiserne Logik!"
</p>
<!-- Interaktiver Hogwarts-Brief & Siegel Intro -->
<div class="escape-letter-intro" id="escapeLetterIntro">
<div class="antique-envelope-scene" id="envelope">
<div class="envelope-base">
<div class="envelope-interior"></div>
<div class="letter-sheet" id="letterSheet">
<header class="letter-header">
<div class="letter-crest-box">
<img src="/static/img/hogwarts_seal.jpg" alt="Hogwarts Crest" class="letter-crest-sketch">
</div>
<h3 class="letter-school-name">Hogwarts-Schule für Hexerei und Zauberei</h3>
<p class="letter-headmaster">Schulleiter: Albus Dumbledore<br><span>(Hüter des Steins der Weisen · Verbotener Korridor)</span></p>
<div class="letter-ornament-line">
<span class="ornament-leaf">❦</span>
<span class="ornament-rule"></span>
<span class="ornament-shield">✦</span>
<span class="ornament-rule"></span>
<span class="ornament-leaf">❧</span>
</div>
</header>
<div class="letter-body-handwritten">
<p class="letter-salutation">Liebe Hexe, lieber Zauberer,</p>
<p class="letter-paragraph">
die Falltür unter Fluffys Pfoten hat sich geöffnet! Tief unter den Kerkern von Hogwarts wachen sechs uralte Schutzzauber der Lehrer über das größte Geheimnis der Alchemie: den <strong>Stein der Weisen</strong>.
</p>
<p class="letter-paragraph">
Schwinge dich auf deinen Besen, stelle dich dem Zauberstab-Duell, braue das goldene Glückselixier und durchschreite Snapes schwarze Flammen. Nur wer alle Kammern meistert, bewahrt das Schloss vor dem Schatten!
</p>
</div>
<footer class="letter-signature-block">
<p class="letter-closing">Mit magischer Hochachtung,</p>
<p class="letter-signature-ink">Minerva McGonagall</p>
<p class="letter-sign-title">Stellvertretende Schulleiterin</p>
</footer>
</div>
<div class="envelope-back-body"></div>
<div class="envelope-closing-flap envelope-v-flap" id="envelopeFlap">
<div class="v-flap-sketch-line"></div>
</div>
<div class="sketched-wax-seal" id="waxSeal" onclick="toggleEscapeLetter()" title="Siegel brechen & Botschaft lesen">
<img src="/static/img/hogwarts_seal.jpg" alt="Hogwarts-Wappen Siegel" class="seal-crest-img">
<div class="seal-emboss-ring"></div>
<div class="seal-glow"></div>
</div>
</div>
</div>
<div style="text-align: center; margin-bottom: 1.5rem;">
<button type="button" id="letterToggleBtn" class="btn-magical" onclick="toggleEscapeLetter()" style="padding: 0.65rem 1.4rem; font-size: 0.95rem;">
📜 Siegel brechen & Einladung lesen
</button>
</div>
</div>
<script>
function toggleEscapeLetter() {
const env = document.getElementById('envelope');
const btn = document.getElementById('letterToggleBtn');
if (!env) return;
const opened = env.classList.toggle('envelope-opened');
if (window.soundFX) window.soundFX.playKeyChime();
const bgm = document.getElementById('bgm');
if (bgm && bgm.paused && (!window.soundFX || !window.soundFX.isMuted())) {
bgm.volume = 0.45;
bgm.play().catch(() => {});
}
if (btn) {
btn.innerText = opened ? '↩ Brief wieder verschließen' : '📜 Siegel brechen & Einladung lesen';
}
}
</script>
<div class="dungeon-card">
<h2 style="color: var(--gold); text-align: center; margin-bottom: 0.5rem; font-size: 1.8rem;">
+3 -3
View File
@@ -40,10 +40,10 @@
<!-- Top HUD Bar -->
<div class="pixies-hud">
<div>
🧚 Gefangen: <strong id="pixieScore" style="color: var(--gold); font-size: 1.3rem;">0</strong> / 10
🧚 Gebannt: <strong id="pixieScore" style="color: var(--gold); font-size: 1.3rem;">0</strong> / 12
</div>
<div>
⏳ Zeit: <strong id="pixieTimer" style="color: #3498db; font-size: 1.3rem;">35</strong>s
⏳ Zeit: <strong id="pixieTimer" style="color: #3498db; font-size: 1.3rem;">30</strong>s
</div>
</div>
@@ -131,5 +131,5 @@
{% endblock %}
{% block scripts %}
<script src="/static/js/pixies.js?v=5.0"></script>
<script src="/static/js/pixies.js?v=6.0"></script>
{% endblock %}