Files
Wackelpeter/web/index.html
T

432 lines
20 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Wackelpeter</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { width: 100%; height: 100%; overflow: hidden; background: #000; }
canvas {
display: block;
cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cg fill='none' stroke='%23140d02' stroke-width='4.5' stroke-linecap='round'%3E%3Ccircle cx='20' cy='20' r='13'/%3E%3Cpath d='M20 2v5M20 33v5M2 20h5M33 20h5'/%3E%3C/g%3E%3Cg fill='none' stroke='%23ffc83d' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='20' cy='20' r='13'/%3E%3Cpath d='M20 2v5M20 33v5M2 20h5M33 20h5'/%3E%3C/g%3E%3Cg fill='%23ffc83d' stroke='%23140d02' stroke-width='1'%3E%3Cpath d='M20 0l1.6 3.4L18.4 3.4Z'/%3E%3Cpath d='M20 40l1.6-3.4L18.4 36.6Z'/%3E%3Cpath d='M0 20l3.4-1.6L3.4 21.6Z'/%3E%3Cpath d='M40 20l-3.4-1.6L36.6 21.6Z'/%3E%3C/g%3E%3Cg fill='%23ffc83d' stroke='%23140d02' stroke-width='1'%3E%3Crect x='8.2' y='8.2' width='3.6' height='3.6' transform='rotate(45 10 10)'/%3E%3Crect x='28.2' y='8.2' width='3.6' height='3.6' transform='rotate(45 30 10)'/%3E%3Crect x='8.2' y='28.2' width='3.6' height='3.6' transform='rotate(45 10 30)'/%3E%3Crect x='28.2' y='28.2' width='3.6' height='3.6' transform='rotate(45 30 30)'/%3E%3C/g%3E%3Ccircle cx='20' cy='20' r='2.6' fill='%23ffe9a8' stroke='%23140d02' stroke-width='1'/%3E%3C/svg%3E") 20 20, crosshair;
}
#ui-overlay {
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
pointer-events: none; font-family: monospace; z-index: 10;
}
#damage-vignette {
position: absolute; inset: 0; opacity: 0; pointer-events: none;
background: radial-gradient(ellipse at center,
rgba(255,0,0,0) 40%, rgba(255,0,0,0.35) 100%);
box-shadow: inset 0 0 120px 40px rgba(255,0,0,0.5);
}
#damage-vignette.hurt { animation: hurt-flash 0.45s ease-out; }
@keyframes hurt-flash {
0% { opacity: 1; }
100% { opacity: 0; }
}
#low-hp-vignette {
position: absolute; inset: 0; opacity: 0; pointer-events: none;
background: radial-gradient(ellipse at center,
rgba(255,0,0,0.05) 0%, rgba(255,0,0,0.15) 55%, rgba(220,0,0,0.7) 100%);
box-shadow: inset 0 0 160px 60px rgba(220,0,0,0.55);
}
#low-hp-vignette.active { animation: low-hp-pulse 1.1s ease-in-out infinite; }
@keyframes low-hp-pulse {
0%, 100% { opacity: 0.25; }
50% { opacity: 0.6; }
}
#ink-vignette {
position: absolute; inset: 0; opacity: 0; pointer-events: none;
background: radial-gradient(ellipse at center,
rgba(120,40,180,0) 35%, rgba(120,40,180,0.4) 100%);
box-shadow: inset 0 0 140px 50px rgba(100,30,160,0.55);
}
#ink-vignette.ink { animation: ink-flash 0.5s ease-out; }
@keyframes ink-flash {
0% { opacity: 1; }
100% { opacity: 0; }
}
#boss-bar {
position: absolute; top: 14px; left: 50%; transform: translateX(-50%);
width: 420px; display: none; text-align: center; font-family: monospace;
}
#boss-bar-label {
color: #ffcc00; font-size: 16px; text-shadow: 1px 1px 3px #000;
margin-bottom: 4px;
}
#boss-bar-bg {
height: 18px; background: rgba(0,0,0,0.6);
border: 2px solid #aa3366;
}
#boss-bar-fill {
height: 100%; width: 100%;
background: linear-gradient(#ff5577, #bb2244);
transition: width 0.15s linear;
}
#health-bar-bg {
position: absolute; top: 16px; left: 16px; width: 250px; height: 20px;
background: rgba(0,0,0,0.6); border: 2px solid #555;
}
#health-bar {
position: absolute; top: 16px; left: 16px; width: 250px; height: 20px;
background: #cc0000;
transition: width 0.1s linear;
}
#health-text {
position: absolute; top: 16px; left: 16px; width: 250px; height: 20px;
text-align: center; line-height: 20px; color: #fff; font-size: 12px;
}
#wave-label {
position: absolute; top: 48px; left: 16px; color: #ffcc00; font-size: 18px;
font-family: monospace; text-shadow: 2px 2px 4px #000;
}
#kills-label {
position: absolute; top: 72px; left: 16px; color: #ffcc00; font-size: 16px;
font-family: monospace; text-shadow: 2px 2px 4px #000;
}
.cooldown-container {
position: absolute; left: 16px; width: 200px; height: 16px;
}
.cooldown-bg {
width: 100%; height: 100%; background: rgba(0,0,0,0.6); border: 1px solid #555;
}
.cooldown-fill {
height: 100%; background: #2266dd; transition: width 0.05s linear;
}
.cooldown-label {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
text-align: left; line-height: 16px; color: #fff; font-size: 11px;
padding-left: 4px; font-family: monospace;
}
#fireball-cooldown { bottom: 72px; }
#sword-cooldown { bottom: 48px; }
#teleport-cooldown { bottom: 24px; }
#lightning-cooldown { bottom: 96px; }
#trap-cooldown { bottom: 120px; }
#gas-cooldown { bottom: 144px; }
#wave-bar-container {
position: absolute; top: 16px; right: 16px; width: 250px; height: 16px;
}
#wave-bar-bg {
width: 100%; height: 100%; background: rgba(0,0,0,0.6); border: 1px solid #555;
}
#wave-bar-fill {
height: 100%; background: #ccaa00; transition: width 0.1s linear;
}
#wave-bar-label {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
text-align: center; line-height: 16px; color: #fff; font-size: 11px;
font-family: monospace;
}
#game-over {
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
font-size: 100px; color: #fff; font-family: monospace; opacity: 0;
text-shadow: 4px 4px 8px #000;
transition: opacity 2s ease-in;
}
#game-over-panel {
position: absolute; top: 62%; left: 50%; transform: translate(-50%, -50%);
display: flex; flex-direction: column; align-items: center; gap: 12px;
pointer-events: none; opacity: 0; visibility: hidden;
transition: opacity 0.8s ease-in 1.5s;
font-family: monospace;
}
#game-over-stats {
color: #ffcc00; font-size: 20px; text-shadow: 2px 2px 4px #000;
}
.menu-button {
pointer-events: auto; cursor: pointer;
background: rgba(0,0,0,0.7); color: #fff; font-family: monospace;
font-size: 18px; padding: 10px 28px; border: 2px solid #888;
}
.menu-button:hover { background: #333; border-color: #ffcc00; color: #ffcc00; }
#main-menu {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
display: flex; flex-direction: column; align-items: center; justify-content: center;
gap: 18px; pointer-events: auto; background: rgba(0,0,0,0.55);
transition: opacity 0.6s ease; font-family: monospace;
}
#main-menu h1 {
color: #fff; font-size: 72px; text-shadow: 4px 4px 8px #000;
}
#main-menu .subtitle {
color: #ffcc00; font-size: 20px; text-shadow: 2px 2px 4px #000;
}
#main-menu .menu-controls {
color: rgba(255,255,255,0.8); font-size: 13px; text-align: center;
line-height: 1.7;
}
#btn-start { font-size: 24px; padding: 14px 48px; }
#btn-confirm { font-size: 18px; padding: 10px 36px; }
#btn-confirm:disabled { opacity: 0.35; cursor: default; }
#instructions {
position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%);
color: rgba(255,255,255,0.5); font-size: 11px; font-family: monospace;
text-align: center;
}
#changelog-panel {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
display: flex; flex-direction: column; align-items: center; justify-content: center;
gap: 14px; background: rgba(0,0,0,0.85);
opacity: 0; pointer-events: none; visibility: hidden;
transition: opacity 0.2s ease; font-family: monospace;
}
#changelog-panel h2 {
color: #ffcc00; font-size: 34px; text-shadow: 3px 3px 6px #000;
}
#changelog-list {
width: 660px; max-width: 92vw; max-height: 55vh; overflow-y: auto;
background: rgba(20,20,30,0.9); border: 2px solid #888; padding: 14px 18px;
color: rgba(255,255,255,0.85); font-size: 13px; line-height: 1.6;
text-align: left;
}
.changelog-entry {
display: flex; gap: 12px; padding: 4px 0;
border-bottom: 1px solid rgba(255,255,255,0.08);
}
.changelog-entry:last-child { border-bottom: none; }
.changelog-date { color: #ffcc00; white-space: nowrap; }
#seed-input {
background: rgba(0,0,0,0.7); border: 2px solid #555; color: #ffcc00;
font-family: monospace; font-size: 16px; padding: 6px 10px; width: 180px;
text-align: center; outline: none;
}
#seed-input:focus { border-color: #ffcc00; }
#level-label {
position: absolute; top: 96px; left: 16px; color: #88ff88; font-size: 16px;
font-family: monospace; text-shadow: 2px 2px 4px #000;
}
#seed-label {
position: absolute; top: 96px; right: 16px; color: rgba(255,255,255,0.6);
font-size: 12px; font-family: monospace; text-shadow: 1px 1px 2px #000;
}
#xp-bar-container {
position: absolute; top: 120px; left: 16px; width: 250px; height: 12px;
}
#xp-bar-bg {
width: 100%; height: 100%; background: rgba(0,0,0,0.6); border: 1px solid #555;
}
#xp-bar-fill {
height: 100%; background: #44cc44; transition: width 0.1s linear;
}
#xp-bar-label {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
text-align: center; line-height: 12px; color: #fff; font-size: 10px;
font-family: monospace;
}
#shield-bar-bg {
position: absolute; top: 44px; left: 16px; width: 250px; height: 10px;
background: rgba(0,0,0,0.6); border: 1px solid #555; display: none;
}
#shield-bar {
position: absolute; top: 44px; left: 16px; width: 250px; height: 10px;
background: #3399ff; transition: width 0.1s linear; display: none;
}
#shield-text {
position: absolute; top: 44px; left: 16px; width: 250px; height: 10px;
text-align: center; line-height: 10px; color: #fff; font-size: 9px;
font-family: monospace; display: none;
}
#level-up {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
display: flex; flex-direction: column; align-items: center; justify-content: center;
gap: 24px; background: rgba(0,0,0,0.7); opacity: 0; pointer-events: none;
visibility: hidden; transition: opacity 0.3s ease; font-family: monospace;
}
#pause-overlay {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
display: flex; flex-direction: column; align-items: center; justify-content: center;
gap: 18px; background: rgba(0,0,0,0.6); opacity: 0; pointer-events: none;
visibility: hidden; transition: opacity 0.2s ease; font-family: monospace;
}
#pause-overlay h2 {
color: #fff; font-size: 48px; text-shadow: 3px 3px 6px #000;
}
#level-up h2 {
color: #ffcc00; font-size: 44px; text-shadow: 3px 3px 6px #000;
}
#offer-row {
display: flex; gap: 20px;
}
.offer-card {
width: 230px; min-height: 220px; background: rgba(20,20,30,0.9);
border: 2px solid #888; padding: 14px; cursor: pointer;
display: flex; flex-direction: column; gap: 10px;
transition: transform 0.1s ease, border-color 0.1s ease;
}
.offer-card:hover { border-color: #ffcc00; background: rgba(40,40,50,0.95); }
.offer-card.selected {
border-color: #ffcc00; background: rgba(60,50,20,0.95);
transform: scale(1.04); box-shadow: 0 0 18px rgba(255,204,0,0.4);
}
.offer-icon {
width: 76px; height: 76px; margin: 2px auto 0;
filter: drop-shadow(0 3px 6px rgba(0,0,0,0.55));
transition: filter 0.1s ease;
}
.offer-icon svg { width: 100%; height: 100%; display: block; }
.offer-card:hover .offer-icon, .offer-card.selected .offer-icon {
filter: drop-shadow(0 0 9px rgba(255,204,0,0.5));
}
.offer-title {
color: #ffcc00; font-size: 18px; font-weight: bold; text-align: center;
}
.offer-desc {
color: rgba(255,255,255,0.85); font-size: 13px; line-height: 1.5;
}
.offer-hint {
color: rgba(255,255,255,0.4); font-size: 12px; margin-top: auto;
}
</style>
</head>
<body>
<div id="ui-overlay">
<div id="damage-vignette"></div>
<div id="low-hp-vignette"></div>
<div id="ink-vignette"></div>
<div id="boss-bar">
<div id="boss-bar-label">BOSS</div>
<div id="boss-bar-bg"><div id="boss-bar-fill"></div></div>
</div>
<div id="health-bar-bg"></div>
<div id="health-bar"></div>
<div id="health-text">100</div>
<div id="shield-bar-bg"></div>
<div id="shield-bar"></div>
<div id="shield-text"></div>
<div id="wave-label">Wave 0</div>
<div id="kills-label">Kills: 0</div>
<div id="level-label">Level 0</div>
<div id="xp-bar-container">
<div id="xp-bar-bg"></div>
<div id="xp-bar-fill"></div>
<div id="xp-bar-label">XP: 0/20</div>
</div>
<div id="seed-label"></div>
<div id="fireball-cooldown" class="cooldown-container" style="display: none">
<div class="cooldown-bg"></div>
<div class="cooldown-fill"></div>
<div class="cooldown-label">Fireball</div>
</div>
<div id="sword-cooldown" class="cooldown-container">
<div class="cooldown-bg"></div>
<div class="cooldown-fill"></div>
<div class="cooldown-label">Sword</div>
</div>
<div id="teleport-cooldown" class="cooldown-container" style="display: none">
<div class="cooldown-bg"></div>
<div class="cooldown-fill"></div>
<div class="cooldown-label">Teleport</div>
</div>
<div id="lightning-cooldown" class="cooldown-container" style="display: none">
<div class="cooldown-bg"></div>
<div class="cooldown-fill"></div>
<div class="cooldown-label">Chain Lightning</div>
</div>
<div id="trap-cooldown" class="cooldown-container" style="display: none">
<div class="cooldown-bg"></div>
<div class="cooldown-fill"></div>
<div class="cooldown-label">Falle</div>
</div>
<div id="gas-cooldown" class="cooldown-container" style="display: none">
<div class="cooldown-bg"></div>
<div class="cooldown-fill"></div>
<div class="cooldown-label">Gaswolke</div>
</div>
<div id="wave-bar-container">
<div id="wave-bar-bg"></div>
<div id="wave-bar-fill"></div>
<div id="wave-bar-label">Next Wave...</div>
</div>
<div id="game-over">Verloren!</div>
<div id="game-over-panel">
<div id="game-over-stats"></div>
<button id="btn-restart" class="menu-button">Nochmal spielen</button>
<button id="btn-menu" class="menu-button">Hauptmenü</button>
</div>
<div id="level-up">
<h2>Level Up!</h2> <div id="offer-row">
<div id="offer-0" class="offer-card">
<div id="offer-icon-0" class="offer-icon"></div>
<div id="offer-title-0" class="offer-title"></div>
<div id="offer-desc-0" class="offer-desc"></div>
<div class="offer-hint">[1] auswählen</div>
</div>
<div id="offer-1" class="offer-card">
<div id="offer-icon-1" class="offer-icon"></div>
<div id="offer-title-1" class="offer-title"></div>
<div id="offer-desc-1" class="offer-desc"></div>
<div class="offer-hint">[2] auswählen</div>
</div>
<div id="offer-2" class="offer-card">
<div id="offer-icon-2" class="offer-icon"></div>
<div id="offer-title-2" class="offer-title"></div>
<div id="offer-desc-2" class="offer-desc"></div>
<div class="offer-hint">[3] auswählen</div>
</div>
</div>
<button id="btn-confirm" class="menu-button" disabled>Bestätigen (Enter)</button>
</div>
<div id="pause-overlay">
<h2>Pausiert</h2>
<button id="btn-resume" class="menu-button">Weiter (ESC)</button>
<button id="btn-pause-menu" class="menu-button">Hauptmenü</button>
</div>
<div id="main-menu">
<h1>WACKELPETER</h1>
<div class="subtitle">Ein Blob kämpft ums Überleben</div>
<div class="menu-controls">
WASD: Bewegen · Space: Springen · Maus: Zielen · ESC: Pause<br>
Linksklick: Schwert · Rechtsklick: Feuerball (per Skill)<br>
Q, E, 14: Skills (werden nach Erwerb belegt)
</div>
<input id="seed-input" type="text" placeholder="Seed (leer = zufällig)" />
<div id="boss-mode" style="opacity:0; pointer-events:none; visibility:hidden; display:flex; flex-direction:column; align-items:center; gap:10px;">
<div class="subtitle">BOSS-MODUS</div>
<div id="boss-mode-buttons" style="display:flex; flex-direction:column; gap:8px; align-items:center;"></div>
</div>
<button id="btn-start" class="menu-button">Start</button>
<button id="btn-changelog" class="menu-button">Changelog</button>
</div>
<div id="changelog-panel">
<h2>Changelog</h2>
<div id="changelog-list">
<div class="changelog-entry"><span class="changelog-date">20.08.</span><span>Sechs neue Gegner: Schamane (heilt), Bogenschütze (Telegraf-Pfeile), Bomber (Explosion), Irrlicht (Slow-Sporen), Schildkröte (Frontpanzer + Rückzug) und Sporen-Pilz (Bogen-Sporen mit DoT-Wolke)</span></div>
<div class="changelog-entry"><span class="changelog-date">20.08.</span><span>Drachen-Boss (Welle 70): fliegt und ist nur am Boden verletzbar, Sturzangriff mit Schatten, Feuerspeer</span></div>
<div class="changelog-entry"><span class="changelog-date">20.08.</span><span>Erz-Nekromant (Welle 60): Teleport mit Telegraf, Projektil-Salven und Beschwörungen</span></div>
<div class="changelog-entry"><span class="changelog-date">20.08.</span><span>Frostriese (Welle 50): Eispanzer-Rüstung, Eisberst-Ringe und Eiszapfen-Regen</span></div>
<div class="changelog-entry"><span class="changelog-date">20.08.</span><span>Spinnenkönigin (Welle 40): Netze fesseln den Spieler, Spinngeschwister und Säuresalven</span></div>
<div class="changelog-entry"><span class="changelog-date">19.08.</span><span>Minotaurus-Boss mit Frontpanzerung, Dash-Stun und überspringbarem Axthieb</span></div>
<div class="changelog-entry"><span class="changelog-date">19.08.</span><span>Boss-Treffer-Feedback mit Aufblitzen und schwebenden Schadenszahlen</span></div>
<div class="changelog-entry"><span class="changelog-date">19.08.</span><span>Krake-Boss mit Tinte, Zug-Markierungen und Sweep-Tentakeln plus Boss-Modus</span></div>
<div class="changelog-entry"><span class="changelog-date">19.08.</span><span>Golem-Boss in Welle 10, startet erst wenn die Arena geräumt ist</span></div>
<div class="changelog-entry"><span class="changelog-date">19.08.</span><span>Bumerang als dünne 120-Grad-Sichel neu designt</span></div>
<div class="changelog-entry"><span class="changelog-date">19.08.</span><span>Spieler-folgendes Licht, Dungeon-Umgebung abgedunkelt</span></div>
<div class="changelog-entry"><span class="changelog-date">19.08.</span><span>Aura-, Bumerang-, Fallen- und Gaswolken-Skills mit Hotbar und ESC-Pause</span></div>
<div class="changelog-entry"><span class="changelog-date">19.08.</span><span>Gegner-Blickrichtung korrigiert und Schadens-Feedback beim Spieler</span></div>
<div class="changelog-entry"><span class="changelog-date">18.08.</span><span>Rückenschild-Modell am Schild-Skill gekoppelt</span></div>
<div class="changelog-entry"><span class="changelog-date">18.08.</span><span>Skill-Icons auf den Level-up-Karten</span></div>
<div class="changelog-entry"><span class="changelog-date">17.08.</span><span>Skill-System, Level-Ups und neue Gegnertypen</span></div>
<div class="changelog-entry"><span class="changelog-date">17.08.</span><span>Hauptmenü, Geist-Gegner und Schwert-Schwung-Spur</span></div>
<div class="changelog-entry"><span class="changelog-date">17.08.</span><span>AGENTS.md mit Git-Regeln</span></div>
</div>
<button id="btn-changelog-close" class="menu-button">Schließen</button>
</div>
<div id="instructions">
WASD: Move · Space: Jump · Mouse: Aim · Left Click: Sword · Right Click: Fireball · Q/E/1-4: Skills · ESC: Pause
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>