edu-boardgame-generator/editor.html
Spiel-Generator Workshop da4f6dc102 fix: remove duplicate codegen.js inline block, add missing unlockSection
- codegen.js war doppelt: einmal im Haupt-Script (korrekt) und einmal
  nochmals inline eingebettet → 'const unlocked already declared' Fehler
- Doppelten Inline-Block entfernt
- unlockSection() fehlte (beim Refactoring verloren gegangen):
  als Wrapper für setCodeFocus/unlocked.add wiederhergestellt
- s3init() läuft jetzt korrekt: Board + Palette erscheinen sofort
2026-03-14 22:47:43 +00:00

4636 lines
336 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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="de">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<title>Spiel-Generator</title>
<link href="https://fonts.googleapis.com/css2?family=Fredoka+One&family=Nunito:wght@400;600;700;800;900&display=swap" rel="stylesheet">
<style>
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
--bg:#0f0e17;--surface:#1a1827;--card:#22203a;
--accent:#f5a623;--accent2:#7c3aed;--accent3:#10b981;
--danger:#ef4444;--text:#fffffe;--muted:#a7a3c2;--border:#2e2b4a;--radius:16px;
}
html,body{height:100%;margin:0;padding:0}
body{
color:var(--text);font-family:'Nunito',sans-serif;
background:var(--bg);
background-image:radial-gradient(ellipse at 20% 10%,rgba(124,58,237,0.18) 0%,transparent 50%),radial-gradient(ellipse at 80% 90%,rgba(245,166,35,0.10) 0%,transparent 50%);
background-attachment:fixed;
display:flex;flex-direction:column;height:100vh;overflow:hidden;
}
/* ─── SPLIT LAYOUT ─── */
#splitWrap{
display:flex;flex-direction:row;flex:1 1 0;overflow:hidden;min-height:0;width:100%;
}
#editorPane{
flex:0 0 65%;width:65%;overflow-y:auto;overflow-x:hidden;min-width:0;
border-right:1px solid var(--border);
order:1;
scrollbar-width:thin;scrollbar-color:rgba(124,58,237,0.3) transparent;
}
#editorPane::-webkit-scrollbar{width:5px}
#editorPane::-webkit-scrollbar-thumb{background:rgba(124,58,237,0.25);border-radius:3px}
#editorPane::-webkit-scrollbar-thumb:hover{background:rgba(124,58,237,0.5)}
#resizerBar{
flex:0 0 5px;width:5px;background:var(--border);cursor:col-resize;
transition:background 0.2s;user-select:none;
display:flex;align-items:center;justify-content:center;
position:relative;z-index:10;order:2;
}
#resizerBar:hover,#resizerBar.dragging{background:var(--accent2);}
#resizerBar::after{
content:'⋮';color:rgba(255,255,255,0.25);font-size:1.1rem;letter-spacing:-2px;
pointer-events:none;
}
#codePane{
flex:1 1 0;min-width:0;overflow:hidden;display:flex;flex-direction:column;
background:#0d0c1a;order:3;
}
/* ─── PROGRESS BAR ─── */
#progressBar{position:relative;z-index:200;flex-shrink:0;width:100%;box-sizing:border-box;background:rgba(15,14,23,0.95);backdrop-filter:blur(14px);border-bottom:1px solid rgba(255,255,255,0.07);padding:10px 24px}
.pb-inner{max-width:100%;margin:0 auto}
.pb-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}
.pb-logo{font-family:'Fredoka One',cursive;font-size:0.95rem;color:var(--accent);display:flex;align-items:center;gap:8px}
.pb-phwg{display:flex;align-items:center;gap:10px}
.pb-phwg img{height:32px;width:auto;object-fit:contain;opacity:0.92}
.pb-phwg-text{display:flex;flex-direction:column;gap:1px}
.pb-phwg-studiengaenge{font-size:9px;font-weight:700;color:var(--muted);letter-spacing:0.3px;line-height:1.4}
.pb-phwg-studiengaenge span{color:rgba(245,166,35,0.7)}
@media(max-width:640px){.pb-phwg-text{display:none}}
.pb-steps{display:flex;align-items:center;gap:0}
.pb-step{display:flex;align-items:center;gap:7px;flex:1;cursor:default;opacity:0.38;transition:opacity 0.3s}
.pb-step.done{opacity:0.7;cursor:pointer}
.pb-step.done:hover{opacity:1}
.pb-step.active{opacity:1}
.pb-dot{width:28px;height:28px;border-radius:50%;border:2.5px solid var(--muted);display:flex;align-items:center;justify-content:center;font-family:'Fredoka One',cursive;font-size:0.85rem;flex-shrink:0;transition:all 0.3s}
.pb-step.active .pb-dot{border-color:var(--accent);background:var(--accent);color:#000;box-shadow:0 0 12px rgba(245,166,35,0.5)}
.pb-step.done .pb-dot{border-color:var(--accent3);background:var(--accent3);color:#fff}
.pb-label{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:0.5px;white-space:nowrap}
.pb-step.active .pb-label{color:var(--accent)}
.pb-step.done .pb-label{color:var(--accent3)}
.pb-connector{flex:1;height:2px;background:var(--border);margin:0 6px;transition:background 0.4s;min-width:12px}
.pb-connector.done{background:var(--accent3)}
@media(max-width:580px){.pb-label{display:none}}
.pb-track{height:3px;background:var(--border);border-radius:999px;margin-top:10px;overflow:hidden}
.pb-fill{height:100%;background:linear-gradient(90deg,var(--accent3),var(--accent));border-radius:999px;transition:width 0.5s cubic-bezier(0.34,1.56,0.64,1)}
/* ─── SCREENS ─── */
.screen{display:none;max-width:680px;margin:0 auto;padding:32px 16px 80px}
.screen.active{display:block}
.slide-in{animation:slideIn 0.38s cubic-bezier(0.16,1,0.3,1) both}
.slide-out{animation:slideOut 0.22s ease both}
@keyframes slideIn{from{opacity:0;transform:translateX(40px)}to{opacity:1;transform:translateX(0)}}
@keyframes slideOut{from{opacity:1;transform:translateX(0)}to{opacity:0;transform:translateX(-30px)}}
@keyframes fadeUp{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}
@keyframes popIn{from{opacity:0;transform:scale(0.9)}to{opacity:1;transform:scale(1)}}
@keyframes float{0%,100%{transform:translateY(0)}50%{transform:translateY(-10px)}}
/* ─── SCREEN HEADER ─── */
.sh{text-align:center;margin-bottom:28px}
.sh-badge{display:inline-block;background:var(--accent2);color:#fff;font-size:11px;font-weight:700;letter-spacing:2px;text-transform:uppercase;padding:4px 14px;border-radius:999px;margin-bottom:12px}
.sh-title{font-family:'Fredoka One',cursive;font-size:clamp(1.8rem,4vw,2.5rem)}
.sh-title em{color:var(--accent);font-style:normal}
.sh-sub{color:var(--muted);font-size:14px;margin-top:8px;line-height:1.6}
/* ─── STEP SUMMARY BANNER ─── */
.summary-banner{background:linear-gradient(135deg,rgba(16,185,129,0.12),rgba(16,185,129,0.04));border:1.5px solid rgba(16,185,129,0.4);border-radius:14px;padding:18px 22px;margin-bottom:20px;display:none;animation:fadeUp 0.4s ease both}
.summary-banner.visible{display:block}
.sb-title{font-family:'Fredoka One',cursive;font-size:1.1rem;color:var(--accent3);margin-bottom:8px;display:flex;align-items:center;gap:8px}
.sb-chips{display:flex;gap:8px;flex-wrap:wrap}
.sb-chip{background:rgba(16,185,129,0.15);border:1px solid rgba(16,185,129,0.3);border-radius:8px;padding:4px 12px;font-size:12px;font-weight:700;color:var(--accent3)}
/* ─── CARD ─── */
.card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius);padding:26px;margin-bottom:18px}
.card-title{font-family:'Fredoka One',cursive;font-size:1.15rem;margin-bottom:5px;display:flex;align-items:center;gap:10px}
.card-sub{color:var(--muted);font-size:13px;margin-bottom:18px;line-height:1.6}
.divider{height:1px;background:var(--border);margin:20px 0}
/* ─── FORM ─── */
label.lbl{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:0.8px;color:var(--muted);margin-bottom:7px;display:block}
.finput,.ftarea{width:100%;background:var(--surface);border:1.5px solid var(--border);border-radius:10px;color:var(--text);font-family:'Nunito',sans-serif;font-size:15px;font-weight:600;padding:12px 16px;outline:none;transition:border-color 0.2s,box-shadow 0.2s}
.finput:focus,.ftarea:focus{border-color:var(--accent2);box-shadow:0 0 0 3px rgba(124,58,237,0.14)}
.finput::placeholder,.ftarea::placeholder{color:#4a476a}
.ftarea{resize:none}
.char-row{display:flex;justify-content:flex-end;font-size:11px;color:var(--muted);margin-top:4px}
.char-row.warn{color:var(--accent)}
/* ─── NAV BUTTONS ─── */
.btn-row{display:flex;justify-content:space-between;gap:12px;margin-top:28px}
.btn-back{background:var(--surface);color:var(--muted);font-family:'Fredoka One',cursive;font-size:1rem;border:1.5px solid var(--border);border-radius:12px;padding:13px 24px;cursor:pointer;transition:all 0.2s}
.btn-back:hover{border-color:var(--muted);color:var(--text)}
.btn-next{background:linear-gradient(135deg,var(--accent2),var(--accent));color:#fff;font-family:'Fredoka One',cursive;font-size:1rem;border:none;border-radius:12px;padding:14px 32px;cursor:pointer;display:flex;align-items:center;gap:8px;transition:transform 0.15s,box-shadow 0.15s,opacity 0.2s;box-shadow:0 4px 20px rgba(124,58,237,0.35)}
.btn-next:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 8px 28px rgba(124,58,237,0.45)}
.btn-next:disabled{opacity:0.32;cursor:not-allowed;transform:none}
/* ─── PREVIEW CARD ─── */
.preview-card{background:linear-gradient(135deg,rgba(124,58,237,0.15),rgba(245,166,35,0.08));border:1px solid rgba(124,58,237,0.35);border-radius:14px;padding:18px 22px;margin-bottom:18px;animation:fadeUp 0.3s ease both}
.preview-card .pv-label{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:1px;color:var(--accent2);margin-bottom:6px}
.preview-card .pv-name{font-family:'Fredoka One',cursive;font-size:1.5rem;color:var(--accent)}
.preview-card .pv-desc{font-size:13px;color:var(--muted);margin-top:4px;line-height:1.5}
/* ─── SUGGESTIONS ─── */
.suggestions{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
.sug{background:var(--surface);border:1px solid var(--border);border-radius:7px;padding:4px 12px;font-size:12px;color:var(--muted);cursor:pointer;transition:all 0.15s}
.sug:hover{border-color:var(--accent2);color:var(--text)}
/* ─── SELECTION GRID (step 2) ─── */
.sel-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(90px,1fr));gap:9px;margin-bottom:14px}
.sel-card{background:var(--surface);border:2px solid var(--border);border-radius:12px;padding:14px 6px;text-align:center;cursor:pointer;transition:all 0.2s;user-select:none}
.sel-card:hover{border-color:var(--accent2);transform:translateY(-2px)}
.sel-card.selected{border-color:var(--accent);background:rgba(245,166,35,0.07);box-shadow:0 0 14px rgba(245,166,35,0.2)}
.sel-card .se{font-size:1.9rem;display:block;margin-bottom:5px}
.sel-card .sl{font-size:11px;font-weight:700;color:var(--muted)}
.sel-card.selected .sl{color:var(--accent)}
.combo-preview{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:18px;text-align:center;margin-top:10px;animation:popIn 0.3s ease both}
.combo-preview .cp-scene{font-size:3rem;display:block;margin-bottom:6px;animation:float 3s ease-in-out infinite}
.combo-preview .cp-label{font-size:12px;color:var(--muted);font-weight:700}
/* ─── RULES (step 3) ─── */
.rules-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:4px}
@media(max-width:560px){.rules-grid{grid-template-columns:1fr}}
.rule-block{background:var(--surface);border:1.5px solid var(--border);border-radius:12px;padding:15px}
.rule-block-title{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:0.8px;color:var(--muted);margin-bottom:11px}
.toggle-group{display:flex;flex-direction:column;gap:8px}
.toggle-option{display:flex;align-items:center;gap:9px;padding:10px 12px;border-radius:9px;border:2px solid var(--border);cursor:pointer;transition:all 0.2s;user-select:none}
.toggle-option:hover{border-color:var(--accent2)}
.toggle-option.selected{border-color:var(--accent);background:rgba(245,166,35,0.07)}
.tog-emoji{font-size:1.2rem;flex-shrink:0}
.tog-text{font-size:13px;font-weight:700}
.tog-sub{font-size:11px;color:var(--muted)}
.tog-check{margin-left:auto;width:18px;height:18px;border-radius:50%;border:2px solid var(--border);transition:all 0.2s;flex-shrink:0}
.toggle-option.selected .tog-check{background:var(--accent);border-color:var(--accent)}
.sub-opts{display:none;gap:7px;margin-top:9px;flex-wrap:wrap}
.sub-opts.visible{display:flex}
.sub-opt{background:var(--card);border:1.5px solid var(--border);border-radius:8px;padding:6px 13px;font-size:13px;font-weight:700;cursor:pointer;transition:all 0.15s;color:var(--muted)}
.sub-opt:hover{border-color:var(--accent2);color:var(--text)}
.sub-opt.selected{border-color:var(--accent);color:var(--accent);background:rgba(245,166,35,0.07)}
.count-row{display:flex;align-items:center;gap:14px;background:var(--surface);border:1.5px solid var(--border);border-radius:12px;padding:14px 18px;margin-bottom:18px}
.count-row label{font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:0.5px;color:var(--muted)}
.count-ctrl{display:flex;align-items:center;gap:10px;margin-left:auto}
.cnt-btn{width:36px;height:36px;border-radius:8px;background:var(--card);border:1.5px solid var(--border);color:var(--text);font-size:1.2rem;font-weight:800;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all 0.15s}
.cnt-btn:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}
.cnt-btn:disabled{opacity:0.3;cursor:not-allowed}
.cnt-val{font-family:'Fredoka One',cursive;font-size:1.8rem;color:var(--accent);min-width:36px;text-align:center}
/* ─── PALETTE ─── */
.pal-tabs{display:flex;gap:8px;margin-bottom:12px}
.pal-tab{background:var(--surface);border:1.5px solid var(--border);border-radius:9px;padding:7px 16px;font-size:12px;font-weight:800;cursor:pointer;color:var(--muted);transition:all 0.2s;text-transform:uppercase;letter-spacing:0.5px}
.pal-tab.active{background:var(--accent2);border-color:var(--accent2);color:#fff}
.pal-panel{display:none}
.pal-panel.active{display:grid;grid-template-columns:repeat(auto-fill,minmax(105px,1fr));gap:9px;margin-bottom:18px}
.mg-card{background:var(--surface);border:2px solid var(--border);border-radius:11px;padding:11px 7px 8px;display:flex;flex-direction:column;align-items:center;gap:4px;cursor:grab;transition:all 0.2s;user-select:none;position:relative}
.mg-card:hover:not(.disabled){border-color:var(--accent2);transform:translateY(-2px);box-shadow:0 5px 18px rgba(124,58,237,0.2)}
.mg-card.click-sel{outline:3px solid var(--accent);outline-offset:2px;background:rgba(245,166,35,0.06)}
.mg-card.disabled{opacity:0.28;cursor:not-allowed;filter:grayscale(0.5);pointer-events:none}
.mg-emoji{font-size:1.6rem;pointer-events:none}
.mg-lbl{font-size:11px;font-weight:700;color:var(--muted);text-align:center;line-height:1.3;pointer-events:none}
.mg-tag{font-size:9px;font-weight:800;letter-spacing:0.5px;text-transform:uppercase;padding:2px 7px;border-radius:999px;pointer-events:none}
.mg-tag.once{background:rgba(239,68,68,0.2);color:#f87171}
.mg-tag.multi{background:rgba(16,185,129,0.2);color:var(--accent3)}
.mg-tag.unlim{background:rgba(245,166,35,0.2);color:var(--accent)}
.mg-tag.story-tag{background:rgba(6,182,212,0.2);color:#22d3ee}
.use-count{position:absolute;top:4px;right:4px;background:var(--accent);color:#000;font-size:10px;font-weight:900;width:17px;height:17px;border-radius:50%;display:none;align-items:center;justify-content:center;pointer-events:none}
.mg-card.used .use-count{display:flex}
.story-counter{display:inline-flex;align-items:center;gap:5px;background:rgba(6,182,212,0.12);border:1px solid rgba(6,182,212,0.4);border-radius:999px;padding:3px 10px;font-size:11px;font-weight:800;color:#22d3ee}
.story-counter.maxed{background:rgba(239,68,68,0.12);border-color:var(--danger);color:var(--danger)}
.sec-label{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:1px;color:var(--muted);margin-bottom:10px;display:flex;align-items:center;justify-content:space-between}
/* ─── BOARD ─── */
.board-builder{display:flex;flex-direction:column;gap:2px}
.drop-zone{height:10px;border-radius:7px;border:2px dashed transparent;transition:all 0.2s;display:flex;align-items:center;justify-content:center;font-size:11px;color:transparent;font-weight:700;cursor:pointer}
.drop-zone.story-hoverable{height:28px;border-color:rgba(6,182,212,0.3);color:rgba(6,182,212,0.4)}
.drop-zone.drag-over{height:38px;background:rgba(6,182,212,0.12);border-color:#22d3ee;color:#22d3ee}
.field-row{display:flex;align-items:center;gap:10px;background:var(--surface);border:1.5px solid var(--border);border-radius:9px;padding:9px 13px;transition:all 0.2s;cursor:pointer}
.field-row:hover:not(.start-f):not(.end-f){border-color:var(--accent2)}
.field-row.filled{border-color:rgba(124,58,237,0.5)}
.field-row.start-f{border-color:var(--accent3);cursor:default}
.field-row.end-f{border-color:var(--accent);cursor:default}
.field-row.drag-target{background:rgba(124,58,237,0.1);border-color:var(--accent)!important;border-style:dashed}
.f-num{font-family:'Fredoka One',cursive;font-size:0.85rem;color:var(--muted);min-width:54px;flex-shrink:0}
.field-row.start-f .f-num{color:var(--accent3)}
.field-row.end-f .f-num{color:var(--accent)}
.f-icon{font-size:1.2rem;min-width:26px;text-align:center;flex-shrink:0}
.f-name{font-size:13px;font-weight:700;flex:1}
.f-empty{color:var(--muted);font-style:italic;font-weight:400}
.f-clear{background:none;border:none;color:var(--muted);cursor:pointer;font-size:0.9rem;padding:4px 6px;border-radius:6px;transition:all 0.15s;display:none}
.field-row.filled .f-clear{display:block}
.f-clear:hover{color:var(--danger);background:rgba(239,68,68,0.1)}
.story-row{display:flex;align-items:flex-start;gap:10px;background:rgba(6,182,212,0.07);border:1.5px solid rgba(6,182,212,0.4);border-radius:9px;padding:11px 13px;animation:fadeUp 0.25s ease both}
.story-icon{font-size:1.3rem;cursor:pointer;transition:transform 0.2s;flex-shrink:0;margin-top:2px}
.story-icon:hover{transform:scale(1.2)}
.story-content{flex:1}
.story-lbl{font-size:9px;font-weight:800;text-transform:uppercase;letter-spacing:1px;color:#22d3ee;margin-bottom:4px}
.story-ta{width:100%;background:rgba(6,182,212,0.06);border:1.5px solid rgba(6,182,212,0.3);border-radius:7px;color:var(--text);font-family:'Nunito',sans-serif;font-size:13px;font-weight:600;padding:7px 10px;resize:none;outline:none;transition:border-color 0.2s}
.story-ta:focus{border-color:#22d3ee}
.story-ta::placeholder{color:#3a6e7a}
.story-meta{display:flex;align-items:center;gap:6px;margin-top:5px}
.story-pos-lbl{font-size:10px;font-weight:700;color:#22d3ee;background:rgba(6,182,212,0.12);padding:2px 8px;border-radius:999px}
.story-chars{font-size:10px;color:var(--muted);margin-left:auto}
.story-clear{background:none;border:none;color:var(--muted);cursor:pointer;font-size:0.85rem;padding:4px;border-radius:5px;transition:all 0.15s;flex-shrink:0}
.story-clear:hover{color:var(--danger);background:rgba(239,68,68,0.1)}
.emoji-picker{position:fixed;background:var(--card);border:1.5px solid var(--border);border-radius:12px;padding:10px;display:grid;grid-template-columns:repeat(6,1fr);gap:4px;z-index:1000;box-shadow:0 8px 30px rgba(0,0,0,0.5);display:none}
.emoji-picker.open{display:grid}
.ep-it{font-size:1.2rem;cursor:pointer;padding:4px;border-radius:6px;text-align:center;transition:background 0.15s}
.ep-it:hover{background:var(--surface)}
.board-stats{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}
.stat-pill{background:var(--surface);border:1px solid var(--border);border-radius:999px;padding:5px 13px;font-size:12px;font-weight:700;color:var(--muted);display:flex;align-items:center;gap:5px}
.stat-pill span{color:var(--text)}
#dragGhost{position:fixed;pointer-events:none;z-index:9999;background:var(--card);border:2px solid var(--accent);border-radius:10px;padding:7px 14px;font-size:1rem;display:flex;align-items:center;gap:7px;box-shadow:0 8px 28px rgba(0,0,0,0.6);transform:translate(-50%,-50%);opacity:0;transition:opacity 0.1s;font-family:'Nunito',sans-serif;font-weight:700;color:var(--text)}
/* ─── QUIZ (step 4) ─── */
.quiz-card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius);padding:22px;margin-bottom:14px;position:relative;overflow:hidden}
.quiz-card::before{content:'';position:absolute;left:0;top:0;bottom:0;width:4px;background:linear-gradient(180deg,var(--accent2),var(--accent))}
.quiz-card.complete::before{background:linear-gradient(180deg,var(--accent3),#059669)}
.qc-head{display:flex;align-items:center;gap:10px;margin-bottom:14px}
.qc-num{width:32px;height:32px;border-radius:50%;background:linear-gradient(135deg,var(--accent2),var(--accent));color:#fff;font-family:'Fredoka One',cursive;font-size:0.9rem;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.quiz-card.complete .qc-num{background:linear-gradient(135deg,var(--accent3),#059669)}
.qc-title{font-family:'Fredoka One',cursive;font-size:1rem;flex:1}
.qc-status{font-size:11px;font-weight:800;text-transform:uppercase;padding:3px 9px;border-radius:999px}
.qc-status.done{background:rgba(16,185,129,0.12);color:var(--accent3);border:1px solid var(--accent3)}
.qc-status.todo{background:rgba(245,166,35,0.08);color:var(--accent);border:1px solid var(--accent)}
.q-input{width:100%;background:var(--surface);border:1.5px solid var(--border);border-radius:9px;color:var(--text);font-family:'Nunito',sans-serif;font-size:14px;font-weight:600;padding:11px 13px;outline:none;transition:border-color 0.2s,box-shadow 0.2s;margin-bottom:12px;resize:none}
.q-input:focus{border-color:var(--accent2);box-shadow:0 0 0 3px rgba(124,58,237,0.12)}
.q-input::placeholder{color:#4a476a}
.ans-grid{display:grid;grid-template-columns:1fr 1fr;gap:7px;margin-bottom:12px}
@media(max-width:480px){.ans-grid{grid-template-columns:1fr}}
.ans-wrap{position:relative}
.ans-letter{position:absolute;left:10px;top:50%;transform:translateY(-50%);font-family:'Fredoka One',cursive;font-size:0.85rem;width:22px;height:22px;border-radius:6px;display:flex;align-items:center;justify-content:center;background:var(--border);color:var(--muted);pointer-events:none;z-index:1;transition:all 0.2s}
.ans-wrap.correct .ans-letter{background:var(--accent3);color:#fff}
.ans-input{width:100%;background:var(--surface);border:1.5px solid var(--border);border-radius:9px;color:var(--text);font-family:'Nunito',sans-serif;font-size:13px;font-weight:600;padding:9px 11px 9px 40px;outline:none;transition:border-color 0.2s}
.ans-input:focus{border-color:var(--accent2)}
.ans-wrap.correct .ans-input{border-color:var(--accent3);background:rgba(16,185,129,0.06)}
.correct-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.correct-lbl{font-size:12px;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:0.5px}
.correct-btns{display:flex;gap:7px}
.correct-btn{width:33px;height:33px;border-radius:8px;background:var(--surface);border:1.5px solid var(--border);font-family:'Fredoka One',cursive;font-size:0.85rem;color:var(--muted);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all 0.2s}
.correct-btn:hover{border-color:var(--accent3);color:var(--accent3)}
.correct-btn.selected{background:var(--accent3);border-color:var(--accent3);color:#fff;box-shadow:0 0 10px rgba(16,185,129,0.35)}
.tips-btn{background:none;border:none;color:var(--accent2);font-size:12px;font-weight:800;cursor:pointer;padding:0;margin-top:10px;display:flex;align-items:center;gap:5px;text-transform:uppercase;letter-spacing:0.5px}
.tips-box{background:rgba(124,58,237,0.07);border:1px solid rgba(124,58,237,0.25);border-radius:9px;padding:11px 13px;margin-top:7px;font-size:13px;color:var(--muted);line-height:1.7;display:none}
.tips-box.open{display:block}
.no-quiz{text-align:center;padding:36px 20px}
.no-quiz .nq-icon{font-size:3rem;margin-bottom:10px}
.no-quiz h3{font-family:'Fredoka One',cursive;font-size:1.2rem;color:var(--muted);margin-bottom:6px}
.af-bar{display:flex;align-items:center;gap:12px;background:var(--surface);border:1px solid var(--border);border-radius:11px;padding:13px 16px;margin-bottom:14px}
.af-icon{font-size:1.4rem;flex-shrink:0}
.af-text .af-title{font-family:'Fredoka One',cursive;font-size:0.95rem}
.af-text .af-sub{font-size:12px;color:var(--muted)}
.btn-sm{background:linear-gradient(135deg,var(--accent2),var(--accent));color:#fff;font-family:'Fredoka One',cursive;font-size:0.85rem;border:none;border-radius:8px;padding:9px 16px;cursor:pointer;transition:transform 0.15s;white-space:nowrap;flex-shrink:0}
.btn-sm:hover{transform:translateY(-1px)}
.ov-bar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.ov-pill{background:var(--card);border:1px solid var(--border);border-radius:999px;padding:5px 13px;font-size:12px;font-weight:700;color:var(--muted);display:flex;align-items:center;gap:5px}
.ov-pill span{color:var(--text)}
.ov-pill.good span{color:var(--accent3)}
.ov-pill.warn span{color:var(--accent)}
/* ─── REVIEW + TEST (step 5) ─── */
.hero-card{background:linear-gradient(135deg,rgba(124,58,237,0.18),rgba(245,166,35,0.08));border:1px solid rgba(124,58,237,0.35);border-radius:var(--radius);padding:26px;margin-bottom:18px;display:flex;align-items:center;gap:18px}
.hero-scene{font-size:3rem;line-height:1;flex-shrink:0;position:relative}
.hero-fig{position:absolute;bottom:-4px;right:-14px;font-size:2rem}
.hero-info .hi-name{font-family:'Fredoka One',cursive;font-size:1.7rem;color:var(--accent)}
.hero-info .hi-desc{color:var(--muted);font-size:13px;margin-top:4px;line-height:1.5}
.hero-tags{display:flex;gap:7px;flex-wrap:wrap;margin-top:9px}
.hero-tag{background:rgba(124,58,237,0.18);border:1px solid rgba(124,58,237,0.3);border-radius:999px;padding:3px 11px;font-size:11px;font-weight:700;color:#c4b5fd}
.info-grid{display:grid;grid-template-columns:1fr 1fr;gap:9px}
@media(max-width:500px){.info-grid{grid-template-columns:1fr}}
.info-block{background:var(--surface);border:1px solid var(--border);border-radius:11px;padding:13px}
.ib-lbl{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:1px;color:var(--muted);margin-bottom:4px}
.ib-val{font-family:'Fredoka One',cursive;font-size:1.05rem}
.tl{display:flex;flex-direction:column}
.tl-item{display:flex;align-items:flex-start;gap:11px;padding:7px 0;position:relative}
.tl-item:not(:last-child)::after{content:'';position:absolute;left:16px;top:38px;bottom:-7px;width:2px;background:var(--border)}
.tl-item.story-it:not(:last-child)::after{background:rgba(6,182,212,0.3)}
.tl-dot{width:34px;height:34px;border-radius:50%;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:0.95rem;border:2px solid var(--border);background:var(--surface)}
.tl-dot.s{background:rgba(16,185,129,0.12);border-color:var(--accent3)}
.tl-dot.e{background:rgba(245,166,35,0.12);border-color:var(--accent)}
.tl-dot.st{background:rgba(6,182,212,0.12);border-color:#22d3ee}
.tl-dot.g{background:rgba(124,58,237,0.12);border-color:var(--accent2)}
.tl-dot.em{opacity:0.35}
.tl-lbl{font-size:13px;font-weight:800;padding-top:6px}
.tl-lbl.s{color:var(--accent3)}.tl-lbl.e{color:var(--accent)}.tl-lbl.st{color:#22d3ee}.tl-lbl.g,.tl-lbl.em{color:var(--muted)}
.tl-sub{font-size:12px;color:var(--muted);margin-top:1px;line-height:1.5}
.tl-badge{display:inline-block;background:rgba(124,58,237,0.12);border:1px solid var(--accent2);border-radius:6px;padding:2px 7px;font-size:10px;font-weight:800;color:var(--accent2);margin-top:2px;text-transform:uppercase;letter-spacing:0.5px}
.tl-badge.st{background:rgba(6,182,212,0.1);border-color:#22d3ee;color:#22d3ee}
.qp-list{display:flex;flex-direction:column;gap:7px}
.qp-item{background:var(--surface);border:1px solid var(--border);border-radius:9px;padding:11px 13px}
.qp-q{font-size:13px;font-weight:700;margin-bottom:6px}
.qp-ans-grid{display:grid;grid-template-columns:1fr 1fr;gap:4px}
.qp-ans{font-size:11px;padding:4px 8px;border-radius:6px;background:var(--card);border:1px solid var(--border);color:var(--muted);display:flex;align-items:center;gap:4px}
.qp-ans.cor{background:rgba(16,185,129,0.1);border-color:var(--accent3);color:var(--accent3);font-weight:700}
.checklist{display:flex;flex-direction:column;gap:6px}
.chk-item{background:var(--surface);border:1px solid var(--border);border-radius:9px;padding:9px 13px;display:flex;align-items:center;gap:8px;font-size:13px}
.chk-item.ok{border-color:rgba(16,185,129,0.3);color:var(--accent3)}
.chk-item.warn{border-color:rgba(245,166,35,0.3);color:var(--accent)}
/* ─── LAUNCH CARD ─── */
.launch-hero{background:linear-gradient(135deg,rgba(124,58,237,0.22),rgba(245,166,35,0.1));border-bottom:1px solid var(--border);padding:30px;text-align:center;position:relative;overflow:hidden}
.launch-hero::before{content:'';position:absolute;inset:0;background:radial-gradient(ellipse at 50% 0%,rgba(124,58,237,0.28),transparent 70%)}
.lh-fig{font-size:3.8rem;display:block;margin-bottom:9px;animation:float 3s ease-in-out infinite;position:relative;z-index:1}
.lh-name{font-family:'Fredoka One',cursive;font-size:1.7rem;color:var(--accent);position:relative;z-index:1}
.lh-desc{color:var(--muted);font-size:13px;margin-top:4px;max-width:360px;margin-left:auto;margin-right:auto;line-height:1.5;position:relative;z-index:1}
.lh-pills{display:flex;gap:7px;justify-content:center;flex-wrap:wrap;margin-top:11px;position:relative;z-index:1}
.lh-pill{background:rgba(255,255,255,0.08);border:1px solid rgba(255,255,255,0.13);border-radius:999px;padding:4px 12px;font-size:12px;font-weight:700;color:rgba(255,255,255,0.72)}
.launch-body{padding:22px 26px}
.launch-chk{display:flex;flex-direction:column;gap:6px;margin-bottom:18px}
.lc-item{display:flex;align-items:center;gap:9px;background:var(--surface);border:1px solid var(--border);border-radius:9px;padding:9px 13px;font-size:13px;font-weight:700}
.lc-check{color:var(--accent3);margin-left:auto}
.btn-launch{width:100%;background:linear-gradient(135deg,var(--accent2),var(--accent));color:#fff;font-family:'Fredoka One',cursive;font-size:1.15rem;border:none;border-radius:13px;padding:17px;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:9px;box-shadow:0 5px 26px rgba(124,58,237,0.4);transition:transform 0.15s,box-shadow 0.15s,opacity 0.2s;position:relative;overflow:hidden}
.btn-launch::after{content:'';position:absolute;inset:0;background:linear-gradient(135deg,rgba(255,255,255,0.1),transparent)}
.btn-launch:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 9px 32px rgba(124,58,237,0.5)}
.btn-launch:disabled{opacity:0.5;cursor:not-allowed;transform:none}
.btn-launch-sub{text-align:center;font-size:12px;color:var(--muted);margin-top:7px;font-weight:700}
.played-badge{display:none;background:rgba(16,185,129,0.1);border:1px solid var(--accent3);border-radius:9px;padding:11px 15px;margin-top:12px;font-size:13px;font-weight:700;color:var(--accent3);align-items:center;gap:7px}
.played-badge.visible{display:flex}
/* ─── FEEDBACK ─── */
.fb-prog{height:4px;background:var(--border);border-radius:999px;margin-bottom:22px;overflow:hidden}
.fb-prog-fill{height:100%;background:linear-gradient(90deg,var(--accent2),var(--accent));border-radius:999px;transition:width 0.4s ease}
.fb-qnum{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:1px;color:var(--accent2);margin-bottom:5px}
.fb-q{font-family:'Fredoka One',cursive;font-size:1.1rem;margin-bottom:11px;line-height:1.4}
.fb-sub{font-size:13px;color:var(--muted);margin-bottom:11px;margin-top:-5px}
.mc-opts{display:flex;flex-direction:column;gap:7px}
.mc-opt{background:var(--surface);border:2px solid var(--border);border-radius:9px;padding:11px 15px;cursor:pointer;transition:all 0.2s;display:flex;align-items:center;gap:10px;font-size:14px;font-weight:600}
.mc-opt:hover{border-color:var(--accent2)}
.mc-opt.sel{border-color:var(--accent);background:rgba(245,166,35,0.07);color:var(--accent)}
.mc-dot{width:19px;height:19px;border-radius:50%;border:2px solid var(--border);flex-shrink:0;transition:all 0.2s}
.mc-opt.sel .mc-dot{background:var(--accent);border-color:var(--accent)}
.scale-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.scale-btn{width:46px;height:46px;border-radius:9px;border:2px solid var(--border);background:var(--surface);font-family:'Fredoka One',cursive;font-size:1.05rem;cursor:pointer;color:var(--muted);transition:all 0.2s;display:flex;align-items:center;justify-content:center}
.scale-btn:hover{border-color:var(--accent2);color:var(--text)}
.scale-btn.sel{background:var(--accent);border-color:var(--accent);color:#000}
.scale-lbls{display:flex;justify-content:space-between;font-size:11px;color:var(--muted);margin-top:5px;font-weight:700}
.fb-ta{width:100%;background:var(--surface);border:1.5px solid var(--border);border-radius:9px;color:var(--text);font-family:'Nunito',sans-serif;font-size:14px;font-weight:600;padding:11px 13px;outline:none;resize:none;transition:border-color 0.2s}
.fb-ta:focus{border-color:var(--accent2)}
.fb-ta::placeholder{color:#4a476a}
.fb-nav{display:flex;gap:9px;margin-top:18px}
.btn-fb-prev{background:var(--surface);color:var(--muted);font-family:'Fredoka One',cursive;font-size:0.9rem;border:1.5px solid var(--border);border-radius:10px;padding:11px 20px;cursor:pointer;transition:all 0.2s}
.btn-fb-prev:hover{border-color:var(--muted);color:var(--text)}
.btn-fb-next{flex:1;background:linear-gradient(135deg,var(--accent2),var(--accent));color:#fff;font-family:'Fredoka One',cursive;font-size:1rem;border:none;border-radius:10px;padding:12px;cursor:pointer;transition:transform 0.15s,opacity 0.2s;box-shadow:0 4px 14px rgba(124,58,237,0.3)}
.btn-fb-next:hover:not(:disabled){transform:translateY(-1px)}
.btn-fb-next:disabled{opacity:0.32;cursor:not-allowed}
/* ─── SUMMARY ─── */
.sum-hero{text-align:center;padding:30px 22px 18px}
.sum-icon{font-size:3.5rem;display:block;margin-bottom:10px}
.sum-hero h2{font-family:'Fredoka One',cursive;font-size:1.9rem;color:var(--accent3)}
.sum-hero p{color:var(--muted);font-size:13px;margin-top:5px;line-height:1.6}
.sum-scores{display:flex;gap:9px;justify-content:center;flex-wrap:wrap;margin-top:14px}
.sum-sc{background:var(--surface);border:1px solid var(--border);border-radius:11px;padding:11px 16px;text-align:center}
.sum-val{font-family:'Fredoka One',cursive;font-size:1.5rem;color:var(--accent)}
.sum-lbl{font-size:10px;font-weight:800;text-transform:uppercase;color:var(--muted);margin-top:2px}
.sum-notes{display:flex;flex-direction:column;gap:6px;margin-bottom:18px}
.sn-item{display:flex;align-items:flex-start;gap:8px;font-size:13px;padding:8px 0;border-bottom:1px solid var(--border)}
.sn-item:last-child{border-bottom:none}
.final-btns{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
.btn-revise{background:var(--surface);color:var(--text);font-family:'Fredoka One',cursive;font-size:1rem;border:1.5px solid var(--border);border-radius:11px;padding:13px 22px;cursor:pointer;transition:all 0.2s}
.btn-revise:hover{border-color:var(--accent2)}
.btn-publish{background:linear-gradient(135deg,var(--accent3),#059669);color:#fff;font-family:'Fredoka One',cursive;font-size:1.05rem;border:none;border-radius:11px;padding:14px 28px;cursor:pointer;transition:transform 0.15s,box-shadow 0.15s;box-shadow:0 4px 18px rgba(16,185,129,0.38)}
.btn-publish:hover{transform:translateY(-2px);box-shadow:0 8px 26px rgba(16,185,129,0.48)}
/* ─── TOAST ─── */
#toast{position:fixed;bottom:22px;left:50%;transform:translateX(-50%) translateY(16px);background:rgba(16,185,129,0.96);color:#fff;font-family:'Fredoka One',cursive;font-size:0.95rem;padding:11px 26px;border-radius:11px;z-index:500;opacity:0;transition:all 0.3s;pointer-events:none;white-space:nowrap;box-shadow:0 4px 18px rgba(0,0,0,0.3)}
#toast.show{opacity:1;transform:translateX(-50%) translateY(0)}
/* ─── MINI-GAME TEST POPUP ─── */
.mg-card{position:relative;}
.mg-test-btn{display:block;width:100%;margin-top:6px;background:rgba(124,58,237,0.25);border:1px solid rgba(124,58,237,0.5);border-radius:6px;color:#c4b5fd;font-size:10px;font-weight:800;padding:4px 0;cursor:pointer;text-transform:uppercase;letter-spacing:0.5px;transition:all 0.15s;z-index:2;}
.mg-test-btn:hover{background:rgba(124,58,237,0.55);color:#fff;border-color:#7c3aed;}
.mg-card.disabled .mg-test-btn{display:none;}
#mgTestOverlay{position:fixed;inset:0;background:rgba(0,0,0,0.75);z-index:5000;display:none;align-items:center;justify-content:center;backdrop-filter:blur(4px);}
#mgTestOverlay.open{display:flex;}
#mgTestBox{background:#1a1827;border:1.5px solid #2e2b4a;border-radius:20px;padding:0;width:min(520px,95vw);max-height:90vh;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 24px 60px rgba(0,0,0,0.7);}
#mgTestHeader{display:flex;align-items:center;gap:12px;padding:18px 22px;border-bottom:1px solid #2e2b4a;background:#22203a;}
#mgTestEmoji{font-size:2rem;}
#mgTestTitle{font-family:'Fredoka One',cursive;font-size:1.3rem;color:#f5a623;flex:1;}
#mgTestClose{background:none;border:none;color:#a7a3c2;font-size:1.4rem;cursor:pointer;padding:4px 8px;border-radius:8px;transition:all 0.15s;line-height:1;}
#mgTestClose:hover{background:rgba(239,68,68,0.15);color:#ef4444;}
#mgTestBody{padding:20px;overflow-y:auto;}
#mgTestCanvas{display:block;margin:0 auto;border-radius:10px;border:1px solid #2e2b4a;}
#mgTestMsg{text-align:center;font-family:'Fredoka One',cursive;font-size:1.1rem;margin-top:14px;min-height:28px;}
#mgTestMsg.win{color:#10b981;}#mgTestMsg.lose{color:#ef4444;}
#mgTestControls{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin-top:14px;}
.mg-ctrl-btn{background:linear-gradient(135deg,#7c3aed,#f5a623);color:#fff;font-family:'Fredoka One',cursive;font-size:0.9rem;border:none;border-radius:9px;padding:10px 20px;cursor:pointer;transition:transform 0.15s;}
.mg-ctrl-btn:hover{transform:translateY(-1px);}
.mg-ctrl-btn.secondary{background:#22203a;border:1.5px solid #2e2b4a;color:#a7a3c2;}
#mgTestDesc{font-size:13px;color:#a7a3c2;text-align:center;line-height:1.6;margin-bottom:14px;}
/* ─── CODE PANE ─── */
#codePane{font-family:'Fira Code','Cascadia Code','Consolas','Monaco',monospace}
#codeHeader{
display:flex;align-items:center;justify-content:space-between;
background:#131221;border-bottom:1px solid rgba(255,255,255,0.07);
padding:9px 16px;flex-shrink:0;
}
#codeHeaderLeft{display:flex;align-items:center;gap:7px}
.code-dot{width:11px;height:11px;border-radius:50%;display:inline-block}
.code-dot.red{background:#ff5f57}.code-dot.yellow{background:#febc2e}.code-dot.green{background:#28c840}
#codeFilename{color:#a7a3c2;font-size:12px;font-weight:600;margin-left:6px;font-family:'Nunito',sans-serif}
#codeHeaderRight{display:flex;align-items:center;gap:12px}
#codeLang{font-size:11px;font-weight:700;color:var(--accent2);font-family:'Nunito',sans-serif;
background:rgba(124,58,237,0.15);border:1px solid rgba(124,58,237,0.3);border-radius:5px;padding:2px 8px}
#codeLines{font-size:10px;color:rgba(255,255,255,0.25);font-family:'Nunito',sans-serif}
#codeScroll{
display:flex;flex:1;overflow-y:auto;overflow-x:hidden;min-height:0;
scrollbar-width:thin;scrollbar-color:rgba(124,58,237,0.3) transparent;
}
#codeScroll::-webkit-scrollbar{width:5px}
#codeScroll::-webkit-scrollbar-thumb{background:rgba(124,58,237,0.3);border-radius:3px}
#codeLineNums{
padding:16px 12px 16px 10px;text-align:right;
color:rgba(255,255,255,0.15);font-size:12px;line-height:1.65;
user-select:none;flex-shrink:0;min-width:38px;border-right:1px solid rgba(255,255,255,0.05);
background:#0a0917;
}
#codeContent{
flex:1;padding:16px 16px 80px 14px;margin:0;white-space:pre;
font-size:12.5px;line-height:1.65;color:#e2e0f0;overflow-x:auto;
background:transparent;border:none;outline:none;
}
/* ── Syntax colors (applied via spans) */
.py-kw{color:#c678dd} /* keywords: def, class, if, for, return, import */
.py-fn{color:#61afef} /* function names */
.py-str{color:#98c379} /* strings */
.py-num{color:#d19a66} /* numbers */
.py-cm{color:#5c6370;font-style:italic} /* comments */
.py-var{color:#e06c75} /* variables (left of =) */
.py-val{color:#abb2bf} /* plain values */
.py-punc{color:#abb2bf} /* punctuation */
.py-cls{color:#e5c07b} /* class names */
.py-dec{color:#56b6c2} /* decorators / special */
.py-hi{ /* active/focused line highlight */
background:rgba(245,166,35,0.13);display:inline-block;width:100%;
border-left:3px solid var(--accent);padding-left:6px;margin-left:-6px;
animation:codeFlash 0.4s ease both;
}
@keyframes codeFlash{
0% {background:rgba(245,166,35,0.35);border-left-color:var(--accent)}
100%{background:rgba(245,166,35,0.10);border-left-color:var(--accent)}
}
#codeFooter{
display:flex;align-items:center;justify-content:space-between;
background:#0d0c1a;border-top:1px solid rgba(255,255,255,0.05);
padding:5px 14px;flex-shrink:0;
}
#codeStatus{font-size:10px;color:var(--accent3);font-weight:700;font-family:'Nunito',sans-serif;display:flex;align-items:center;gap:5px}
#codeInfo{font-size:10px;color:rgba(255,255,255,0.2);font-family:'Nunito',sans-serif}
/* typing cursor in code */
.py-cursor{display:inline-block;width:2px;height:14px;background:var(--accent2);vertical-align:middle;animation:blink 1s step-end infinite;margin-left:1px}
@keyframes blink{0%,100%{opacity:1}50%{opacity:0}}
/* Responsive: hide code pane on small screens */
@media(max-width:900px){
#resizerBar,#codePane{display:none}
#editorPane{flex:1;border-right:none}
}
</style>
</head>
<body>
<!-- ═══ PROGRESS BAR ═══ -->
<div id="progressBar">
<div class="pb-inner">
<div class="pb-top">
<div class="pb-logo" style="display:flex;align-items:center;gap:12px">
<span>🎲 Spiel-Generator <span style="color:var(--muted);font-size:0.75rem;font-family:'Nunito',sans-serif;font-weight:700">— Dein Spiel, deine Regeln</span></span>
<button onclick="resetAll()" title="Alles zurücksetzen" style="background:rgba(239,68,68,0.12);border:1px solid rgba(239,68,68,0.3);color:#ef4444;font-size:10px;font-weight:800;font-family:'Nunito',sans-serif;border-radius:6px;padding:3px 9px;cursor:pointer;letter-spacing:0.5px;transition:all 0.2s" onmouseover="this.style.background='rgba(239,68,68,0.25)'" onmouseout="this.style.background='rgba(239,68,68,0.12)'">↺ Reset</button>
</div>
<div class="pb-phwg">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABOIAAAHfCAYAAAD9WneSAAEAAElEQVR4nOz9WZBkWX7fd37Pcq+7xx6RkXtWZe1VXYXesTQBNAgQ4gISFEgKpGgiJZISZdKYzTzpYV7GxmxszOZxbGxexqQxk0y0mdHIhiIH1IgECRGCBAEQQYAAG+i9umvpWnOP1d3vPef85+Fcj4xcqiqzuqqyO/P3McuO6lg8PK7fe/3e//kvICIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi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SZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSdK95/8DXGICUCSJF7cAAAAASUVORK5CYII=" alt="PH Weingarten"/>
<div class="pb-phwg-text">
<div class="pb-phwg-studiengaenge"><span>Medien- und Bildungsmanagement</span></div>
<div class="pb-phwg-studiengaenge"><span>Informatik (Lehramt)</span></div>
</div>
</div>
</div>
<div class="pb-steps">
<div class="pb-step active" id="pb0" onclick="pbClick(0)"><div class="pb-dot">1</div><span class="pb-label">Grundinfos</span></div>
<div class="pb-connector" id="pbc0"></div>
<div class="pb-step" id="pb1" onclick="pbClick(1)"><div class="pb-dot">2</div><span class="pb-label">Gestaltung</span></div>
<div class="pb-connector" id="pbc1"></div>
<div class="pb-step" id="pb2" onclick="pbClick(2)"><div class="pb-dot">3</div><span class="pb-label">Spielfeld</span></div>
<div class="pb-connector" id="pbc2"></div>
<div class="pb-step" id="pb3" onclick="pbClick(3)"><div class="pb-dot">4</div><span class="pb-label">Quiz</span></div>
<div class="pb-connector" id="pbc3"></div>
<div class="pb-step" id="pb4" onclick="pbClick(4)"><div class="pb-dot">5</div><span class="pb-label">Testen</span></div>
</div>
<div class="pb-track"><div class="pb-fill" id="pbFill" style="width:10%"></div></div>
</div>
</div>
</div>
<div id="splitWrap">
<div id="editorPane">
<div id="dragGhost"></div>
<div class="emoji-picker" id="emojiPicker"></div>
<div id="toast">✅ Gespeichert!</div>
<!-- ════════════ SCREEN 1: GRUNDINFOS ════════════ -->
<div class="screen active" id="s0">
<div class="sh">
<div class="sh-badge">Schritt 1 von 5</div>
<h1 class="sh-title">Dein Spiel <em>beginnt hier ✨</em></h1>
<p class="sh-sub">Erstmal wichtig: Wer bist du? Dann gib deinem Spiel einen Namen.</p>
</div>
<div class="card" style="background:linear-gradient(135deg,rgba(124,58,237,0.12),rgba(245,166,35,0.06));border-color:rgba(124,58,237,0.4)">
<div class="card-title">👋 Hallo! Wie heißt du?</div>
<p class="card-sub">Dein Name oder Nickname — er erscheint auf deinem Spiel als Entwickler:in!</p>
<input class="finput" id="s1devname" type="text" onfocus="setCodeFocus('dev')" maxlength="30" placeholder="z.B. Lena, MrCoder, GameMaster42 …" oninput="s1update()" style="border-color:rgba(124,58,237,0.5)"/>
<div id="devGreeting" style="margin-top:10px;min-height:28px;font-family:'Fredoka One',cursive;font-size:1.05rem;color:var(--accent);transition:opacity 0.3s;opacity:0"></div>
</div>
<div class="card">
<label class="lbl">🎮 Spielname</label>
<input class="finput" id="s1name" type="text" onfocus="setCodeFocus('name')" maxlength="40" placeholder="z.B. Abenteuer im Dschungel" oninput="s1update()"/>
<div class="char-row" id="s1nc">0 / 40</div>
<div class="suggestions">
<div class="sug" onclick="suggest('Abenteuer im Dschungel')">🌴 Abenteuer im Dschungel</div>
<div class="sug" onclick="suggest('Mission Weltraum')">🚀 Mission Weltraum</div>
<div class="sug" onclick="suggest('Das große Quiz-Turnier')">❓ Das große Quiz-Turnier</div>
<div class="sug" onclick="suggest('Schatz des Drachen')">🐲 Schatz des Drachen</div>
<div class="sug" onclick="suggest('Flucht aus dem Labyrinth')">🌀 Flucht aus dem Labyrinth</div>
</div>
<div class="divider"></div>
<label class="lbl">📝 Beschreibung <span style="color:var(--muted);font-weight:400;font-size:10px">(optional)</span></label>
<textarea class="ftarea" id="s1desc" rows="3" onfocus="setCodeFocus('desc')" maxlength="120" placeholder="Worum geht es? Was ist das Ziel?" oninput="s1update()"></textarea>
<div class="char-row" id="s1dc">0 / 120</div>
</div>
<div id="s1preview" style="display:none">
<div class="preview-card">
<div class="pv-label">👁️ Vorschau</div>
<div class="pv-name" id="s1pvname"></div>
<div class="pv-desc" id="s1pvdesc"></div>
<div id="s1pvdev" style="margin-top:6px;font-size:11px;font-weight:700;color:var(--accent2)"></div>
</div>
</div>
<div class="btn-row">
<div></div>
<button class="btn-next" id="s1next" onclick="goTo(1)" disabled>Weiter <span></span></button>
</div>
</div>
<!-- ════════════ SCREEN 2: GESTALTUNG ════════════ -->
<div class="screen" id="s1">
<div class="sh">
<div class="sh-badge">Schritt 2 von 5</div>
<h1 class="sh-title">Figur & <em>Setting 🎨</em></h1>
<p class="sh-sub">Wähle deine Spielfigur und die Spielwelt.</p>
</div>
<div class="summary-banner" id="sum0">
<div class="sb-title">✅ Schritt 1 abgeschlossen</div>
<div class="sb-chips" id="sum0chips"></div>
</div>
<div class="card">
<div class="card-title">👤 Spielfigur</div>
<p class="card-sub">Das bist du im Spiel!</p>
<div class="sel-grid" id="figGrid"></div>
</div>
<div class="card">
<div class="card-title">🌍 Spielwelt</div>
<p class="card-sub">Wo findet das Abenteuer statt?</p>
<div class="sel-grid" id="bgGrid"></div>
<div id="s2combo" style="display:none">
<div class="combo-preview">
<span class="cp-scene" id="s2scene"></span>
<div class="cp-label" id="s2clabel"></div>
</div>
</div>
</div>
<div class="btn-row">
<button class="btn-back" onclick="goTo(0)">← Zurück</button>
<button class="btn-next" id="s2next" onclick="goTo(2)" disabled>Weiter <span></span></button>
</div>
</div>
<!-- ════════════ SCREEN 3: SPIELFELD ════════════ -->
<div class="screen" id="s2">
<div class="sh">
<div class="sh-badge">Schritt 3 von 5</div>
<h1 class="sh-title">Bau dein <em>Spielfeld 🎲</em></h1>
<p class="sh-sub">Lege Regeln fest und bestücke die Felder mit Mini-Games.</p>
</div>
<div class="summary-banner" id="sum1">
<div class="sb-title">✅ Schritt 2 abgeschlossen</div>
<div class="sb-chips" id="sum1chips"></div>
</div>
<div class="card">
<div class="card-title">⚙️ Spielregeln</div>
<p class="card-sub">Wie soll dein Spiel funktionieren?</p>
<div class="rules-grid">
<div class="rule-block">
<div class="rule-block-title">🎲 Bewegung</div>
<div class="toggle-group">
<div class="toggle-option selected" data-g="movement" data-v="dice" onclick="selRule(this)"><span class="tog-emoji">🎲</span><div><div class="tog-text">Würfeln</div><div class="tog-sub">Zufällig 16 Felder</div></div><div class="tog-check"></div></div>
<div class="toggle-option" data-g="movement" data-v="step" onclick="selRule(this)"><span class="tog-emoji">👣</span><div><div class="tog-text">Ein Feld pro Runde</div><div class="tog-sub">Jedes Feld wird besucht</div></div><div class="tog-check"></div></div>
</div>
</div>
<div class="rule-block">
<div class="rule-block-title">💀 Bei Niederlage</div>
<div class="toggle-group">
<div class="toggle-option selected" data-g="fail" data-v="lives" onclick="selRule(this)"><span class="tog-emoji">❤️</span><div><div class="tog-text">Leben verlieren</div><div class="tog-sub">Bei 0 Leben: Game Over</div></div><div class="tog-check"></div></div>
<div class="toggle-option" data-g="fail" data-v="points" onclick="selRule(this)"><span class="tog-emoji"></span><div><div class="tog-text">Punkte sammeln</div><div class="tog-sub">Kein Verlieren, nur Score</div></div><div class="tog-check"></div></div>
</div>
<div class="sub-opts visible" id="sub_lives">
<div class="sub-opt selected" data-g="lives" data-v="3" onclick="selSub(this)">❤️❤️❤️ 3 Leben</div>
<div class="sub-opt" data-g="lives" data-v="5" onclick="selSub(this)">5 Leben</div>
<div class="sub-opt" data-g="lives" data-v="1" onclick="selSub(this)">☠️ 1 Leben</div>
</div>
<div class="sub-opts" id="sub_points">
<div class="sub-opt selected" data-g="pts" data-v="10" onclick="selSub(this)">+10 Punkte</div>
<div class="sub-opt" data-g="pts" data-v="25" onclick="selSub(this)">+25 Punkte</div>
<div class="sub-opt" data-g="pts" data-v="50" onclick="selSub(this)">+50 Punkte</div>
</div>
</div>
</div>
<div class="divider"></div>
<div class="count-row">
<label>⬛ Anzahl Felder</label>
<div class="count-ctrl">
<button class="cnt-btn" id="cntMinus" onclick="chgCount(-1)"></button>
<div class="cnt-val" id="cntVal">10</div>
<button class="cnt-btn" id="cntPlus" onclick="chgCount(1)">+</button>
<span style="font-size:11px;color:var(--muted)">(620)</span>
</div>
</div>
<div class="sec-label"><span>🕹️ Bausteine</span><div class="story-counter" id="storyCtr">📖 0 / 5</div></div>
<div class="pal-tabs">
<div class="pal-tab active" onclick="palTab('games')">🕹️ Mini-Games</div>
<div class="pal-tab" onclick="palTab('story')">📖 Erzähltexte</div>
</div>
<div class="pal-panel active" id="panGames"></div>
<div class="pal-panel" id="panStory">
<div class="mg-card" id="storyCard" draggable="true" onclick="clickStory()" style="border-color:rgba(6,182,212,0.4)">
<div class="use-count" id="storyUC">0</div>
<div class="mg-emoji">📖</div>
<div class="mg-lbl">Erzähl-Text</div>
<div class="mg-tag story-tag">max.5×</div>
<div style="font-size:10px;color:rgba(6,182,212,0.6);margin-top:2px">Vor/nach Feld</div>
</div>
</div>
<div class="sec-label" style="margin-top:6px">📋 Spielfeld <span style="font-size:10px;font-weight:400;text-transform:none;letter-spacing:0">Klicke auf ein Feld oder ziehe Bausteine hinein</span></div>
<div class="board-builder" id="boardBuilder"></div>
<div class="board-stats" id="boardStats"></div>
</div>
<div class="btn-row">
<button class="btn-back" onclick="goTo(1)">← Zurück</button>
<button class="btn-next" id="s3next" onclick="goTo(3)" disabled>Weiter <span></span></button>
</div>
</div>
<!-- ════════════ SCREEN 4: QUIZ ════════════ -->
<div class="screen" id="s3">
<div class="sh">
<div class="sh-badge">Schritt 4 von 5</div>
<h1 class="sh-title">Deine <em>Quiz-Fragen ❓</em></h1>
<p class="sh-sub">Für jedes Quiz-Feld brauchst du eine Frage mit vier Antworten.</p>
</div>
<div class="summary-banner" id="sum2">
<div class="sb-title">✅ Schritt 3 abgeschlossen</div>
<div class="sb-chips" id="sum2chips"></div>
</div>
<div id="quizArea"></div>
<div class="btn-row">
<button class="btn-back" onclick="goTo(2)">← Zurück</button>
<button class="btn-next" id="s4next" onclick="goTo(4)">Weiter <span></span></button>
</div>
</div>
<!-- ════════════ SCREEN 5: TESTEN ════════════ -->
<div class="screen" id="s4">
<div class="sh">
<div class="sh-badge">Schritt 5 von 5</div>
<h1 class="sh-title">Testen & <em>Feedback 🎮</em></h1>
<p class="sh-sub">Überblick über dein Spiel — dann starten und ausprobieren!</p>
</div>
<div class="summary-banner" id="sum3">
<div class="sb-title">✅ Schritt 4 abgeschlossen</div>
<div class="sb-chips" id="sum3chips"></div>
</div>
<!-- Review filled dynamically -->
<div id="reviewArea"></div>
<!-- Launch card -->
<div class="card" id="launchCard" style="padding:0;overflow:hidden;margin-bottom:18px">
<div class="launch-hero">
<span class="lh-fig" id="lhFig">🎮</span>
<div class="lh-name" id="lhName"></div>
<div class="lh-desc" id="lhDesc"></div>
<div class="lh-pills" id="lhPills"></div>
</div>
<div class="launch-body">
<div class="launch-chk" id="launchChk"></div>
<button class="btn-launch" id="btnLaunch" onclick="doLaunch()">🎮 Spiel starten &amp; testen!</button>
<div class="btn-launch-sub">Öffnet das Spiel in einem neuen Fenster</div>
<div class="played-badge" id="playedBadge">✅ Du hast gespielt! Jetzt bitte Feedback geben ↓</div>
</div>
</div>
<!-- Feedback (hidden until played) -->
<div class="card" id="fbCard" style="display:none">
<div class="card-title">📝 Feedback zu deinem Spiel</div>
<p class="card-sub">Beantworte diese Fragen ehrlich — sie helfen dir, das Spiel zu verbessern!</p>
<div class="fb-prog"><div class="fb-prog-fill" id="fbFill" style="width:0%"></div></div>
<div id="fbArea"></div>
<div class="fb-nav">
<button class="btn-fb-prev" id="fbPrev" onclick="fbBack()" style="display:none">← Zurück</button>
<button class="btn-fb-next" id="fbNext" onclick="fbFwd()" disabled>Weiter →</button>
</div>
</div>
<!-- Summary (hidden until feedback done) -->
<div class="card" id="sumCard" style="display:none;padding:0;overflow:hidden">
<div class="sum-hero">
<span class="sum-icon">🎉</span>
<h2>Test abgeschlossen!</h2>
<p id="sumText"></p>
<div class="sum-scores" id="sumScores"></div>
</div>
<div style="padding:0 22px 6px">
<div class="card-title" style="margin-bottom:9px">📋 Auswertung</div>
<div class="sum-notes" id="sumNotes"></div>
</div>
<div style="padding:14px 22px 26px">
<div class="final-btns">
<button class="btn-revise" onclick="goTo(0)">✏️ Überarbeiten</button>
<button class="btn-publish" onclick="doPublish()">🚀 Spiel veröffentlichen →</button>
</div>
</div>
</div>
<div class="btn-row">
<button class="btn-back" onclick="goTo(3)">← Zurück</button>
<div></div>
</div>
</div>
<!-- ════ SHARE MODAL ════ -->
<div id="shareOverlay" onclick="if(event.target===this)closeShare()" style="
display:none;position:fixed;inset:0;background:rgba(0,0,0,0.8);z-index:6000;
align-items:center;justify-content:center;backdrop-filter:blur(6px);">
<div style="background:#1a1827;border:1.5px solid #2e2b4a;border-radius:20px;
width:min(520px,94vw);max-height:90vh;overflow-y:auto;box-shadow:0 24px 60px rgba(0,0,0,0.7);">
<div style="display:flex;align-items:center;justify-content:space-between;
padding:18px 22px 14px;border-bottom:1px solid #2e2b4a;">
<div style="font-family:'Fredoka One',cursive;font-size:1.3rem;color:#a78bfa">
🎉 Dein Spiel ist fertig!
</div>
<button onclick="closeShare()" style="background:none;border:none;color:#a7a3c2;
font-size:1.3rem;cursor:pointer;padding:4px 8px;border-radius:6px"></button>
</div>
<div style="padding:22px">
<div id="shareGameInfo" style="background:rgba(124,58,237,0.1);border:1px solid rgba(124,58,237,0.3);
border-radius:12px;padding:14px;margin-bottom:18px;font-family:'Nunito',sans-serif;"></div>
<div style="margin-bottom:18px">
<div style="font-family:'Fredoka One',cursive;color:#a78bfa;font-size:0.95rem;margin-bottom:8px">
🔗 Dein Spiel-Link
</div>
<div style="display:flex;gap:8px;align-items:center">
<input id="shareLinkInput" readonly style="
flex:1;background:#0f0e17;border:1.5px solid #2e2b4a;border-radius:10px;
color:#e2e0f0;font-family:'Nunito',sans-serif;font-size:11px;
padding:10px 12px;outline:none;" />
<button onclick="copyShareLink()" id="shareCopyBtn" style="
background:linear-gradient(135deg,#7c3aed,#5b21b6);color:#fff;
font-family:'Fredoka One',cursive;font-size:0.9rem;border:none;
border-radius:10px;padding:10px 16px;cursor:pointer;white-space:nowrap">
📋 Kopieren
</button>
</div>
<div id="shareLinkLen" style="font-size:11px;color:#64748b;margin-top:4px;font-family:'Nunito',sans-serif;"></div>
</div>
<div style="margin-bottom:18px;text-align:center">
<div style="font-family:'Fredoka One',cursive;color:#a78bfa;font-size:0.95rem;margin-bottom:10px">
📱 QR-Code zum Scannen
</div>
<div id="shareQR" style="display:inline-block;background:#fff;padding:12px;border-radius:12px;min-width:160px;min-height:160px;"></div>
<div style="font-size:11px;color:#64748b;margin-top:6px;font-family:'Nunito',sans-serif">
Handy-Kamera auf den QR-Code richten
</div>
</div>
<div style="font-family:'Fredoka One',cursive;color:#a78bfa;font-size:0.95rem;margin-bottom:10px">
📤 Direkt teilen
</div>
<div style="display:flex;gap:10px;flex-wrap:wrap;margin-bottom:16px">
<button onclick="shareViaEmail()" style="flex:1;min-width:100px;background:rgba(59,130,246,0.15);
border:1.5px solid rgba(59,130,246,0.4);color:#93c5fd;font-family:'Fredoka One',cursive;
font-size:0.85rem;border-radius:10px;padding:10px 14px;cursor:pointer">
📧 E-Mail
</button>
<button onclick="shareViaWhatsApp()" style="flex:1;min-width:100px;background:rgba(34,197,94,0.15);
border:1.5px solid rgba(34,197,94,0.4);color:#86efac;font-family:'Fredoka One',cursive;
font-size:0.85rem;border-radius:10px;padding:10px 14px;cursor:pointer">
💬 WhatsApp
</button>
<button onclick="shareNative()" style="flex:1;min-width:100px;background:rgba(245,158,11,0.15);
border:1.5px solid rgba(245,158,11,0.4);color:#fcd34d;font-family:'Fredoka One',cursive;
font-size:0.85rem;border-radius:10px;padding:10px 14px;cursor:pointer">
📲 Teilen...
</button>
</div>
<div style="background:rgba(16,185,129,0.1);border:1px solid rgba(16,185,129,0.3);
border-radius:10px;padding:12px;font-family:'Nunito',sans-serif;font-size:12px;color:#6ee7b7;">
Der Link enthält dein komplettes Spiel. Jeder mit dem Link kann es direkt spielen keine Anmeldung nötig!
</div>
</div>
</div>
</div>
<script>
/* ══════════════════════════════════════════════
DATA
══════════════════════════════════════════════ */
const FIGURES=[
{id:'robot',e:'🤖',n:'Roboter'},{id:'ninja',e:'🥷',n:'Ninja'},{id:'knight',e:'🧙‍♂️',n:'Zauberer'},
{id:'cat',e:'🐱',n:'Katze'},{id:'rocket',e:'🚀',n:'Rakete'},{id:'dino',e:'🦖',n:'Dino'},
{id:'alien',e:'👾',n:'Alien'},{id:'superhero',e:'🦸',n:'Superheld'},{id:'pirate',e:'🏴‍☠️',n:'Pirat'},
{id:'fox',e:'🦊',n:'Fuchs'},{id:'dragon',e:'🐲',n:'Drache'},{id:'astronaut',e:'👨‍🚀',n:'Astronaut'},
];
const BACKGROUNDS=[
{id:'jungle', e:'🌴',scene:'🌴🦜🌿',n:'Dschungel', color:'#22c55e',glow:'rgba(34,197,94,0.4)'},
{id:'space', e:'🌌',scene:'🌌🪐⭐', n:'Weltraum', color:'#818cf8',glow:'rgba(129,140,248,0.4)'},
{id:'ocean', e:'🌊',scene:'🌊🐠🐙',n:'Unterwasser', color:'#06b6d4',glow:'rgba(6,182,212,0.4)'},
{id:'fantasy',e:'🏰',scene:'🏰🐉✨', n:'Fantasy', color:'#c084fc',glow:'rgba(192,132,252,0.4)'},
{id:'school', e:'🏫',scene:'🏫📚✏️',n:'Schule', color:'#fbbf24',glow:'rgba(251,191,36,0.4)'},
{id:'volcano',e:'🌋',scene:'🌋🏝️🔥',n:'Vulkaninsel', color:'#f97316',glow:'rgba(249,115,22,0.4)'},
{id:'snow', e:'❄️',scene:'❄️🏔️⛄', n:'Schneereich', color:'#bae6fd',glow:'rgba(186,230,253,0.4)'},
{id:'city', e:'🌆',scene:'🌆🚗🏙️',n:'Großstadt', color:'#94a3b8',glow:'rgba(148,163,184,0.4)'},
{id:'candy', e:'🍭',scene:'🍭🍬🎂', n:'Süßigkeitenland',color:'#f472b6',glow:'rgba(244,114,182,0.4)'},
{id:'desert', e:'🏜️',scene:'🏜️🌵🐪',n:'Wüste', color:'#fcd34d',glow:'rgba(252,211,77,0.4)'},
{id:'haunted',e:'👻',scene:'👻🏚️🕸️',n:'Geisterhaus', color:'#818cf8',glow:'rgba(129,140,248,0.4)'},
{id:'future', e:'🤖',scene:'🤖🏙️💡',n:'Zukunft', color:'#34d399',glow:'rgba(52,211,153,0.4)'},
];
const MINIGAMES=[
{id:'quiz',e:'❓',n:'Quiz',multi:'∞'},{id:'reaction',e:'⚡',n:'Reaktion',multi:3},
{id:'puzzle',e:'🧩',n:'Rätsel',multi:3},{id:'spotdiff',e:'🔍',n:'Fehler finden',multi:3},
{id:'typing',e:'⌨️',n:'Tipp-Rennen',multi:3},{id:'snake',e:'🐍',n:'Snake',multi:1},
{id:'flappy',e:'🐦',n:'Flappy Bird',multi:1},{id:'catch',e:'🍎',n:'Äpfel fangen',multi:1},
{id:'basketball',e:'🏀',n:'Basketball',multi:1},{id:'memory',e:'🃏',n:'Memory',multi:1},
{id:'maze',e:'🌀',n:'Labyrinth',multi:1},{id:'simon',e:'🔴',n:'Simon Says',multi:1},
];
const STORY_EMOJIS=['📖','🗺️','⚔️','🧭','💬','🌟','🔥','💡','🎭','🏴‍☠️','🌈','🐉','👁️','🎶','🌙','⚡','🗝️','🌊','🏔️','🎪','🦋','🌺','💎','🎯'];
const LETTERS=['A','B','C','D'];
const QUIZ_EX=[
{q:'Was ist die Hauptstadt von Deutschland?',a:['Paris','London','Berlin','Madrid'],c:2},
{q:'Wie viele Seiten hat ein Hexagon?',a:['5','6','7','8'],c:1},
{q:'Wer schrieb "Romeo und Julia"?',a:['Goethe','Schiller','Shakespeare','Kafka'],c:2},
{q:'Was ist das größte Tier der Welt?',a:['Elefant','Blauwal','Hai','Giraffe'],c:1},
{q:'Wie viele Minuten hat eine Stunde?',a:['50','70','100','60'],c:3},
{q:'Chemische Formel für Wasser?',a:['CO2','H2O','O2','NaCl'],c:1},
{q:'In welchem Kontinent liegt Ägypten?',a:['Asien','Europa','Amerika','Afrika'],c:3},
{q:'Was ist 12 × 12?',a:['132','144','124','148'],c:1},
{q:'Blau + Gelb = ?',a:['Rot','Orange','Grün','Lila'],c:2},
{q:'Höchster Berg der Welt?',a:['K2','Mont Blanc','Everest','Kilimandscharo'],c:2},
];
const FB_QS=[
{id:'fun',t:'scale',q:'Wie viel Spaß hat dein Spiel gemacht?',sub:'1 = gar kein Spaß · 5 = mega viel Spaß',min:'😴 Langweilig',max:'🔥 Super Spaß'},
{id:'difficulty',t:'mc',q:'Wie schwierig war dein Spiel?',opts:['😴 Viel zu einfach','👍 Genau richtig','😅 Etwas zu schwer','💀 Viel zu schwer']},
{id:'flow',t:'mc',q:'Wie gut passt das Spiel zusammen?',sub:'„Flow" — fühlt sich alles stimmig und flüssig an?',opts:['🔀 Wirkt zusammengewürfelt','🤔 Einigermaßen','👌 Passt gut','✨ Perfekt stimmig']},
{id:'clarity',t:'mc',q:'Waren Regeln und Aufgaben klar?',opts:['❓ Oft unklar','🤔 Manchmal unklar','👍 Meistens klar','✅ Immer sofort klar']},
{id:'minigames',t:'scale',q:'Wie gut passen die Mini-Games zum Thema?',sub:'Passen sie zur Geschichte und zum Setting?',min:'🚫 Passen nicht',max:'✨ Passen perfekt'},
{id:'problems',t:'text',q:'Was hat noch nicht so gut funktioniert?',ph:'z.B. "Das Quiz war zu einfach" oder "zu viele leere Felder"...'},
{id:'highlight',t:'text',q:'Was war der beste Teil deines Spiels?',ph:'z.B. "Die Geschichte war spannend" oder "Snake hat Spaß gemacht"...'},
{id:'replay',t:'mc',q:'Würdest du das Spiel nochmal spielen?',opts:['❌ Eher nicht','🤷 Vielleicht','😊 Ja','🚀 Auf jeden Fall!']},
];
/* ══════════════════════════════════════════════
STATE
══════════════════════════════════════════════ */
const ST={
devName:'',name:'',desc:'',figure:'',background:'',
fieldCount:10,fields:Array(10).fill(null),
storyItems:[],quizData:[],
rules:{movement:'dice',fail:'lives',lives:'3',pts:'10'},
highestStep:0,
};
try{
const sv=JSON.parse(localStorage.getItem('gameConfig')||'{}');
if(sv.devName)ST.devName=sv.devName;
if(sv.name)ST.name=sv.name;if(sv.desc)ST.desc=sv.desc;
if(sv.figure)ST.figure=sv.figure;if(sv.background)ST.background=sv.background;
if(sv.fieldCount)ST.fieldCount=sv.fieldCount;
if(sv.fields){ST.fields=sv.fields;while(ST.fields.length<ST.fieldCount)ST.fields.push(null);ST.fields=ST.fields.slice(0,ST.fieldCount);}
if(sv.storyItems)ST.storyItems=sv.storyItems;
if(sv.quizData)ST.quizData=sv.quizData;
if(sv.rules)Object.assign(ST.rules,sv.rules);
if(sv.highestStep)ST.highestStep=sv.highestStep;
}catch(e){}
let cur=0;
function save(){
localStorage.setItem('gameConfig',JSON.stringify({
devName:ST.devName,name:ST.name,desc:ST.desc,figure:ST.figure,background:ST.background,
fieldCount:ST.fieldCount,fields:ST.fields,storyItems:ST.storyItems,
quizData:ST.quizData,rules:ST.rules,highestStep:ST.highestStep,
}));
// Note: code update is triggered by input/change listeners, not here
}
function resetAll(){
if(!confirm('Wirklich alles zurücksetzen?\nAlle Eingaben gehen verloren!')) return;
localStorage.removeItem('gameConfig');
localStorage.removeItem('testFeedback');
location.reload();
}
/* ══════════════════════════════════════════════
NAVIGATION
══════════════════════════════════════════════ */
function goTo(step){
if(step>cur&&!canLeave(cur))return;
save();
const from=document.getElementById('s'+cur);
from.classList.remove('active');
from.style.display='none';
setTimeout(()=>{from.style.display='';},50);
if(step>cur)ST.highestStep=Math.max(ST.highestStep,step);
cur=step;
const to=document.getElementById('s'+cur);
to.classList.add('active','slide-in');
to.addEventListener('animationend',()=>to.classList.remove('slide-in'),{once:true});
const ep=document.getElementById('editorPane');if(ep)ep.scrollTo({top:0,behavior:'smooth'});else window.scrollTo({top:0,behavior:'smooth'});
updatePB();
showSummary(step);
if(step===1)s2init();
if(step===2)s3init();
if(step===3)buildQuiz();
if(step===4)buildReview();
showToast('✅ Schritt '+(step+1)+' geöffnet!');
}
function pbClick(step){if(step<cur&&step<=ST.highestStep){goTo(step);}}
function canLeave(step){
if(step===0)return ST.name.trim().length>0;
if(step===1)return !!(ST.figure&&ST.background);
if(step===2)return ST.fields.slice(1,ST.fieldCount-1).filter(Boolean).length>0;
return true;
}
function updatePB(){
for(let i=0;i<5;i++){
const d=document.getElementById('pb'+i);
d.className='pb-step'+(i===cur?' active':i<cur?' done':'');
const c=document.getElementById('pbc'+i);
if(c)c.className='pb-connector'+(i<cur?' done':'');
}
document.getElementById('pbFill').style.width=((cur+1)/5*100)+'%';
}
function showSummary(step){
const idx=step-1;
if(idx<0)return;
const banner=document.getElementById('sum'+idx);
if(!banner)return;
banner.classList.add('visible');
const chips=document.getElementById('sum'+idx+'chips');
if(!chips)return;
let html='';
if(idx===0){if(ST.devName)html+=`<div class="sb-chip">👋 ${ST.devName}</div>`;html+=`<div class="sb-chip">🎮 ${ST.name}</div>`;if(ST.desc)html+=`<div class="sb-chip">"${ST.desc.slice(0,40)}${ST.desc.length>40?'…':''}"</div>`;}
if(idx===1){const f=FIGURES.find(x=>x.id===ST.figure);const b=BACKGROUNDS.find(x=>x.id===ST.background);if(f)html+=`<div class="sb-chip">${f.e} ${f.n}</div>`;if(b)html+=`<div class="sb-chip">🌍 ${b.n}</div>`;}
if(idx===2){const filled=ST.fields.slice(1,ST.fieldCount-1).filter(Boolean).length;html+=`<div class="sb-chip">⬛ ${ST.fieldCount} Felder</div><div class="sb-chip">🕹️ ${filled} Mini-Games</div><div class="sb-chip">📖 ${ST.storyItems.length} Erzähltexte</div>`;}
if(idx===3){const done=ST.quizData.filter(isQComplete).length;html+=`<div class="sb-chip">❓ ${done}/${ST.quizData.length||0} Quiz-Fragen</div>`;}
chips.innerHTML=html;
}
function showToast(msg){
const t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');
setTimeout(()=>t.classList.remove('show'),2000);
}
/* ══════════════════════════════════════════════
STEP 1 — GRUNDINFOS
══════════════════════════════════════════════ */
function s1init(){
document.getElementById('s1devname').value=ST.devName;
document.getElementById('s1name').value=ST.name;
document.getElementById('s1desc').value=ST.desc;
s1update();
}
function s1update(){
ST.devName=document.getElementById('s1devname').value.trim();
ST.name=document.getElementById('s1name').value.trim();
ST.desc=document.getElementById('s1desc').value;
const nl=document.getElementById('s1name').value.length;
const dl=ST.desc.length;
document.getElementById('s1nc').textContent=nl+' / 40';
document.getElementById('s1dc').textContent=dl+' / 120';
document.getElementById('s1dc').className='char-row'+(dl>100?' warn':'');
document.getElementById('s1next').disabled=!ST.name||!ST.devName;
// Persönliche Begrüßung
const grEl=document.getElementById('devGreeting');
if(ST.devName){
const greetings=[
'Hey '+ST.devName+' 👋 Schön, dass du dabei bist!',
'Los geht\'s, '+ST.devName+'! Dein Spiel wartet 🎮',
'Hi '+ST.devName+'! Du wirst ein tolles Spiel bauen ✨',
'Willkommen, '+ST.devName+'! Game on! 🚀',
];
grEl.textContent=greetings[ST.devName.length%greetings.length];
grEl.style.opacity='1';
} else {grEl.style.opacity='0';}
// Vorschau
const show=ST.name.length>0&&ST.devName.length>0;
document.getElementById('s1preview').style.display=show?'':'none';
if(show){
document.getElementById('s1pvname').textContent=ST.name;
document.getElementById('s1pvdesc').textContent=ST.desc||'Keine Beschreibung.';
document.getElementById('s1pvdev').textContent='👨‍💻 Entwickelt von '+ST.devName;
}
}
function suggest(txt){document.getElementById('s1name').value=txt;s1update();}
/* ══════════════════════════════════════════════
STEP 2 — GESTALTUNG
══════════════════════════════════════════════ */
function s2init(){
const fg=document.getElementById('figGrid');
fg.innerHTML='';
FIGURES.forEach(f=>{
const c=document.createElement('div');c.className='sel-card'+(ST.figure===f.id?' selected':'');
c.innerHTML=`<span class="se">${f.e}</span><div class="sl">${f.n}</div>`;
c.onclick=()=>{ST.figure=f.id;setCodeFocus('figure');s2update();fg.querySelectorAll('.sel-card').forEach(x=>x.classList.remove('selected'));c.classList.add('selected');};
fg.appendChild(c);
});
const bg=document.getElementById('bgGrid');
bg.innerHTML='';
BACKGROUNDS.forEach(b=>{
const c=document.createElement('div');c.className='sel-card'+(ST.background===b.id?' selected':'');
c.innerHTML=`<span class="se">${b.e}</span><div class="sl">${b.n}</div>`;
c.onclick=()=>{ST.background=b.id;setCodeFocus('bg');s2update();bg.querySelectorAll('.sel-card').forEach(x=>x.classList.remove('selected'));c.classList.add('selected');};
bg.appendChild(c);
});
s2update();
}
function s2update(){
const ok=!!(ST.figure&&ST.background);
document.getElementById('s2next').disabled=!ok;
const combo=document.getElementById('s2combo');
if(ok){
const f=FIGURES.find(x=>x.id===ST.figure);const b=BACKGROUNDS.find(x=>x.id===ST.background);
combo.style.display='';
document.getElementById('s2scene').textContent=b.scene+' '+f.e;
document.getElementById('s2clabel').textContent=f.n+' im '+b.n;
}else combo.style.display='none';
}
/* ══════════════════════════════════════════════
STEP 3 — SPIELFELD
══════════════════════════════════════════════ */
let selGame=null,dragging=null,epFor=null;
const STORY_MAX=5,MULTI_MAX=3;
// unlockSection: Markiert eine Sektion als "gesehen" für den Live-Code-Preview
function unlockSection(key){
if(typeof unlocked !== 'undefined') unlocked.add(key);
if(typeof setCodeFocus === 'function') setCodeFocus(key);
}
function s3init(){
unlockSection('movement'); unlockSection('failmode'); unlockSection('fieldcount'); unlockSection('fields');
document.getElementById('cntVal').textContent=ST.fieldCount;
document.getElementById('cntMinus').disabled=ST.fieldCount<=6;
document.getElementById('cntPlus').disabled=ST.fieldCount>=20;
applyRuleUI();
buildPalette();
buildBoard();
}
function selRule(el){
const g=el.dataset.g;
document.querySelectorAll(`[data-g="${g}"]`).forEach(x=>x.classList.remove('selected'));
el.classList.add('selected');ST.rules[g]=el.dataset.v;
// Map data-g to focus keys
const fkMap={'movement':'movement','fail':'failmode'};
setCodeFocus(fkMap[g]||g);
if(g==='fail'){
document.getElementById('sub_lives').classList.toggle('visible',ST.rules.fail==='lives');
document.getElementById('sub_points').classList.toggle('visible',ST.rules.fail==='points');
}
}
function selSub(el){
const g=el.dataset.g;
document.querySelectorAll(`[data-g="${g}"]`).forEach(x=>x.classList.remove('selected'));
el.classList.add('selected');ST.rules[g]=el.dataset.v;
// lives/pts sub-options
setCodeFocus(g==='lives'?'lives':g==='pts'?'pts':'failmode');
}
function applyRuleUI(){
['movement','fail'].forEach(g=>document.querySelectorAll(`[data-g="${g}"]`).forEach(x=>x.classList.toggle('selected',x.dataset.v===ST.rules[g])));
document.getElementById('sub_lives').classList.toggle('visible',ST.rules.fail==='lives');
document.getElementById('sub_points').classList.toggle('visible',ST.rules.fail==='points');
['lives','pts'].forEach(g=>document.querySelectorAll(`[data-g="${g}"]`).forEach(x=>x.classList.toggle('selected',x.dataset.v===ST.rules[g])));
}
function chgCount(d){
const n=ST.fieldCount+d;if(n<6||n>20)return;
ST.fieldCount=n;setCodeFocus('fieldcount');document.getElementById('cntVal').textContent=n;
document.getElementById('cntMinus').disabled=n<=6;document.getElementById('cntPlus').disabled=n>=20;
while(ST.fields.length<n)ST.fields.push(null);
ST.fields=ST.fields.slice(0,n);
ST.storyItems=ST.storyItems.filter(s=>s.fieldIndex<n);
buildBoard();
}
function palTab(t){
document.querySelectorAll('.pal-tab').forEach((x,i)=>x.classList.toggle('active',(i===0&&t==='games')||(i===1&&t==='story')));
document.getElementById('panGames').classList.toggle('active',t==='games');
document.getElementById('panStory').classList.toggle('active',t==='story');
}
function getUC(id){return ST.fields.filter(f=>f===id).length;}
function mgDis(mg){const c=getUC(mg.id);return mg.multi===1?c>=1:mg.multi===3?c>=MULTI_MAX:false;}
function sCnt(){return ST.storyItems.length;}
function sMaxed(){return ST.storyItems.length>=STORY_MAX;}
function buildPalette(){
const pan=document.getElementById('panGames');pan.innerHTML='';
MINIGAMES.forEach(mg=>{
const tagCls=mg.multi==='∞'?'unlim':mg.multi===3?'multi':'once';
const tagTxt=mg.multi==='∞'?'∞':mg.multi===3?'max.3×':'1×';
const c=document.createElement('div');c.className='mg-card';c.id='mgc_'+mg.id;c.draggable=true;
c.innerHTML=`<div class="use-count" id="uc_${mg.id}">0</div><div class="mg-emoji">${mg.e}</div><div class="mg-lbl">${mg.n}</div><div class="mg-tag ${tagCls}">${tagTxt}</div><button class="mg-test-btn" onclick="openMGTest('${mg.id}',event)">▶ Test</button>`;
c.addEventListener('click',()=>{if(c.classList.contains('disabled'))return;if(selGame===mg.id){selGame=null;c.classList.remove('click-sel');}else{clearSel();selGame=mg.id;c.classList.add('click-sel');}});
c.addEventListener('dragstart',e=>{
if(c.classList.contains('disabled')){e.preventDefault();return;}
dragging='game'; dragId=mg.id; clearSel();
e.dataTransfer.effectAllowed='copy';
e.dataTransfer.setData('text/plain','game:'+mg.id);
// Use the card itself as drag image — offset so cursor is in center
e.dataTransfer.setDragImage(c, c.offsetWidth/2, c.offsetHeight/2);
ghost(mg.e+' '+mg.n);
});
c.addEventListener('dragend',()=>{dragging=null;dragId=null;unghost();cleanDropTargets();});
pan.appendChild(c);
});
const sc=document.getElementById('storyCard');
sc.ondragstart=e=>{
if(sMaxed()){e.preventDefault();return;}
dragging='story'; dragId='story'; clearSel(); selGame='story';
e.dataTransfer.effectAllowed='copy';
e.dataTransfer.setData('text/plain','story');
e.dataTransfer.setDragImage(sc, sc.offsetWidth/2, sc.offsetHeight/2);
ghost('📖 Erzähl-Text');
};
sc.ondragend=()=>{dragging=null;dragId=null;unghost();cleanDropTargets();};
updPal();
}
function clearSel(){selGame=null;document.querySelectorAll('.mg-card').forEach(c=>c.classList.remove('click-sel'));}
function cleanDropTargets(){
document.querySelectorAll('.drop-zone').forEach(z=>{z.classList.remove('story-hoverable','drag-over');});
document.querySelectorAll('.field-row').forEach(r=>r.classList.remove('drag-target'));
}
function updPal(){
MINIGAMES.forEach(mg=>{
const c=document.getElementById('mgc_'+mg.id);const uc=document.getElementById('uc_'+mg.id);if(!c)return;
const cnt=getUC(mg.id);uc.textContent=cnt;
c.classList.toggle('used',cnt>0);c.classList.toggle('disabled',mgDis(mg));
if(mgDis(mg)&&selGame===mg.id)clearSel();
});
const sc=document.getElementById('storyCard');if(sc){sc.classList.toggle('disabled',sMaxed());const suc=document.getElementById('storyUC');if(suc)suc.textContent=sCnt();sc.classList.toggle('used',sCnt()>0);}
const badge=document.getElementById('storyCtr');badge.textContent='📖 '+sCnt()+' / '+STORY_MAX;badge.classList.toggle('maxed',sMaxed());
const filled=ST.fields.slice(1,ST.fieldCount-1).filter(Boolean).length;
document.getElementById('s3next').disabled=filled===0;
}
let dragId=null;
function ghost(txt){const g=document.getElementById('dragGhost');g.textContent=txt;g.style.opacity='1';}
function unghost(){document.getElementById('dragGhost').style.opacity='0';}
// Track mouse position for ghost element
document.addEventListener('dragover',e=>{
e.preventDefault();
const g=document.getElementById('dragGhost');
if(dragging){g.style.left=e.clientX+'px';g.style.top=e.clientY+'px';}
if(dragging==='story'){
document.querySelectorAll('.drop-zone').forEach(z=>z.classList.add('story-hoverable'));
}
});
document.addEventListener('dragend',()=>cleanDropTargets());
function buildBoard(){
const bb=document.getElementById('boardBuilder');bb.innerHTML='';
for(let i=0;i<ST.fieldCount;i++){
if(i>0)bb.appendChild(mkDrop('before',i));
ST.storyItems.filter(s=>s.position==='before'&&s.fieldIndex===i).forEach(s=>bb.appendChild(mkStory(s)));
const g=ST.fields[i];const mg=g?MINIGAMES.find(m=>m.id===g):null;
const isSt=i===0,isEn=i===ST.fieldCount-1;
const row=document.createElement('div');
row.className='field-row'+(mg?' filled':'')+(isSt?' start-f':'')+(isEn?' end-f':'');
const numLbl=isSt?'🟢 Start':isEn?'🏁 Ziel':`Feld ${i}`;
const icon=mg?mg.e:isSt?'🟢':isEn?'🏁':'⬜';
const name=mg?mg.n:isSt?'Startfeld':isEn?'Zielfeld':'Leer — klicken oder hineinziehen';
row.innerHTML=`<div class="f-num">${numLbl}</div><div class="f-icon">${icon}</div><div class="f-name ${mg||isSt||isEn?'':'f-empty'}">${name}</div><button class="f-clear" onclick="clearF(${i},event)">✕</button>`;
if(!isSt&&!isEn){
row.addEventListener('click',()=>handleFClick(i));
row.addEventListener('dragenter',e=>{if(dragging==='game'){e.preventDefault();row.classList.add('drag-target');}});
row.addEventListener('dragover',e=>{if(dragging==='game'){e.preventDefault();e.dataTransfer.dropEffect='copy';row.classList.add('drag-target');}});
row.addEventListener('dragleave',e=>{if(!row.contains(e.relatedTarget))row.classList.remove('drag-target');});
row.addEventListener('drop',e=>{
e.preventDefault();row.classList.remove('drag-target');
const d=e.dataTransfer.getData('text/plain');
if(d.startsWith('game:'))dropGame(i,d.replace('game:',''));
});
}
bb.appendChild(row);
ST.storyItems.filter(s=>s.position==='after'&&s.fieldIndex===i).forEach(s=>bb.appendChild(mkStory(s)));
if(i<ST.fieldCount-1)bb.appendChild(mkDrop('after',i));
}
updPal();
const filled=ST.fields.slice(1,ST.fieldCount-1).filter(Boolean).length;
document.getElementById('boardStats').innerHTML=`<div class="stat-pill">🎯 Belegt: <span>${filled}/${ST.fieldCount-2}</span></div><div class="stat-pill">🕹️ Games: <span>${new Set(ST.fields.filter(Boolean)).size}</span></div><div class="stat-pill">📖 Texte: <span>${sCnt()}</span></div>`;
}
function mkDrop(pos,fi){
const z=document.createElement('div');z.className='drop-zone';
z.textContent='+ Erzähl-Text hier ablegen';
z.addEventListener('dragenter',e=>{if(dragging==='story'){e.preventDefault();z.classList.add('drag-over');}});
z.addEventListener('dragover',e=>{if(dragging==='story'){e.preventDefault();e.dataTransfer.dropEffect='copy';z.classList.add('drag-over');}});
z.addEventListener('dragleave',e=>{if(!z.contains(e.relatedTarget))z.classList.remove('drag-over');});
z.addEventListener('drop',e=>{
e.preventDefault();z.classList.remove('drag-over');
if(e.dataTransfer.getData('text/plain')==='story')dropStory(pos,fi);
});
z.addEventListener('click',()=>{if(selGame==='story')dropStory(pos,fi);});
return z;
}
function mkStory(s){
const row=document.createElement('div');row.className='story-row';row.dataset.sid=s.id;
const posLbl=s.position==='before'?`Vor Feld ${s.fieldIndex}`:`Nach Feld ${s.fieldIndex}`;
row.innerHTML=`<div class="story-icon" onclick="openEP('${s.id}',this)">${s.emoji||'📖'}</div><div class="story-content"><div class="story-lbl">📖 Erzähl-Text</div><textarea class="story-ta" rows="2" maxlength="300" placeholder="Schreib deine Geschichte..." oninput="updStory('${s.id}',this.value)">${s.text||''}</textarea><div class="story-meta"><div class="story-pos-lbl">${posLbl}</div><div class="story-chars">${(s.text||'').length}/300</div></div></div><button class="story-clear" onclick="rmStory('${s.id}')">✕</button>`;
return row;
}
function clickStory(){if(sMaxed())return;if(selGame==='story'){selGame=null;document.getElementById('storyCard').classList.remove('click-sel');}else{clearSel();selGame='story';document.getElementById('storyCard').classList.add('click-sel');}}
function dropStory(pos,fi){
if(sMaxed()){showToast('⚠️ Maximal 5 Erzähltexte!');return;}
const id='st_'+Date.now();
ST.storyItems.push({id,emoji:'📖',text:'',position:pos,fieldIndex:fi});
clearSel();buildBoard();
setTimeout(()=>{const r=document.querySelector(`[data-sid="${id}"] textarea`);if(r)r.focus();},80);
}
function updStory(id,val){const s=ST.storyItems.find(x=>x.id===id);if(!s)return;s.text=val;const row=document.querySelector(`[data-sid="${id}"]`);if(row){const cc=row.querySelector('.story-chars');if(cc)cc.textContent=val.length+'/300';}}
function rmStory(id){ST.storyItems=ST.storyItems.filter(x=>x.id!==id);buildBoard();}
function openEP(sid,iconEl){
const picker=document.getElementById('emojiPicker');
if(epFor===sid){picker.classList.remove('open');epFor=null;return;}
epFor=sid;picker.innerHTML='';
STORY_EMOJIS.forEach(em=>{const btn=document.createElement('div');btn.className='ep-it';btn.textContent=em;btn.addEventListener('click',()=>{const s=ST.storyItems.find(x=>x.id===sid);if(s){s.emoji=em;buildBoard();}picker.classList.remove('open');epFor=null;});picker.appendChild(btn);});
const r=iconEl.getBoundingClientRect();
picker.style.left=Math.min(r.left,window.innerWidth-220)+'px';
picker.style.top=(r.bottom+6)+'px';
picker.classList.add('open');
}
document.addEventListener('click',e=>{if(epFor&&!e.target.classList.contains('story-icon')&&!document.getElementById('emojiPicker').contains(e.target)){document.getElementById('emojiPicker').classList.remove('open');epFor=null;}});
function handleFClick(idx){if(!selGame||selGame==='story')return;const mg=MINIGAMES.find(m=>m.id===selGame);if(!mg||mgDis(mg))return;ST.fields[idx]=selGame;setCodeFocus('fields');buildBoard();}
function dropGame(idx,id){
const mg=MINIGAMES.find(m=>m.id===id);if(!mg)return;
const tmp=[...ST.fields];tmp[idx]=null;
const cnt=tmp.filter(f=>f===id).length;
if((mg.multi===1&&cnt>=1)||(mg.multi===3&&cnt>=MULTI_MAX)){showToast('⚠️ Limit erreicht für '+mg.n+'!');return;}
ST.fields[idx]=id;
setCodeFocus('fields');
buildBoard();
}
function clearF(idx,e){e&&e.stopPropagation();ST.fields[idx]=null;buildBoard();}
/* ══════════════════════════════════════════════
STEP 4 — QUIZ
══════════════════════════════════════════════ */
function isQComplete(q){return q.question.trim()&&q.answers.every(a=>a.trim())&&q.correct!==null;}
function getQ(fi){return ST.quizData.find(q=>q.fieldIndex===fi);}
function buildQuiz(){
const qidx=ST.fields.map((f,i)=>f==='quiz'?i:-1).filter(i=>i>=0);
qidx.forEach(fi=>{if(!ST.quizData.find(q=>q.fieldIndex===fi))ST.quizData.push({fieldIndex:fi,question:'',answers:['','','',''],correct:null});});
ST.quizData=ST.quizData.filter(q=>qidx.includes(q.fieldIndex));
const area=document.getElementById('quizArea');area.innerHTML='';
if(qidx.length===0){
area.innerHTML=`<div class="card"><div class="no-quiz"><div class="nq-icon">❓</div><h3>Keine Quiz-Felder platziert</h3><p style="color:var(--muted);font-size:13px">In Schritt 3 hast du keine Quiz-Felder hinzugefügt.<br>Du kannst trotzdem weitermachen!</p></div></div>`;
document.getElementById('s4next').disabled=false;return;
}
const done=ST.quizData.filter(isQComplete).length;
const ov=document.createElement('div');ov.className='ov-bar';
ov.innerHTML=`<div class="ov-pill ${done===qidx.length?'good':'warn'}">✅ Fertig: <span>${done}/${qidx.length}</span></div><div class="ov-pill">❓ Quiz-Felder: <span>${qidx.length}</span></div>`;
area.appendChild(ov);
const af=document.createElement('div');af.className='af-bar';
af.innerHTML=`<div class="af-icon">✨</div><div class="af-text"><div class="af-title">Beispielfragen</div><div class="af-sub">Alle leeren Felder automatisch ausfüllen</div></div><button class="btn-sm" onclick="autoFill()">Ausfüllen</button>`;
area.appendChild(af);
ST.quizData.forEach((q,i)=>area.appendChild(mkQCard(q,i)));
updQNext();
}
function updQNext(){
const qidx=ST.fields.map((f,i)=>f==='quiz'?i:-1).filter(i=>i>=0);
document.getElementById('s4next').disabled=qidx.length>0&&ST.quizData.filter(isQComplete).length<qidx.length;
const done=ST.quizData.filter(isQComplete).length;
const p=document.querySelector('.ov-pill');if(p){p.className='ov-pill '+(done===qidx.length?'good':'warn');p.innerHTML=`✅ Fertig: <span>${done}/${qidx.length}</span>`;}
}
function mkQCard(q,idx){
const comp=isQComplete(q);
const c=document.createElement('div');c.className='card quiz-card'+(comp?' complete':'');c.id='qc_'+q.fieldIndex;
const fl=q.fieldIndex===0?'Start':q.fieldIndex===ST.fieldCount-1?'Ziel':'Feld '+q.fieldIndex;
c.innerHTML=`
<div class="qc-head">
<div class="qc-num" id="qnum_${q.fieldIndex}">${idx+1}</div>
<div class="qc-title">Quiz-Frage ${idx+1}</div>
<div class="qc-status ${comp?'done':'todo'}" id="qst_${q.fieldIndex}">${comp?'✓ Fertig':'⏳ Ausfüllen'}</div>
</div>
<label class="lbl">Frage (📍 ${fl})</label>
<textarea class="q-input" rows="2" maxlength="200" placeholder="Schreib deine Frage hier..." oninput="updQ(${q.fieldIndex},'q',this.value)">${q.question}</textarea>
<label class="lbl">Die vier Antworten</label>
<div class="ans-grid" id="ag_${q.fieldIndex}">
${LETTERS.map((L,i)=>`<div class="ans-wrap ${q.correct===i?'correct':''}" id="aw_${q.fieldIndex}_${i}"><div class="ans-letter">${L}</div><input type="text" class="ans-input" maxlength="80" placeholder="Antwort ${L}..." value="${q.answers[i]||''}" oninput="updQ(${q.fieldIndex},'a${i}',this.value)"/></div>`).join('')}
</div>
<div class="correct-row">
<span class="correct-lbl">✅ Richtige Antwort:</span>
<div class="correct-btns">${LETTERS.map((L,i)=>`<button class="correct-btn ${q.correct===i?'selected':''}" onclick="setCorr(${q.fieldIndex},${i})">${L}</button>`).join('')}</div>
</div>
<button class="tips-btn" onclick="this.nextElementSibling.classList.toggle('open')">💡 Tipps</button>
<div class="tips-box">• Stelle eine klare, eindeutige Frage<br>• Alle 4 Antworten sollten plausibel klingen<br>• Nur eine Antwort ist korrekt<br>• Beziehe die Frage auf dein Spielthema!</div>
`;
return c;
}
function updQ(fi,field,val){
const q=getQ(fi);if(!q)return;
if(field==='q')q.question=val;
else q.answers[parseInt(field.slice(1))]=val;
refQCard(fi);updQNext();
}
function setCorr(fi,idx){
const q=getQ(fi);if(!q)return;q.correct=idx;
LETTERS.forEach((_,i)=>{const w=document.getElementById(`aw_${fi}_${i}`);if(w)w.className='ans-wrap '+(i===idx?'correct':'');});
const card=document.getElementById('qc_'+fi);if(card)card.querySelectorAll('.correct-btn').forEach((b,i)=>b.classList.toggle('selected',i===idx));
refQCard(fi);updQNext();
}
function refQCard(fi){
const q=getQ(fi);if(!q)return;
const comp=isQComplete(q);
const c=document.getElementById('qc_'+fi);if(!c)return;
c.classList.toggle('complete',comp);
const st=document.getElementById('qst_'+fi);if(st){st.className='qc-status '+(comp?'done':'todo');st.textContent=comp?'✓ Fertig':'⏳ Ausfüllen';}
const num=document.getElementById('qnum_'+fi);if(num)num.style.background=comp?'linear-gradient(135deg,#10b981,#059669)':'linear-gradient(135deg,#7c3aed,#f5a623)';
}
function autoFill(){
ST.quizData.forEach((q,i)=>{if(!isQComplete(q)){const ex=QUIZ_EX[i%QUIZ_EX.length];q.question=ex.q;q.answers=[...ex.a];q.correct=ex.c;}});
buildQuiz();showToast('✅ Beispielfragen eingefügt!');
}
/* ══════════════════════════════════════════════
STEP 5 — REVIEW + TEST
══════════════════════════════════════════════ */
function buildReview(){
const fig=FIGURES.find(f=>f.id===ST.figure)||{e:'🎮',n:'Figur'};
const bg=BACKGROUNDS.find(b=>b.id===ST.background)||{scene:'🌍',n:'Welt'};
const area=document.getElementById('reviewArea');area.innerHTML='';
// Hero card
const hero=document.createElement('div');hero.className='hero-card';
hero.innerHTML=`<div class="hero-scene">${bg.scene}<span class="hero-fig">${fig.e}</span></div><div class="hero-info"><div class="hi-name">${ST.name||'Mein Spiel'}</div><div class="hi-desc">${ST.desc||'Keine Beschreibung.'}</div><div class="hero-tags"><div class="hero-tag">${fig.e} ${fig.n}</div><div class="hero-tag">🌍 ${bg.n}</div><div class="hero-tag">⬛ ${ST.fieldCount} Felder</div></div></div>`;
area.appendChild(hero);
// Rules
const rules=document.createElement('div');rules.className='card';
const filled=ST.fields.slice(1,ST.fieldCount-1).filter(Boolean).length;
rules.innerHTML=`<div class="card-title" style="margin-bottom:12px">⚙️ Spielregeln</div><div class="info-grid"><div class="info-block"><div class="ib-lbl">🎲 Bewegung</div><div class="ib-val">${ST.rules.movement==='dice'?'🎲 Würfeln':'👣 Ein Feld'}</div></div><div class="info-block"><div class="ib-lbl">${ST.rules.fail==='lives'?'❤️ Leben':'⭐ Punkte'}</div><div class="ib-val">${ST.rules.fail==='lives'?ST.rules.lives+' Leben':'+'+ST.rules.pts+' Pts'}</div></div><div class="info-block"><div class="ib-lbl">🕹️ Mini-Games</div><div class="ib-val">${filled} Felder</div></div><div class="info-block"><div class="ib-lbl">📖 Erzähltexte</div><div class="ib-val">${ST.storyItems.length}</div></div></div>`;
area.appendChild(rules);
// Timeline
const tlCard=document.createElement('div');tlCard.className='card';
tlCard.innerHTML='<div class="card-title" style="margin-bottom:12px">🗺️ Spielablauf</div>';
const tl=document.createElement('div');tl.className='tl';
for(let i=0;i<ST.fieldCount;i++){
const g=ST.fields[i];const mg=g?MINIGAMES.find(m=>m.id===g):null;
const isSt=i===0,isEn=i===ST.fieldCount-1;
ST.storyItems.filter(s=>s.position==='before'&&s.fieldIndex===i).forEach(s=>{
const it=document.createElement('div');it.className='tl-item story-it';
it.innerHTML=`<div class="tl-dot st">${s.emoji||'📖'}</div><div><div class="tl-lbl st">Erzähl-Text</div><div class="tl-sub">${s.text||'(noch leer)'}</div><div class="tl-badge st">Vor Feld ${i}</div></div>`;
tl.appendChild(it);
});
const it=document.createElement('div');it.className='tl-item';
let dCls,lCls,lbl,sub,badge='';
if(isSt){dCls='s';lCls='s';lbl='🟢 Start';sub='Das Abenteuer beginnt!';}
else if(isEn){dCls='e';lCls='e';lbl='🏁 Ziel';sub='Hier gewinnt man!';}
else if(mg){dCls='g';lCls='g';lbl='Feld '+i;sub=mg.n;badge=`<div class="tl-badge">${mg.e} ${mg.n}</div>`;}
else{dCls='em';lCls='em';lbl='Feld '+i;sub='Leeres Durchgangsfeld';}
it.innerHTML=`<div class="tl-dot ${dCls}">${isSt?'🟢':isEn?'🏁':mg?mg.e:'⬜'}</div><div><div class="tl-lbl ${lCls}">${lbl}</div><div class="tl-sub">${sub}</div>${badge}</div>`;
tl.appendChild(it);
ST.storyItems.filter(s=>s.position==='after'&&s.fieldIndex===i).forEach(s=>{
const it2=document.createElement('div');it2.className='tl-item story-it';
it2.innerHTML=`<div class="tl-dot st">${s.emoji||'📖'}</div><div><div class="tl-lbl st">Erzähl-Text</div><div class="tl-sub">${s.text||'(noch leer)'}</div><div class="tl-badge st">Nach Feld ${i}</div></div>`;
tl.appendChild(it2);
});
}
tlCard.appendChild(tl);area.appendChild(tlCard);
// Quiz preview
if(ST.quizData.length>0){
const qc=document.createElement('div');qc.className='card';
qc.innerHTML='<div class="card-title" style="margin-bottom:10px">❓ Quiz-Fragen</div>';
const ql=document.createElement('div');ql.className='qp-list';
ST.quizData.forEach((q,i)=>{
const qi=document.createElement('div');qi.className='qp-item';
qi.innerHTML=`<div class="qp-q">Frage ${i+1}: ${q.question||'(leer)'}</div><div class="qp-ans-grid">${LETTERS.map((L,j)=>`<div class="qp-ans ${q.correct===j?'cor':''}">${L} ${q.answers[j]||'?'}${q.correct===j?' ✓':''}</div>`).join('')}</div>`;
ql.appendChild(qi);
});
qc.appendChild(ql);area.appendChild(qc);
}
// Checklist
const cc=document.createElement('div');cc.className='card';cc.innerHTML='<div class="card-title" style="margin-bottom:10px">🔍 Checkliste</div>';
const cl=document.createElement('div');cl.className='checklist';
const qDone=ST.quizData.filter(isQComplete).length;
[
{ok:!!ST.name,t:ST.name?`Spielname: "${ST.name}"`:'Kein Spielname vergeben'},
{ok:!!(ST.figure&&ST.background),t:ST.figure?`Figur & Setting: ${fig.n} / ${bg.n}`:'Figur oder Setting fehlt'},
{ok:filled>0,t:`${filled} von ${ST.fieldCount-2} Spielfeldern belegt`},
{ok:ST.quizData.length===0||qDone===ST.quizData.length,t:ST.quizData.length===0?'Keine Quiz-Felder (ok)':`${qDone}/${ST.quizData.length} Quiz-Fragen ausgefüllt`},
].forEach(ch=>{const it=document.createElement('div');it.className='chk-item '+(ch.ok?'ok':'warn');it.innerHTML=`<span>${ch.ok?'✅':'⚠️'}</span>${ch.t}`;cl.appendChild(it);});
cc.appendChild(cl);area.appendChild(cc);
// Fill launch card
document.getElementById('lhFig').textContent=fig.e;
document.getElementById('lhName').textContent=ST.name||'Mein Spiel';
document.getElementById('lhDesc').textContent=ST.desc||'';
document.getElementById('lhPills').innerHTML=[
`<div class="lh-pill">${fig.e} ${fig.n}</div>`,
`<div class="lh-pill">🌍 ${bg.n}</div>`,
`<div class="lh-pill">⬛ ${ST.fieldCount} Felder</div>`,
`<div class="lh-pill">${ST.rules.fail==='lives'?'❤️ '+ST.rules.lives+' Leben':'⭐ Punkte'}</div>`,
].join('');
const uniqueG=[...new Set(ST.fields.filter(Boolean))];
document.getElementById('launchChk').innerHTML=[
{i:'🎲',t:`${ST.fieldCount} Felder · ${filled} Mini-Games`},
{i:'🕹️',t:`Games: ${uniqueG.map(g=>{const m=MINIGAMES.find(x=>x.id===g);return m?m.e:'❓';}).join(' ')||'—'}`},
{i:'📖',t:`${ST.storyItems.length} Erzähltexte`},
{i:'🎵',t:`Musik-Theme: ${bg.n}`},
].map(x=>`<div class="lc-item"><span>${x.i}</span><span style="flex:1">${x.t}</span><span class="lc-check">✓</span></div>`).join('');
}
let gamePlayed=false;
function doLaunch(){
save();
const w=window.open('game.html','Spiel',`width=${Math.min(1100,screen.width-60)},height=${Math.min(800,screen.height-60)},left=40,top=30,resizable=yes,scrollbars=no`);
if(!w){showToast('⚠️ Popup blockiert! Bitte Popups erlauben.');return;}
document.getElementById('btnLaunch').textContent='⏳ Warte auf Spielende...';
document.getElementById('btnLaunch').disabled=true;
const poll=setInterval(()=>{if(w.closed){clearInterval(poll);onGameDone();}},800);
}
function onGameDone(){
gamePlayed=true;
document.getElementById('btnLaunch').textContent='🔄 Nochmal spielen';
document.getElementById('btnLaunch').disabled=false;
document.getElementById('playedBadge').classList.add('visible');
const fc=document.getElementById('fbCard');fc.style.display='block';
fc.style.animation='slideIn 0.4s ease both';
setTimeout(()=>fc.scrollIntoView({behavior:'smooth',block:'start'}),500);
fbCur=0;fbAnswers={};renderFB();
}
/* ══════════════════════════════════════════════
FEEDBACK
══════════════════════════════════════════════ */
let fbCur=0,fbAnswers={};
function renderFB(){
const q=FB_QS[fbCur];
document.getElementById('fbFill').style.width=(fbCur/FB_QS.length*100)+'%';
document.getElementById('fbPrev').style.display=fbCur>0?'':'none';
document.getElementById('fbNext').textContent=fbCur<FB_QS.length-1?'Weiter →':'Auswertung ✅';
const area=document.getElementById('fbArea');
area.innerHTML=`<div class="fb-qnum">Frage ${fbCur+1} von ${FB_QS.length}</div><div class="fb-q">${q.q}</div>${q.sub?`<div class="fb-sub">${q.sub}</div>`:''}`;
if(q.t==='mc'){
const opts=document.createElement('div');opts.className='mc-opts';
q.opts.forEach((o,i)=>{const btn=document.createElement('div');btn.className='mc-opt'+(fbAnswers[q.id]===i?' sel':'');btn.innerHTML=`<div class="mc-dot"></div>${o}`;btn.addEventListener('click',()=>{fbAnswers[q.id]=i;opts.querySelectorAll('.mc-opt').forEach(b=>b.classList.remove('sel'));btn.classList.add('sel');document.getElementById('fbNext').disabled=false;});opts.appendChild(btn);});
area.appendChild(opts);
}
if(q.t==='scale'){
const row=document.createElement('div');row.className='scale-row';
for(let i=1;i<=5;i++){const btn=document.createElement('button');btn.className='scale-btn'+(fbAnswers[q.id]===i?' sel':'');btn.textContent=i;btn.addEventListener('click',()=>{fbAnswers[q.id]=i;row.querySelectorAll('.scale-btn').forEach(b=>b.classList.remove('sel'));btn.classList.add('sel');document.getElementById('fbNext').disabled=false;});row.appendChild(btn);}
area.appendChild(row);
const lbl=document.createElement('div');lbl.className='scale-lbls';lbl.innerHTML=`<span>${q.min}</span><span>${q.max}</span>`;area.appendChild(lbl);
}
if(q.t==='text'){
const ta=document.createElement('textarea');ta.className='fb-ta';ta.rows=3;ta.placeholder=q.ph||'';ta.value=fbAnswers[q.id]||'';ta.addEventListener('input',()=>{fbAnswers[q.id]=ta.value;document.getElementById('fbNext').disabled=ta.value.trim().length<3;});area.appendChild(ta);
}
document.getElementById('fbNext').disabled=fbAnswers[q.id]===undefined;
}
function fbFwd(){
fbCur++;
if(fbCur>=FB_QS.length){showSummaryCard();return;}
renderFB();
}
function fbBack(){if(fbCur>0){fbCur--;renderFB();}}
/* ══════════════════════════════════════════════
SUMMARY CARD
══════════════════════════════════════════════ */
function showSummaryCard(){
document.getElementById('fbCard').style.display='none';
const sc=document.getElementById('sumCard');sc.style.display='block';
sc.style.animation='slideIn 0.4s ease both';
setTimeout(()=>sc.scrollIntoView({behavior:'smooth',block:'start'}),400);
const fun=fbAnswers.fun||3;const mg=fbAnswers.minigames||3;
const diff=fbAnswers.difficulty;const replay=fbAnswers.replay;
document.getElementById('sumText').textContent='Du hast dein Spiel getestet und Feedback gegeben. Hier ist deine Auswertung:';
document.getElementById('sumScores').innerHTML=`<div class="sum-sc"><div class="sum-val">${fun}/5</div><div class="sum-lbl">Spaßfaktor</div></div><div class="sum-sc"><div class="sum-val">${mg}/5</div><div class="sum-lbl">Mini-Game Passung</div></div><div class="sum-sc"><div class="sum-val">${ST.fieldCount}</div><div class="sum-lbl">Felder</div></div><div class="sum-sc"><div class="sum-val">${ST.storyItems.length}</div><div class="sum-lbl">Erzähltexte</div></div>`;
const notes=[];
if(fun<=2)notes.push({i:'🎯',t:'Der Spaßfaktor ist noch niedrig — überlege, spannendere Mini-Games oder Erzähltexte hinzuzufügen.'});
else if(fun>=4)notes.push({i:'🔥',t:'Super Spaßfaktor! Dein Spiel macht offensichtlich Freude.'});
if(diff===0)notes.push({i:'⚠️',t:'Das Spiel war zu einfach — probiere schwierigere Mini-Games oder weniger Leben.'});
else if(diff===3)notes.push({i:'⚠️',t:'Das Spiel war zu schwer — erhöhe die Lebensanzahl oder wähle einfachere Mini-Games.'});
if(ST.storyItems.length===0)notes.push({i:'📖',t:'Keine Erzähltexte vorhanden — sie machen das Spiel viel lebendiger!'});
if(ST.fields.slice(1,ST.fieldCount-1).filter(Boolean).length<3)notes.push({i:'🕹️',t:'Nur wenige Felder sind belegt — füge mehr Mini-Games hinzu für mehr Abwechslung.'});
if(replay>=2)notes.push({i:'🚀',t:'Das Spiel hat Wiederspielwert — großartig!'});
if(fbAnswers.problems&&fbAnswers.problems.length>5)notes.push({i:'🔧',t:`Problem: "${fbAnswers.problems}" — geh zurück und überarbeite das.`});
if(notes.length===0)notes.push({i:'✅',t:'Alles sieht gut aus! Dein Spiel ist bereit zum Teilen.'});
document.getElementById('sumNotes').innerHTML=notes.map(n=>`<div class="sn-item"><span>${n.i}</span><span>${n.t}</span></div>`).join('');
save();localStorage.setItem('testFeedback',JSON.stringify(fbAnswers));
}
// ── URL-Sharing System ─────────────────────────────────────────────────────
// Komprimiert die Spielkonfiguration und kodiert sie als URL-Hash
// JSON → pako.gzip (DEFLATE) → Base64 → URL-Hash
function buildShareURL() {
// Nur die nötigen Felder exportieren (kein highestStep etc.)
const exportCfg = {
devName: ST.devName,
name: ST.name,
desc: ST.desc,
figure: ST.figure,
background: ST.background,
fieldCount: ST.fieldCount,
fields: ST.fields,
storyItems: ST.storyItems,
quizData: ST.quizData,
rules: ST.rules,
};
const json = JSON.stringify(exportCfg);
// pako ist über CDN geladen falls nicht verfügbar: direktes Base64
let encoded;
try {
const compressed = pako.deflate(json, { level: 9 });
// Uint8Array → binary string → btoa
const binary = Array.from(compressed).map(b => String.fromCharCode(b)).join('');
encoded = 'z:' + btoa(binary);
} catch(e) {
// Fallback ohne Kompression
encoded = 'j:' + btoa(unescape(encodeURIComponent(json)));
}
const base = window.location.href.replace(/\/editor\.html.*$/, '') + '/game.html';
return base + '#' + encoded;
}
function doPublish() {
const url = buildShareURL();
// Spiel-Info füllen
const bg = BACKGROUNDS.find(b => b.id === ST.background);
const fig = FIGURES.find(f => f.id === ST.figure);
const infoEl = document.getElementById('shareGameInfo');
infoEl.innerHTML = `
<div style="display:flex;gap:12px;align-items:center">
<div style="font-size:2rem">${fig ? fig.e : '🎮'}${bg ? bg.e : ''}</div>
<div>
<div style="font-family:'Fredoka One',cursive;font-size:1.1rem;color:#e2e0f0">${ST.name || 'Mein Spiel'}</div>
<div style="font-size:12px;color:#a7a3c2">von ${ST.devName || 'Anonym'} · ${ST.fieldCount} Felder · ${ST.fields.filter(Boolean).length} Mini-Games</div>
</div>
</div>
`;
// Link setzen
const input = document.getElementById('shareLinkInput');
input.value = url;
const lenEl = document.getElementById('shareLinkLen');
lenEl.textContent = `Link-Länge: ${url.length} Zeichen${url.length > 4000 ? ' ⚠️ zu lang für QR-Code!' : ' ✅ QR-Code-tauglich'}`;
// QR-Code generieren
const qrEl = document.getElementById('shareQR');
qrEl.innerHTML = '';
try {
new QRCode(qrEl, {
text: url,
width: 180,
height: 180,
colorDark: '#000000',
colorLight: '#ffffff',
correctLevel: QRCode.CorrectLevel.M,
});
} catch(e) {
qrEl.innerHTML = '<div style="color:#ef4444;font-size:12px;padding:20px">QR-Code konnte nicht erstellt werden.<br>Link zum Kopieren nutzen.</div>';
}
// Native Share Button ausblenden falls nicht unterstützt
// Overlay zeigen
const ov = document.getElementById('shareOverlay');
ov.style.display = 'flex';
document.body.style.overflow = 'hidden';
}
function closeShare() {
document.getElementById('shareOverlay').style.display = 'none';
document.body.style.overflow = '';
}
function copyShareLink() {
const input = document.getElementById('shareLinkInput');
input.select();
navigator.clipboard.writeText(input.value).then(() => {
const btn = document.getElementById('shareCopyBtn');
btn.textContent = '✅ Kopiert!';
setTimeout(() => btn.textContent = '📋 Kopieren', 2000);
}).catch(() => {
document.execCommand('copy');
showToast('📋 Link kopiert!');
});
}
function shareViaEmail() {
const url = document.getElementById('shareLinkInput').value;
const subject = encodeURIComponent('🎲 Mein Brettspiel: ' + (ST.name || 'Mein Spiel'));
const body = encodeURIComponent(
'Hallo!\n\nIch habe ein Brettspiel erstellt und möchte es mit dir teilen:\n\n' +
(ST.name || 'Mein Spiel') + '\n' + url + '\n\nViel Spaß beim Spielen!\n' + (ST.devName || '')
);
window.open('mailto:?subject=' + subject + '&body=' + body);
}
function shareViaWhatsApp() {
const url = document.getElementById('shareLinkInput').value;
const text = encodeURIComponent('🎲 Mein Brettspiel "' + (ST.name || 'Mein Spiel') + '" einfach anklicken und spielen! ' + url);
window.open('https://wa.me/?text=' + text, '_blank');
}
function shareNative() {
const url = document.getElementById('shareLinkInput').value;
if (navigator.share) {
navigator.share({
title: ST.name || 'Mein Brettspiel',
text: 'Ich habe ein Brettspiel erstellt!',
url: url,
}).catch(() => {});
} else {
copyShareLink();
showToast('📋 Link in die Zwischenablage kopiert!');
}
}
/* ══════════════════════════════════════════════
INIT
══════════════════════════════════════════════ */
// ── Init wird nach Modulen ausgeführt (siehe unten) ──
/* ══════════════════════════════════════════════
MINI-GAME TEST POPUP
══════════════════════════════════════════════ */
let mgTestLoop=null;
let mgTestActive=null;
const MG_DEMOS={
snake:{desc:'Steuere die Schlange mit den Pfeiltasten. Friss 3 Äpfel um zu gewinnen!',run:runSnake},
flappy:{desc:'Klicke oder drücke Leertaste um zu fliegen. Durch 3 Hindernisse = Sieg!',run:runFlappy},
memory:{desc:'Finde alle Paare! Klicke auf die Karten um sie umzudrehen.',run:runMemory},
reaction:{desc:'Wenn der Kreis GRÜN wird — so schnell wie möglich klicken!',run:runReaction},
quiz:{desc:'Quiz-Fragen kommen aus deinen eigenen Fragen (Schritt 4).',run:runQuizDemo},
puzzle:{desc:'Ordne die Teile in die richtige Reihenfolge!',run:runPuzzle},
spotdiff:{desc:'Finde den Unterschied zwischen den zwei Bildern!',run:runSpotdiff},
typing:{desc:'Tippe den angezeigten Text so schnell wie möglich!',run:runTyping},
snake:{desc:'Steuere die Schlange mit den Pfeiltasten. Friss 3 Äpfel um zu gewinnen!',run:runSnake},
flappy:{desc:'Klicke oder drücke Leertaste um zu fliegen. Durch 3 Hindernisse = Sieg!',run:runFlappy},
catch:{desc:'Bewege die Schüssel mit der Maus und fange 5 Äpfel!',run:runCatch},
basketball:{desc:'Klicke zum richtigen Zeitpunkt um den Ball zu werfen!',run:runBasketball},
maze:{desc:'Steuere mit den Pfeiltasten durch das Labyrinth!',run:runMaze},
simon:{desc:'Merke dir die Farbreihenfolge und tippe sie nach!',run:runSimon},
};
function openMGTest(id, e){
e&&e.stopPropagation();
const mg=MINIGAMES.find(m=>m.id===id);if(!mg)return;
closeMGTest();
currentMGId=id;
document.getElementById('mgTestEmoji').textContent=mg.e;
document.getElementById('mgTestTitle').textContent=mg.n+' — Probespiel';
// Beschreibung aus Modul oder MINIGAMES
const mod=window['MG_'+id];
document.getElementById('mgTestDesc').textContent=mod?mod.desc:(mg.desc||'');
document.getElementById('mgTestMsg').textContent='';
document.getElementById('mgTestMsg').className='';
const ctrl=document.getElementById('mgTestControls');
ctrl.innerHTML='<button class="mg-ctrl-btn" onclick="restartMGTest()">🔄 Neu starten</button><button class="mg-ctrl-btn secondary" onclick="closeMGTest()">Schließen</button>';
document.getElementById('mgTestOverlay').classList.add('open');
document.body.style.overflow='hidden';
// Modul-System: preview() aufrufen
const wrap=document.getElementById('mgTestWrap');
wrap.innerHTML='';
if(mod && mod.preview){
// Theme aus aktuellem ST-State
const bg=BACKGROUNDS.find(b=>b.id===ST.background);
const modCfg={
theme: bg?{primary:bg.color||'#7c3aed',glow:bg.glow||'rgba(124,58,237,0.4)'}:{primary:'#7c3aed',glow:'rgba(124,58,237,0.4)'},
quizData: ST.quizData||[],
devName: ST.devName,
gameName: ST.name,
};
// onResult-Handler
window._mgOnResult=(won)=>{
setMsg(won?'🏆 Gewonnen! 🎉':'💀 Verloren! Versuch es nochmal.', won?'win':'lose');
};
if(window.MGAPI) MGAPI.onResult=window._mgOnResult;
mgTestActive=mod.preview(wrap, wrap.offsetWidth||400, 280, modCfg);
} else {
// Fallback: altes Canvas-System
const canvas=document.getElementById('mgTestCanvas');
canvas.width=400;canvas.height=280;canvas.style.display='block';
wrap.appendChild(canvas);
const demo=MG_DEMOS[id];
if(demo)demo.run();
}
}
function closeMGTest(){
// Modul stoppen falls aktiv
if(mgTestActive&&mgTestActive.stop){mgTestActive.stop();mgTestActive=null;}
if(mgTestLoop){clearInterval(mgTestLoop);cancelAnimationFrame(mgTestLoop);mgTestLoop=null;}
document.removeEventListener('keydown',mgKeyHandler);
document.removeEventListener('mousemove',mgMouseHandler);
document.getElementById('mgTestOverlay').classList.remove('open');
document.body.style.overflow='';
// Wrap leeren
const wrap=document.getElementById('mgTestWrap');
if(wrap)wrap.innerHTML='';
const canvas=document.getElementById('mgTestCanvas');
if(canvas){const ctx=canvas.getContext('2d');ctx.clearRect(0,0,canvas.width,canvas.height);}
currentMGId=null;
}
let currentMGId=null;
function restartMGTest(){
if(currentMGId)openMGTest(currentMGId,null);
}
let mgKeyHandler=null,mgMouseHandler=null;
function setMsg(txt,cls=''){const m=document.getElementById('mgTestMsg');m.textContent=txt;m.className=cls;}
/* ─── SNAKE ─── */
function runSnake(){
currentMGId='snake';
const canvas=document.getElementById('mgTestCanvas');canvas.width=400;canvas.height=280;
const ctx=canvas.getContext('2d');
const CELL=20,COLS=20,ROWS=14;
let snake=[{x:10,y:7}],dir={x:1,y:0},nextDir={x:1,y:0};
let apple=rndApple(),score=0,running=true;
function rndApple(){return{x:Math.floor(Math.random()*COLS),y:Math.floor(Math.random()*ROWS)};}
function draw(){
ctx.fillStyle='#0f0e17';ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.strokeStyle='#1a1827';ctx.lineWidth=0.5;
for(let x=0;x<COLS;x++)for(let y=0;y<ROWS;y++){ctx.strokeRect(x*CELL,y*CELL,CELL,CELL);}
ctx.fillStyle='#7c3aed';
snake.forEach((s,i)=>{ctx.fillStyle=i===0?'#a78bfa':'#7c3aed';ctx.fillRect(s.x*CELL+1,s.y*CELL+1,CELL-2,CELL-2);});
ctx.font=`${CELL-2}px serif`;ctx.textAlign='center';
ctx.fillText('🍎',apple.x*CELL+CELL/2,apple.y*CELL+CELL/1.2);
ctx.fillStyle='#f5a623';ctx.font='bold 13px Nunito,sans-serif';ctx.textAlign='left';
ctx.fillText('Äpfel: '+score+' / 3',6,16);
}
document.removeEventListener('keydown',mgKeyHandler);
mgKeyHandler=e=>{
const map={'ArrowUp':{x:0,y:-1},'ArrowDown':{x:0,y:1},'ArrowLeft':{x:-1,y:0},'ArrowRight':{x:1,y:0},
'w':{x:0,y:-1},'s':{x:0,y:1},'a':{x:-1,y:0},'d':{x:1,y:0}};
if(map[e.key]){e.preventDefault();const d=map[e.key];if(d.x!==-dir.x||d.y!==-dir.y)nextDir=d;}
};
document.addEventListener('keydown',mgKeyHandler);
if(mgTestLoop)clearInterval(mgTestLoop);
mgTestLoop=setInterval(()=>{
if(!running)return;
dir=nextDir;
const head={x:snake[0].x+dir.x,y:snake[0].y+dir.y};
if(head.x<0||head.x>=COLS||head.y<0||head.y>=ROWS||snake.some(s=>s.x===head.x&&s.y===head.y)){
running=false;setMsg('💀 Game Over! Neu starten?','lose');return;}
snake.unshift(head);
if(head.x===apple.x&&head.y===apple.y){
score++;apple=rndApple();
if(score>=3){running=false;draw();setMsg('🏆 Gewonnen! 3 Äpfel gefressen!','win');return;}
}else snake.pop();
draw();
},140);
}
/* ─── FLAPPY ─── */
function runFlappy(){
currentMGId='flappy';
const canvas=document.getElementById('mgTestCanvas');canvas.width=400;canvas.height=280;
const ctx=canvas.getContext('2d');
let bird={y:140,vy:0},pipes=[],frame=0,score=0,running=true;
const PIPE_GAP=80,PIPE_W=40,GRAV=0.5,JUMP=-8;
function addPipe(){const top=40+Math.random()*100;pipes.push({x:400,top,bot:top+PIPE_GAP});}
function flap(){if(running)bird.vy=JUMP;}
canvas.onclick=flap;
document.removeEventListener('keydown',mgKeyHandler);
mgKeyHandler=e=>{if(e.code==='Space'&&running){e.preventDefault();flap();}};
document.addEventListener('keydown',mgKeyHandler);
if(mgTestLoop)cancelAnimationFrame(mgTestLoop);
function loop(){
if(!running)return;
ctx.fillStyle='#0f0e17';ctx.fillRect(0,0,400,280);
bird.vy+=GRAV;bird.y+=bird.vy;
ctx.font='24px serif';ctx.textAlign='center';
ctx.fillText('🐦',40,bird.y);
if(frame%90===0)addPipe();
pipes.forEach(p=>{
p.x-=2.5;
ctx.fillStyle='#10b981';
ctx.fillRect(p.x,0,PIPE_W,p.top);
ctx.fillRect(p.x,p.bot,PIPE_W,280-p.bot);
if(p.x+PIPE_W<40&&!p.passed){p.passed=true;score++;if(score>=3){running=false;setMsg('🏆 Gewonnen! 3 Hindernisse geschafft!','win');return;}}
if(p.x<50&&p.x+PIPE_W>26&&(bird.y<p.top||bird.y>p.bot)){running=false;setMsg('💀 Getroffen! Neu starten?','lose');}
});
pipes=pipes.filter(p=>p.x>-PIPE_W);
if(bird.y>280||bird.y<0){running=false;setMsg('💀 Abgestürzt! Neu starten?','lose');}
ctx.fillStyle='#f5a623';ctx.font='bold 13px Nunito,sans-serif';ctx.textAlign='left';
ctx.fillText('Hindernisse: '+score+' / 3',6,16);
frame++;
mgTestLoop=requestAnimationFrame(loop);
}
loop();
}
/* ─── MEMORY ─── */
function runMemory(){
currentMGId='memory';
const canvas=document.getElementById('mgTestCanvas');canvas.width=400;canvas.height=280;
const ctx=canvas.getContext('2d');
const EMOJIS=['🐶','🐱','🦊','🐸','🦄','🐙'];
let cards=[...EMOJIS,...EMOJIS].sort(()=>Math.random()-0.5).map((e,i)=>({e,i,flipped:false,matched:false}));
let first=null,lock=false,pairs=0;
const CW=60,CH=60,COLS=6,ROWS=2,OX=20,OY=60;
function draw(){
ctx.fillStyle='#0f0e17';ctx.fillRect(0,0,400,280);
ctx.fillStyle='#f5a623';ctx.font='bold 13px Nunito,sans-serif';ctx.textAlign='center';
ctx.fillText('Finde alle '+EMOJIS.length+' Paare!',200,30);
cards.forEach((card,i)=>{
const col=i%COLS,row=Math.floor(i/COLS);
const x=OX+col*(CW+8),y=OY+row*(CH+8);
if(card.matched){ctx.fillStyle='rgba(16,185,129,0.2)';}
else if(card.flipped){ctx.fillStyle='#22203a';}
else{ctx.fillStyle='#22203a';}
ctx.beginPath();ctx.roundRect(x,y,CW,CH,8);ctx.fill();
if(card.matched){ctx.strokeStyle='#10b981';ctx.lineWidth=2;ctx.stroke();}
else if(card.flipped){ctx.strokeStyle='#7c3aed';ctx.lineWidth=2;ctx.stroke();}
else{ctx.strokeStyle='#2e2b4a';ctx.lineWidth=1;ctx.stroke();}
if(card.flipped||card.matched){ctx.font=`${CW-16}px serif`;ctx.textAlign='center';ctx.fillText(card.e,x+CW/2,y+CH/1.4);}
else{ctx.fillStyle='#a7a3c2';ctx.font='bold 22px Nunito';ctx.textAlign='center';ctx.fillText('?',x+CW/2,y+CH/1.5);}
});
ctx.fillStyle='#f5a623';ctx.font='bold 13px Nunito,sans-serif';ctx.textAlign='left';
ctx.fillText('Paare: '+pairs+' / '+EMOJIS.length,6,16);
}
canvas.onclick=e=>{
if(lock)return;
const rect=canvas.getBoundingClientRect();
const mx=(e.clientX-rect.left)*(canvas.width/rect.width);
const my=(e.clientY-rect.top)*(canvas.height/rect.height);
cards.forEach((card,i)=>{
if(card.flipped||card.matched)return;
const col=i%COLS,row=Math.floor(i/COLS);
const x=OX+col*(CW+8),y=OY+row*(CH+8);
if(mx>x&&mx<x+CW&&my>y&&my<y+CH){
card.flipped=true;draw();
if(!first){first=card;}
else{
lock=true;
setTimeout(()=>{
if(first.e===card.e){first.matched=card.matched=true;pairs++;if(pairs===EMOJIS.length)setMsg('🏆 Alle Paare gefunden!','win');}
else{first.flipped=card.flipped=false;}
first=null;lock=false;draw();
},800);
}
}
});
};
draw();
}
/* ─── REACTION ─── */
function runReaction(){
currentMGId='reaction';
const canvas=document.getElementById('mgTestCanvas');canvas.width=400;canvas.height=280;
const ctx=canvas.getContext('2d');
let phase='wait',startT=0,round=0,times=[],timeout=null;
function drawCircle(color,label){
ctx.fillStyle='#0f0e17';ctx.fillRect(0,0,400,280);
ctx.beginPath();ctx.arc(200,140,70,0,Math.PI*2);
ctx.fillStyle=color;ctx.fill();
ctx.fillStyle='#fff';ctx.font='bold 16px Nunito,sans-serif';ctx.textAlign='center';
ctx.fillText(label,200,148);
ctx.fillStyle='#f5a623';ctx.font='bold 13px Nunito,sans-serif';
ctx.fillText('Runde '+Math.min(round+1,3)+' / 3',200,24);
}
function nextRound(){
phase='wait';drawCircle('#ef4444','Warte...');
if(timeout)clearTimeout(timeout);
timeout=setTimeout(()=>{phase='go';startT=Date.now();drawCircle('#10b981','JETZT!');},1500+Math.random()*2000);
}
canvas.onclick=()=>{
if(phase==='go'){
const t=Date.now()-startT;times.push(t);round++;
if(round>=3){const avg=Math.round(times.reduce((a,b)=>a+b)/times.length);setMsg('🏆 Durchschnitt: '+avg+'ms — '+(avg<500?'Blitzschnell!':'Gut gemacht!'),'win');return;}
setMsg('⚡ '+t+'ms!');nextRound();
} else if(phase==='wait'){
if(timeout)clearTimeout(timeout);
setMsg('Zu früh! Warte auf Grün.','lose');
setTimeout(()=>{setMsg('');nextRound();},1200);
}
};
nextRound();
}
/* ─── CATCH ─── */
function runCatch(){
currentMGId='catch';
const canvas=document.getElementById('mgTestCanvas');canvas.width=400;canvas.height=280;
const ctx=canvas.getContext('2d');
let bowl={x:200},apples=[],score=0,missed=0,running=true;
canvas.addEventListener('mousemove',e=>{const r=canvas.getBoundingClientRect();bowl.x=(e.clientX-r.left)*(400/r.width);});
canvas.addEventListener('touchmove',e=>{e.preventDefault();const r=canvas.getBoundingClientRect();bowl.x=(e.touches[0].clientX-r.left)*(400/r.width);},{passive:false});
if(mgTestLoop)cancelAnimationFrame(mgTestLoop);
let frame=0;
function loop(){
if(!running)return;
ctx.fillStyle='#0f0e17';ctx.fillRect(0,0,400,280);
if(frame%50===0)apples.push({x:20+Math.random()*360,y:0,speed:2+Math.random()*2});
apples.forEach(a=>{a.y+=a.speed;ctx.font='24px serif';ctx.textAlign='center';ctx.fillText('🍎',a.x,a.y);});
// Bowl
ctx.fillStyle='#f5a623';ctx.beginPath();ctx.ellipse(bowl.x,260,40,12,0,0,Math.PI*2);ctx.fill();
// Check catch/miss
apples=apples.filter(a=>{
if(a.y>248&&Math.abs(a.x-bowl.x)<40){score++;if(score>=5){running=false;setMsg('🏆 5 Äpfel gefangen!','win');}return false;}
if(a.y>280){missed++;if(missed>=3){running=false;setMsg('💀 3 Äpfel verpasst!','lose');}return false;}
return true;
});
ctx.fillStyle='#f5a623';ctx.font='bold 13px Nunito,sans-serif';ctx.textAlign='left';
ctx.fillText('Gefangen: '+score+'/5 Verpasst: '+missed+'/3',6,16);
frame++;mgTestLoop=requestAnimationFrame(loop);
}
loop();
}
/* ─── BASKETBALL ─── */
function runBasketball(){
currentMGId='basketball';
const canvas=document.getElementById('mgTestCanvas');canvas.width=400;canvas.height=280;
const ctx=canvas.getContext('2d');
let power=0,dir=1,shooting=false,ball=null,score=0,shots=0,running=true;
const HOOP={x:300,y:100};
if(mgTestLoop)cancelAnimationFrame(mgTestLoop);
function draw(){
ctx.fillStyle='#0f0e17';ctx.fillRect(0,0,400,280);
// Hoop
ctx.strokeStyle='#f5a623';ctx.lineWidth=3;
ctx.beginPath();ctx.moveTo(HOOP.x-20,HOOP.y);ctx.lineTo(HOOP.x+20,HOOP.y);ctx.stroke();
ctx.strokeStyle='#aaa';ctx.lineWidth=2;
ctx.beginPath();ctx.moveTo(HOOP.x+20,HOOP.y);ctx.lineTo(HOOP.x+20,HOOP.y+40);ctx.lineTo(HOOP.x+60,HOOP.y+40);ctx.stroke();
// Power bar
if(!shooting){
ctx.fillStyle='#2e2b4a';ctx.fillRect(30,240,160,14);
ctx.fillStyle=power<50?'#10b981':'#ef4444';ctx.fillRect(30,240,power*1.6,14);
ctx.fillStyle='#fff';ctx.font='bold 11px Nunito';ctx.textAlign='left';ctx.fillText('Klicken = Schießen!',30,232);
}
// Ball
if(ball){ctx.font='28px serif';ctx.textAlign='center';ctx.fillText('🏀',ball.x,ball.y);}
else{ctx.font='28px serif';ctx.textAlign='center';ctx.fillText('🏀',80,250);}
ctx.fillStyle='#f5a623';ctx.font='bold 13px Nunito,sans-serif';ctx.textAlign='left';
ctx.fillText('Treffer: '+score+' Würfe: '+shots+'/5',6,16);
}
function loop(){
if(!shooting){power+=dir*2;if(power>=100||power<=0)dir*=-1;}
if(ball){
ball.x+=ball.vx;ball.y+=ball.vy;ball.vy+=0.4;
if(Math.abs(ball.x-HOOP.x)<22&&Math.abs(ball.y-HOOP.y)<18){score++;setMsg('🏀 Treffer! +1','win');}
if(ball.y>290){shooting=false;ball=null;if(shots>=5){running=false;setMsg(score>=3?'🏆 '+score+'/5 Treffer!':'😅 '+score+'/5 Treffer','win');return;}}
}
draw();if(running)mgTestLoop=requestAnimationFrame(loop);
}
canvas.onclick=()=>{
if(!running||shooting)return;
shots++;shooting=true;
const angle=-(0.6+power/100*0.6);const speed=8+power/12;
ball={x:80,y:250,vx:Math.cos(angle)*speed,vy:Math.sin(angle)*speed};
setTimeout(()=>{if(shooting){shooting=false;ball=null;}},2000);
};
loop();
}
/* ─── MAZE ─── */
function runMaze(){
currentMGId='maze';
const canvas=document.getElementById('mgTestCanvas');canvas.width=400;canvas.height=280;
const ctx=canvas.getContext('2d');
const CELL=40,COLS=10,ROWS=7;
// Simple fixed maze: 0=open, 1=wall
const maze=[
[0,1,0,0,0,1,0,0,0,0],
[0,1,0,1,0,1,0,1,1,0],
[0,0,0,1,0,0,0,0,1,0],
[1,1,0,1,1,1,1,0,1,0],
[0,0,0,0,0,0,1,0,0,0],
[0,1,1,1,0,1,1,1,0,1],
[0,0,0,0,0,0,0,0,0,0],
];
let player={x:0,y:0},won=false;
const GOAL={x:9,y:6};
document.removeEventListener('keydown',mgKeyHandler);
mgKeyHandler=e=>{
if(won)return;
const moves={'ArrowUp':{dx:0,dy:-1},'ArrowDown':{dx:0,dy:1},'ArrowLeft':{dx:-1,dy:0},'ArrowRight':{dx:1,dy:0}};
if(!moves[e.key])return;e.preventDefault();
const{dx,dy}=moves[e.key];const nx=player.x+dx,ny=player.y+dy;
if(nx>=0&&nx<COLS&&ny>=0&&ny<ROWS&&maze[ny][nx]===0){player.x=nx;player.y=ny;}
if(player.x===GOAL.x&&player.y===GOAL.y){won=true;draw();setMsg('🏆 Ziel erreicht!','win');}
else draw();
};
document.addEventListener('keydown',mgKeyHandler);
function draw(){
ctx.fillStyle='#0f0e17';ctx.fillRect(0,0,400,280);
for(let y=0;y<ROWS;y++)for(let x=0;x<COLS;x++){
ctx.fillStyle=maze[y][x]===1?'#2e2b4a':'#1a1827';
ctx.fillRect(x*CELL,y*CELL,CELL,CELL);
ctx.strokeStyle='#0f0e17';ctx.lineWidth=1;ctx.strokeRect(x*CELL,y*CELL,CELL,CELL);
}
ctx.font='26px serif';ctx.textAlign='center';
ctx.fillText('🏁',GOAL.x*CELL+CELL/2,GOAL.y*CELL+CELL/1.4);
ctx.fillText('🧙‍♂️',player.x*CELL+CELL/2,player.y*CELL+CELL/1.4);
}
draw();
}
/* ─── SIMON SAYS ─── */
function runSimon(){
currentMGId='simon';
const canvas=document.getElementById('mgTestCanvas');canvas.width=400;canvas.height=280;
const ctx=canvas.getContext('2d');
const COLORS=['#ef4444','#10b981','#f5a623','#7c3aed'];
const LABELS=['ROT','GRÜN','GELB','LILA'];
const RECTS=[{x:30,y:60,w:160,h:100},{x:210,y:60,w:160,h:100},{x:30,y:170,w:160,h:100},{x:210,y:170,w:160,h:100}];
let seq=[],playerSeq=[],step=0,showing=false,won=false;
function draw(lit=-1){
ctx.fillStyle='#0f0e17';ctx.fillRect(0,0,400,280);
RECTS.forEach((r,i)=>{
ctx.fillStyle=i===lit?COLORS[i]:COLORS[i]+'55';
ctx.beginPath();ctx.roundRect(r.x,r.y,r.w,r.h,10);ctx.fill();
ctx.fillStyle='#fff';ctx.font='bold 14px Nunito,sans-serif';ctx.textAlign='center';
ctx.fillText(LABELS[i],r.x+r.w/2,r.y+r.h/2+5);
});
ctx.fillStyle='#f5a623';ctx.font='bold 13px Nunito,sans-serif';ctx.textAlign='center';
ctx.fillText('Runde '+seq.length+' / 4',200,22);
}
function showSeq(i=0){
if(i>=seq.length){showing=false;setMsg('Jetzt du! Tippe die Reihenfolge nach.');return;}
showing=true;draw(seq[i]);
setTimeout(()=>{draw(-1);setTimeout(()=>showSeq(i+1),300);},600);
}
function nextRound(){seq.push(Math.floor(Math.random()*4));playerSeq=[];step=0;draw();setTimeout(()=>showSeq(),600);}
canvas.onclick=e=>{
if(showing||won)return;
const rect=canvas.getBoundingClientRect();
const mx=(e.clientX-rect.left)*(400/rect.width);
const my=(e.clientY-rect.top)*(280/rect.height);
RECTS.forEach((r,i)=>{
if(mx>r.x&&mx<r.x+r.w&&my>r.y&&my<r.y+r.h){
draw(i);setTimeout(()=>draw(-1),200);
if(seq[step]===i){
step++;
if(step===seq.length){
if(seq.length>=4){won=true;setMsg('🏆 Simon Says gewonnen!','win');return;}
setMsg('✅ Richtig! Weiter...');setTimeout(nextRound,1000);
}
} else {setMsg('❌ Falsch! Nochmal.','lose');setTimeout(()=>{seq=[];nextRound();},1200);}
}
});
};
nextRound();
}
/* ─── QUIZ DEMO ─── */
function runQuizDemo(){
currentMGId='quiz';
const canvas=document.getElementById('mgTestCanvas');canvas.width=400;canvas.height=280;
const ctx=canvas.getContext('2d');
// Use own quiz data or fallback
const questions=ST.quizData.filter(q=>q.question&&q.answers.every(a=>a)&&q.correct!==null);
const fallback=[{question:'Was ist die Hauptstadt von Deutschland?',answers:['Paris','London','Berlin','Madrid'],correct:2},{question:'Wie viele Seiten hat ein Dreieck?',answers:['2','3','4','5'],correct:1}];
const pool=questions.length>0?questions:fallback;
const q=pool[Math.floor(Math.random()*pool.length)];
ctx.fillStyle='#0f0e17';ctx.fillRect(0,0,400,280);
ctx.fillStyle='#fff';ctx.font='bold 14px Nunito,sans-serif';ctx.textAlign='center';
wrapText(ctx,q.question,200,50,360,20);
const cols=['#7c3aed','#10b981','#f5a623','#ef4444'];
const ANSWERS_RECTS=[{x:20,y:110,w:170,h:60},{x:210,y:110,w:170,h:60},{x:20,y:180,w:170,h:60},{x:210,y:180,w:170,h:60}];
ANSWERS_RECTS.forEach((r,i)=>{
ctx.fillStyle=cols[i]+'aa';ctx.beginPath();ctx.roundRect(r.x,r.y,r.w,r.h,10);ctx.fill();
ctx.fillStyle='#fff';ctx.font='bold 13px Nunito,sans-serif';ctx.textAlign='center';
ctx.fillText(['A','B','C','D'][i]+') '+q.answers[i],r.x+r.w/2,r.y+r.h/2+5);
});
canvas.onclick=e=>{
const rect=canvas.getBoundingClientRect();
const mx=(e.clientX-rect.left)*(400/rect.width);
const my=(e.clientY-rect.top)*(280/rect.height);
ANSWERS_RECTS.forEach((r,i)=>{
if(mx>r.x&&mx<r.x+r.w&&my>r.y&&my<r.y+r.h){
canvas.onclick=null;
ctx.fillStyle='#0f0e17';ctx.fillRect(0,0,400,280);
ANSWERS_RECTS.forEach((r2,j)=>{
ctx.fillStyle=j===q.correct?'#10b981':j===i?'#ef4444':cols[j]+'44';
ctx.beginPath();ctx.roundRect(r2.x,r2.y,r2.w,r2.h,10);ctx.fill();
ctx.fillStyle='#fff';ctx.font='bold 13px Nunito,sans-serif';ctx.textAlign='center';
ctx.fillText(['A','B','C','D'][j]+') '+q.answers[j],r2.x+r2.w/2,r2.y+r2.h/2+5);
});
wrapText(ctx,q.question,200,50,360,20);
setMsg(i===q.correct?'🏆 Richtig!':'❌ Falsch! Richtig war: '+['A','B','C','D'][q.correct],i===q.correct?'win':'lose');
}
});
};
}
function wrapText(ctx,text,x,y,maxW,lh){
const words=text.split(' ');let line='';
for(let w of words){const test=line+w+' ';if(ctx.measureText(test).width>maxW&&line!==''){ctx.fillText(line.trim(),x,y);line=w+' ';y+=lh;}else line=test;}
ctx.fillText(line.trim(),x,y);
}
/* ─── STUBS FOR OTHER GAMES ─── */
function runPuzzle(){runStub('puzzle','🧩','Sortiere die Zahlen!','Zahlen-Reihenfolge');}
function runSpotdiff(){runStub('spotdiff','🔍','Finde den Unterschied zwischen den Bildern.','Unterschied finden');}
function runTyping(){
currentMGId='typing';
const canvas=document.getElementById('mgTestCanvas');canvas.width=400;canvas.height=280;
const ctx=canvas.getContext('2d');
const WORDS=['Hallo Welt','Spielen macht Spaß','Quiz Turnier','Abenteuer'];
const target=WORDS[Math.floor(Math.random()*WORDS.length)];
let typed='',done=false,startT=Date.now();
function draw(){
ctx.fillStyle='#0f0e17';ctx.fillRect(0,0,400,280);
ctx.fillStyle='#a7a3c2';ctx.font='14px Nunito,sans-serif';ctx.textAlign='center';ctx.fillText('Tippe den folgenden Text:',200,60);
ctx.fillStyle='#f5a623';ctx.font='bold 22px Fredoka One,cursive';ctx.fillText(target,200,110);
// Show typed so far
for(let i=0;i<typed.length;i++){
const ok=typed[i]===target[i];
ctx.fillStyle=ok?'#10b981':'#ef4444';
ctx.font='bold 20px Nunito,sans-serif';ctx.textAlign='left';
ctx.fillText(typed[i],50+i*14,160);
}
// Cursor
ctx.fillStyle='#7c3aed';ctx.fillRect(50+typed.length*14,143,2,22);
}
document.removeEventListener('keydown',mgKeyHandler);
mgKeyHandler=e=>{
if(done)return;
if(e.key==='Backspace'){typed=typed.slice(0,-1);}
else if(e.key.length===1){typed+=e.key;}
if(typed===target){done=true;const t=((Date.now()-startT)/1000).toFixed(1);setMsg('🏆 Fertig in '+t+'s!','win');}
draw();
};
document.addEventListener('keydown',mgKeyHandler);
draw();
}
function runStub(id,emoji,desc,name){
currentMGId=id;
const canvas=document.getElementById('mgTestCanvas');canvas.width=400;canvas.height=280;
const ctx=canvas.getContext('2d');
ctx.fillStyle='#0f0e17';ctx.fillRect(0,0,400,280);
ctx.font='60px serif';ctx.textAlign='center';ctx.fillText(emoji,200,130);
ctx.fillStyle='#a7a3c2';ctx.font='bold 16px Nunito,sans-serif';ctx.fillText(desc,200,190);
ctx.fillStyle='#7c3aed';ctx.font='bold 13px Nunito,sans-serif';ctx.fillText('(Im echten Spiel vollständig spielbar)',200,220);
}
/* ══════════════════════════════════════════════
PYTHON CODE GENERATOR — Live-Vorschau
══════════════════════════════════════════════ */
const MINIGAME_PY = {
snake: 'snake_game',
flappy: 'flappy_bird',
memory: 'memory_cards',
quiz: 'quiz_challenge',
reaction: 'reaction_test',
basketball: 'basketball_shot',
catch: 'apple_catcher',
maze: 'maze_runner',
simon: 'simon_says',
puzzle: 'number_puzzle',
spotdiff: 'spot_difference',
typing: 'typing_race',
};
const MINIGAME_COMMENTS = {
snake: 'Schlange steuern Iss das Futter ohne gegen die Wand zu fahren',
flappy: 'Flugspiel Durch Hindernisse fliegen ohne zu crashen',
memory: 'Memory Alle Paare finden und merken',
quiz: 'Quiz Frage beantworten, richtige Antwort wählen',
reaction: 'Reaktionstest So schnell wie möglich auf Signal reagieren',
basketball: 'Basketball Ball zum richtigen Zeitpunkt werfen',
catch: 'Fangspiel Fallende Objekte mit dem Korb auffangen',
maze: 'Labyrinth Den Ausweg aus dem Labyrinth finden',
simon: 'Simon Says Farbsequenz merken und wiederholen',
puzzle: 'Zahlenrätsel Teile in die richtige Reihenfolge bringen',
spotdiff: 'Unterschiede suchen Alle Unterschiede im Bild finden',
typing: 'Tipp-Rennen Text so schnell wie möglich eintippen',
};
// ── Progressive unlock tracking ─────────────────────────────
const unlocked = new Set();
let lastKey = null; // which section was LAST interacted with → gets yellow highlight
function setCodeFocus(key){
unlocked.add(key);
lastKey = key;
scheduleCodeUpdate(50);
}
// Focus listener for text inputs
document.addEventListener('focusin', e=>{
const id = e.target.id || '';
if(id==='s1devname') setCodeFocus('dev');
if(id==='s1name') setCodeFocus('gamename');
if(id==='s1desc') setCodeFocus('gamedesc');
if(id && id.startsWith('qq')) setCodeFocus('quiz');
});
// ─────────────────────────────────────────────
function buildPythonCode(){
const s = ST;
const fig = FIGURES.find(f=>f.id===s.figure);
const bg = BACKGROUNDS.find(b=>b.id===s.background);
// Empty until first interaction
if(unlocked.size===0 && !s.devName && !s.name && !s.figure) return [];
const lines = [];
// hi() returns true only for the last-touched key
const hi = key => lastKey === key;
// Header + imports — always shown once anything unlocked
lines.push({t:'cm', v:'# ═══════════════════════════════════════════'});
lines.push({t:'cm', v:'# boardgame.py — Spiel-Generator PH Weingarten'});
lines.push({t:'cm', v:'# ═══════════════════════════════════════════'});
lines.push({t:'bl'});
lines.push({t:'cm', v:'# Module importieren'});
lines.push({t:'kw', v:'import', rest:' boardgame_engine as engine'});
lines.push({t:'kw', v:'import', rest:' minigames'});
lines.push({t:'kw', v:'from', rest:' config import GameConfig, Field, StoryText'});
lines.push({t:'bl'});
// DEVELOPER
if(unlocked.has('dev') || s.devName){
lines.push({t:'cm', v:'# Wer hat dieses Spiel programmiert?'});
if(s.devName)
lines.push({t:'ass', var:'developer_name', val:`"${s.devName}"`, hi:hi('dev')});
else
lines.push({t:'ph', var:'developer_name', hint:'← tippe deinen Namen'});
lines.push({t:'bl'});
}
// GAME NAME
if(unlocked.has('gamename') || s.name){
lines.push({t:'cm', v:'# Wie heißt das Spiel?'});
if(s.name)
lines.push({t:'ass', var:'game_name', val:`"${s.name}"`, hi:hi('gamename')});
else
lines.push({t:'ph', var:'game_name', hint:'← tippe den Spielnamen'});
lines.push({t:'bl'});
}
// DESCRIPTION
if(unlocked.has('gamedesc') || s.desc){
lines.push({t:'cm', v:'# Kurze Beschreibung des Spiels'});
if(s.desc)
lines.push({t:'ass', var:'game_description', val:`"${s.desc}"`, hi:hi('gamedesc')});
else
lines.push({t:'ph', var:'game_description', hint:'← tippe eine Beschreibung'});
lines.push({t:'bl'});
}
// FIGURE
if(unlocked.has('figure') || s.figure){
lines.push({t:'cm', v:'# Spielfigur auswählen'});
if(s.figure)
lines.push({t:'ass', var:'player_figure',
val:`"${s.figure}" # ${fig?fig.e+' '+fig.n:''}`, hi:hi('figure')});
else
lines.push({t:'ph', var:'player_figure', hint:'← klicke eine Figur an'});
lines.push({t:'bl'});
}
// BACKGROUND
if(unlocked.has('background') || s.background){
lines.push({t:'cm', v:'# Spielwelt / Hintergrund'});
if(s.background)
lines.push({t:'ass', var:'world_setting',
val:`"${s.background}" # ${bg?bg.e+' '+bg.n:''}`, hi:hi('background')});
else
lines.push({t:'ph', var:'world_setting', hint:'← klicke eine Welt an'});
lines.push({t:'bl'});
}
// MOVEMENT
if(unlocked.has('movement')){
lines.push({t:'cm', v:'# Wie viele Felder pro Runde?'});
lines.push({t:'ass', var:'movement_type',
val: s.rules.movement==='step' ? '"schritt" # immer genau 1 Feld'
: '"wuerfeln" # zufällig 1-6 Felder',
hi:hi('movement')});
lines.push({t:'bl'});
}
// FAIL MODE
if(unlocked.has('failmode')){
lines.push({t:'cm', v:'# Was passiert wenn man verliert?'});
if(s.rules.fail==='lives'){
lines.push({t:'ass', var:'verlust_system', val:'"leben"', hi:hi('failmode')});
lines.push({t:'ass', var:'anzahl_leben', val:String(s.rules.lives||3), hi:hi('lives')});
} else {
lines.push({t:'ass', var:'verlust_system', val:'"punkte"', hi:hi('failmode')});
lines.push({t:'ass', var:'punkte_pro_sieg',val:String(s.rules.pts||10), hi:hi('pts')});
}
lines.push({t:'bl'});
}
// LIVES / PTS sub-option
if(unlocked.has('lives') && s.rules.fail==='lives'){
// already rendered above, just make sure hi updates
}
// FIELD COUNT
if(unlocked.has('fieldcount')){
lines.push({t:'cm', v:'# Wie groß ist das Spielfeld?'});
lines.push({t:'ass', var:'anzahl_felder', val:String(s.fieldCount), hi:hi('fieldcount')});
lines.push({t:'bl'});
}
// BOARD SETUP — only once a game was dropped
const MG_PY ={snake:'schlangen_spiel',flappy:'flug_spiel',memory:'memory',quiz:'quiz',reaction:'reaktionstest',basketball:'basketball',catch:'fangen',maze:'labyrinth',simon:'simon_says',puzzle:'raetsel',spotdiff:'unterschiede',typing:'tipp_rennen'};
const MG_CM ={snake:'Schlange steuern',flappy:'Durch Hindernisse fliegen',memory:'Paare finden',quiz:'Frage beantworten',reaction:'Schnell reagieren',basketball:'Ball werfen',catch:'Objekte fangen',maze:'Ausweg finden',simon:'Sequenz merken',puzzle:'Rätsel lösen',spotdiff:'Unterschiede finden',typing:'Text eintippen'};
const hasAnyField = (s.fields||[]).some(Boolean);
if(unlocked.has('fields') || hasAnyField){
lines.push({t:'cm', v:'# Spielfeld aufbauen — jedes Feld wird definiert'});
lines.push({t:'fn-def', name:'setup_spielfeld', args:''});
lines.push({t:'ind', v:'felder = []'});
lines.push({t:'bl'});
lines.push({t:'ind-cm', v:'# Startfeld (Index 0)'});
lines.push({t:'ind', v:'felder.append(Field(index=0, typ="start"))'});
for(let i=1;i<s.fieldCount-1;i++){
const fId=(s.fields||[])[i];
lines.push({t:'bl'});
if(fId){
lines.push({t:'ind-cm', v:`# Feld ${i}: Mini-Game → ${MG_CM[fId]||fId}`});
lines.push({t:'ind', v:`felder.append(Field(index=${i}, typ="minigame", spiel="${MG_PY[fId]||fId}"))`,
hi: hi('fields') && (s.fields||[])[i]===fId});
} else {
lines.push({t:'ind-cm', v:`# Feld ${i}: kein Spiel, einfach durchlaufen`});
lines.push({t:'ind', v:`felder.append(Field(index=${i}, typ="leer"))`});
}
}
lines.push({t:'bl'});
lines.push({t:'ind-cm', v:`# Zielfeld (Index ${s.fieldCount-1}) 🏁`});
lines.push({t:'ind', v:`felder.append(Field(index=${s.fieldCount-1}, typ="ziel"))`});
lines.push({t:'bl'});
lines.push({t:'ind', v:'return felder'});
lines.push({t:'bl'});
}
// MINIGAME FUNCTIONS
const usedGames=[...new Set((s.fields||[]).filter(Boolean))];
if(usedGames.length>0){
const MG_CM2={snake:'Schlange steuern ohne Wand zu treffen',flappy:'Durch alle Hindernisse fliegen',memory:'Alle Kartenpaare finden',quiz:'Die richtige Antwort wählen',reaction:'Schnell auf Signal drücken',basketball:'Ball zum richtigen Moment werfen',catch:'Fallende Objekte auffangen',maze:'Den Ausgang aus dem Labyrinth finden',simon:'Farbreihenfolge merken und wiederholen',puzzle:'Zahlen in die richtige Reihenfolge bringen',spotdiff:'Alle Unterschiede im Bild finden',typing:'Text so schnell wie möglich eintippen'};
lines.push({t:'cm', v:'# Für jedes Mini-Game gibt es eine eigene Funktion'});
usedGames.forEach(id=>{
const pyName=MG_PY[id]||id;
lines.push({t:'bl'});
lines.push({t:'fn-def', name:`spiele_${pyName}`, args:'spieler'});
lines.push({t:'ind-cm', v:`# Aufgabe: ${MG_CM2[id]||id}`});
lines.push({t:'ind', v:`ergebnis = minigames.${pyName}.starten(spieler)`});
lines.push({t:'ind', v:`return ergebnis.gewonnen`});
});
lines.push({t:'bl'});
}
// QUIZ
const quizItems=(s.quizData||[]).filter(q=>q&&q.question);
if(quizItems.length>0 || unlocked.has('quiz')){
lines.push({t:'cm', v:'# Quiz-Fragen für das Spiel'});
lines.push({t:'ass', var:'fragen', val:'[', hi:false});
quizItems.forEach(q=>{
const clean=q.question.replace(/"/g,"'").slice(0,50);
const ans=q.answers.map(a=>`"${(a||'').replace(/"/g,"'")}"`).join(', ');
const cor=q.correct!=null?`"${(q.answers[q.correct]||'').replace(/"/g,"'")}"`:'None';
lines.push({t:'ind', v:`{"frage": "${clean}", "antworten": [${ans}], "richtig": ${cor}},`});
});
if(quizItems.length===0) lines.push({t:'ind-cm', v:'# noch keine Fragen eingetragen...'});
lines.push({t:'ass-end', v:']'});
lines.push({t:'bl'});
}
// MAIN BLOCK
lines.push({t:'cm', v:'# ── Spiel starten ───────────────────────────'});
lines.push({t:'kw', v:'if', rest:" __name__ == '__main__':"});
lines.push({t:'ind-cm', v:'# Konfiguration zusammenstellen und Spiel starten'});
lines.push({t:'ind', v:'config = GameConfig('});
lines.push({t:'ind2', v:`name=${s.name?`"${s.name}"`:'""'},`});
lines.push({t:'ind2', v:`developer=${s.devName?`"${s.devName}"`:'""'},`});
if(s.figure) lines.push({t:'ind2', v:`figure="${s.figure}",`});
if(s.background) lines.push({t:'ind2', v:`setting="${s.background}",`});
if(hasAnyField) lines.push({t:'ind2', v:'board=setup_spielfeld(),'});
if(quizItems.length) lines.push({t:'ind2', v:'questions=fragen,'});
lines.push({t:'ind', v:')'});
lines.push({t:'bl'});
lines.push({t:'ind', v:'engine.run(config)'});
return lines;
}
function renderToken(line){
const esc = s => String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
let r='';
switch(line.t){
case 'cm': r=`<span class="py-cm">${esc(line.v)}</span>`; break;
case 'bl': return '';
case 'ph': r=`<span class="py-var">${esc(line.var)}</span><span class="py-punc"> = </span><span class="py-cm">"???" <span style="color:#e06c75;font-style:italic">${esc(line.hint||'')}</span></span>`; break;
case 'kw': r=`<span class="py-kw">${esc(line.v)}</span><span class="py-val">${esc(line.rest||'')}</span>`; break;
case 'ass': r=`<span class="py-var">${esc(line.var)}</span><span class="py-punc"> = </span><span class="py-str">${esc(String(line.val))}</span>`; break;
case 'ass-end':r=`<span class="py-punc">${esc(line.v)}</span>`; break;
case 'fn-def': r=`<span class="py-kw">def </span><span class="py-fn">${esc(line.name)}</span><span class="py-punc">(${esc(line.args||'')})</span><span class="py-punc">:</span>`; break;
case 'ind': r=` <span class="py-val">${esc(line.v)}</span>`; break;
case 'ind2': r=` <span class="py-val">${esc(line.v)}</span>`; break;
case 'ind-cm': r=` <span class="py-cm">${esc(line.v)}</span>`; break;
default: return esc(line.v||'');
}
return line.hi ? `<span class="py-hi">${r}</span>` : r;
}
let codeTypingTimer = null;
let lastLineCount = 0;
let lastKey_scroll = null; // prevent scroll thrash
function updateCodePane(){
const lines = buildPythonCode();
const codeEl = document.getElementById('codeContent');
const numsEl = document.getElementById('codeLineNums');
const linesEl= document.getElementById('codeLines');
if(!codeEl) return;
// Filename
const dev = ST.devName ? ST.devName.toLowerCase().replace(/[^a-z0-9]/g,'_') : 'dev';
const gn = ST.name ? ST.name.toLowerCase().replace(/[^a-z0-9]/g,'_').slice(0,20) : 'boardgame';
const fnEl = document.getElementById('codeFilename');
if(fnEl) fnEl.textContent = (ST.name||ST.devName) ? `${gn}_von_${dev}.py` : 'boardgame.py';
if(lines.length===0){
codeEl.innerHTML='<span class="py-cm"># Klicke ein Feld an — dein Code erscheint hier ✨</span>';
numsEl.innerHTML='<div>1</div>';
if(linesEl) linesEl.textContent='1 Zeile';
lastLineCount=0; return;
}
let html='', lineNum=1;
const lineNums=[];
lines.forEach(line=>{
if(line.t==='bl'){ html+='\n'; }
else { html+=renderToken(line)+'\n'; }
lineNums.push(lineNum++);
});
const newCount = lines.length;
const grew = newCount > lastLineCount;
const prevCount= lastLineCount;
lastLineCount = newCount;
codeEl.innerHTML = html;
numsEl.innerHTML = lineNums.map(n=>`<div>${n}</div>`).join('');
if(linesEl) linesEl.textContent = lineNum+' Zeilen';
const status = document.getElementById('codeStatus');
if(status){ status.textContent='● Live'; setTimeout(()=>{ status.textContent='● Bereit'; },800); }
// Scroll: only when new lines appeared AND key changed (avoid thrash while typing)
const scroll = document.getElementById('codeScroll');
if(scroll && grew && lastKey !== lastKey_scroll){
lastKey_scroll = lastKey;
// Find the first highlighted line's position
setTimeout(()=>{
const hiEl = codeEl.querySelector('.py-hi');
if(hiEl){
const pre = codeEl;
const preTop = pre.getBoundingClientRect().top;
const hiTop = hiEl.getBoundingClientRect().top;
const offset = hiTop - preTop;
const scrollTarget = scroll.scrollTop + offset - 80;
scroll.scrollTo({top: Math.max(0, scrollTarget), behavior:'smooth'});
}
}, 80);
}
}
function scheduleCodeUpdate(delay=80){
clearTimeout(codeTypingTimer);
codeTypingTimer = setTimeout(updateCodePane, delay);
}
document.addEventListener('input', ()=>scheduleCodeUpdate(50));
document.addEventListener('change', ()=>scheduleCodeUpdate(50));
// Initial render
setTimeout(updateCodePane, 200);
</script>
<!-- ════ MINI-GAME TEST POPUP ════ -->
<div id="mgTestOverlay" onclick="if(event.target===this)closeMGTest()">
<div id="mgTestBox">
<div id="mgTestHeader">
<span id="mgTestEmoji">🎮</span>
<div id="mgTestTitle">Mini-Game Test</div>
<button id="mgTestClose" onclick="closeMGTest()"></button>
</div>
<div id="mgTestBody">
<div id="mgTestDesc"></div>
<div id="mgTestWrap" style="width:100%;min-height:280px;position:relative;overflow:hidden;border-radius:10px;">
<canvas id="mgTestCanvas" width="400" height="280" style="display:none;margin:0 auto;border-radius:10px;border:1px solid #2e2b4a;"></canvas>
</div>
<div id="mgTestMsg"></div>
<div id="mgTestControls"></div>
</div>
</div>
</div>
</div><!-- /editorPane -->
<div id="resizerBar"></div>
<div id="codePane">
<div id="codeHeader">
<div id="codeHeaderLeft">
<span class="code-dot red"></span>
<span class="code-dot yellow"></span>
<span class="code-dot green"></span>
<span id="codeFilename">boardgame.py</span>
</div>
<div id="codeHeaderRight">
<span id="codeLang">🐍 Python</span>
<span id="codeLines">0 Zeilen</span>
</div>
</div>
<div id="codeScroll">
<div id="codeLineNums"></div>
<pre id="codeContent"></pre>
</div>
<div id="codeFooter">
<span id="codeStatus">● Bereit</span>
<span id="codeInfo">Live-Vorschau deines Spielcodes</span>
</div>
</div><!-- /codePane -->
</div><!-- /splitWrap -->
<!-- CDN Libraries: QR-Code + Kompression -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/pako/2.1.0/pako.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<!-- ═══ Module (inline) ═══ -->
<script>
/* ═══ _api.js ═══ */
/**
* minigames/_api.js
* Gemeinsame API und Hilfsfunktionen für alle Mini-Games
*
* Jedes Mini-Game muss folgendes exportieren (als globale Variable window.MG_<NAME>):
*
* window.MG_snake = {
* id: 'snake',
* emoji: '🐍',
* name: 'Snake',
* desc: 'Steuere die Schlange...',
* controls: 'Pfeiltasten oder WASD',
* multi: 1, // 1 = einmalig, 3 = max 3x, 99 = unbegrenzt
* launch: function(wrap, W, H, cfg) { ... return { stop() {} }; },
* preview: function(wrap, W, H, cfg) { ... return { stop() {} }; },
* };
*
* launch() → vollständiges Spiel, wird in game.html verwendet
* preview() → kompakte Demo, wird im Editor-Test-Popup verwendet
* Beide geben ein Objekt { stop() } zurück zum Aufräumen.
*
* cfg = { quizData, theme, rules, devName, gameName }
*/
window.MGAPI = (function() {
// ── Canvas-Setup-Helfer ──────────────────────────────────────────────────
function makeCanvas(wrap, W, H) {
const canvas = document.createElement('canvas');
canvas.width = W;
canvas.height = H;
canvas.style.display = 'block';
canvas.style.margin = '0 auto';
canvas.style.borderRadius = '12px';
canvas.style.background = '#0f0e17';
wrap.appendChild(canvas);
return { canvas, ctx: canvas.getContext('2d') };
}
// ── Ergebnis-Anzeige (wird von game.html überschrieben) ──────────────────
// game.html setzt window.MGAPI.onResult = finishMinigame
// editor.html setzt window.MGAPI.onResult = previewResult
function onResult(won) {
if (typeof window._mgOnResult === 'function') {
window._mgOnResult(won);
}
}
// ── Schrift-Helfer ───────────────────────────────────────────────────────
function text(ctx, str, x, y, opts = {}) {
ctx.save();
ctx.font = `${opts.weight || 'bold'} ${opts.size || 16}px ${opts.family || 'Nunito,sans-serif'}`;
ctx.fillStyle = opts.color || '#fff';
ctx.textAlign = opts.align || 'center';
ctx.textBaseline = opts.baseline || 'middle';
if (opts.shadow) {
ctx.shadowColor = opts.shadow;
ctx.shadowBlur = opts.shadowBlur || 10;
}
ctx.fillText(str, x, y);
ctx.restore();
}
// ── Runde Rechtecke ──────────────────────────────────────────────────────
function roundRect(ctx, x, y, w, h, r, fill, stroke) {
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.lineTo(x + w - r, y);
ctx.arcTo(x + w, y, x + w, y + r, r);
ctx.lineTo(x + w, y + h - r);
ctx.arcTo(x + w, y + h, x + w - r, y + h, r);
ctx.lineTo(x + r, y + h);
ctx.arcTo(x, y + h, x, y + h - r, r);
ctx.lineTo(x, y + r);
ctx.arcTo(x, y, x + r, y, r);
ctx.closePath();
if (fill) { ctx.fillStyle = fill; ctx.fill(); }
if (stroke) { ctx.strokeStyle = stroke; ctx.stroke(); }
}
// ── Game-Over / Win Screen ───────────────────────────────────────────────
function resultScreen(ctx, W, H, won, msg) {
ctx.fillStyle = won ? 'rgba(16,185,129,0.85)' : 'rgba(239,68,68,0.85)';
roundRect(ctx, W/2-120, H/2-50, 240, 100, 16, ctx.fillStyle, null);
text(ctx, won ? '🎉 Gewonnen!' : '💀 Verloren!', W/2, H/2-16,
{ size: 22, weight: 'bold', family: "'Fredoka One',cursive", color: '#fff' });
if (msg) text(ctx, msg, W/2, H/2+16, { size: 13, color: 'rgba(255,255,255,0.85)' });
}
// ── Öffentliche API ──────────────────────────────────────────────────────
return { makeCanvas, onResult, text, roundRect, resultScreen };
})();
/* ═══ snake.js ═══ */
/**
* minigames/snake.js
* 🐍 Snake — Steuere die Schlange, friss Äpfel ohne gegen die Wand zu fahren
*/
window.MG_snake = (function() {
const ID = 'snake';
const EMOJI = '🐍';
const NAME = 'Snake';
const DESC = 'Steuere die Schlange! Friss 3 Äpfel ohne gegen die Wand zu fahren.';
const CONTROLS = 'Pfeiltasten oder WASD';
const MULTI = 1; // einmalig pro Spiel
// ── Gemeinsame Spiel-Logik ────────────────────────────────────────────────
function run(wrap, W, H, cfg, onDone) {
const { canvas, ctx } = MGAPI.makeCanvas(wrap, W, H);
const SZ = 20;
const COLS = Math.floor(W / SZ);
const ROWS = Math.floor(H / SZ);
const WIN_SCORE = cfg.winScore || 3;
const theme = cfg.theme || { primary: '#10b981', glow: 'rgba(16,185,129,0.4)' };
function rndFood() {
return {
x: Math.floor(Math.random() * COLS),
y: Math.floor(Math.random() * ROWS),
};
}
let snake = [{ x: 5, y: 5 }, { x: 4, y: 5 }, { x: 3, y: 5 }];
let dir = { x: 1, y: 0 };
let nextDir = { x: 1, y: 0 };
let food = rndFood();
let score = 0;
let dead = false;
let stopped = false;
let raf, endTimer, last = 0;
// Steuerung
function onKey(e) {
const map = {
ArrowUp: { x: 0, y: -1 }, w: { x: 0, y: -1 },
ArrowDown: { x: 0, y: 1 }, s: { x: 0, y: 1 },
ArrowLeft: { x: -1, y: 0 }, a: { x: -1, y: 0 },
ArrowRight: { x: 1, y: 0 }, d: { x: 1, y: 0 },
};
const d = map[e.key];
if (d && (d.x !== -dir.x || d.y !== -dir.y)) {
e.preventDefault();
nextDir = d;
}
}
document.addEventListener('keydown', onKey);
// Touch-Steuerung (Swipe)
let touchStart = null;
canvas.addEventListener('touchstart', e => {
touchStart = { x: e.touches[0].clientX, y: e.touches[0].clientY };
}, { passive: true });
canvas.addEventListener('touchend', e => {
if (!touchStart) return;
const dx = e.changedTouches[0].clientX - touchStart.x;
const dy = e.changedTouches[0].clientY - touchStart.y;
if (Math.abs(dx) > Math.abs(dy)) {
nextDir = dx > 0 ? { x: 1, y: 0 } : { x: -1, y: 0 };
} else {
nextDir = dy > 0 ? { x: 0, y: 1 } : { x: 0, y: -1 };
}
}, { passive: true });
function drawGrid() {
ctx.strokeStyle = 'rgba(255,255,255,0.04)';
ctx.lineWidth = 0.5;
for (let x = 0; x < COLS; x++)
for (let y = 0; y < ROWS; y++)
ctx.strokeRect(x * SZ, y * SZ, SZ, SZ);
}
function loop(ts) {
if (stopped) return;
raf = requestAnimationFrame(loop);
if (ts - last < 140) return;
last = ts;
dir = nextDir;
if (!dead) {
const head = { x: snake[0].x + dir.x, y: snake[0].y + dir.y };
if (
head.x < 0 || head.x >= COLS ||
head.y < 0 || head.y >= ROWS ||
snake.some(s => s.x === head.x && s.y === head.y)
) {
dead = true;
if (!endTimer) endTimer = setTimeout(() => onDone(score >= WIN_SCORE), 1200);
} else {
snake.unshift(head);
if (head.x === food.x && head.y === food.y) {
score++;
food = rndFood();
if (score >= WIN_SCORE && !endTimer) {
endTimer = setTimeout(() => onDone(true), 1200);
}
} else {
snake.pop();
}
}
}
// Zeichnen
ctx.fillStyle = '#050508';
ctx.fillRect(0, 0, W, H);
drawGrid();
// Futter
ctx.shadowColor = theme.primary;
ctx.shadowBlur = 12;
ctx.font = `${SZ - 2}px serif`;
ctx.textAlign = 'center';
ctx.fillText('🍎', food.x * SZ + SZ / 2, food.y * SZ + SZ / 1.2);
ctx.shadowBlur = 0;
// Schlange
snake.forEach((s, i) => {
ctx.fillStyle = i === 0 ? theme.primary : `${theme.primary}88`;
if (i === 0) { ctx.shadowColor = theme.primary; ctx.shadowBlur = 8; }
MGAPI.roundRect(ctx, s.x * SZ + 2, s.y * SZ + 2, SZ - 4, SZ - 4, 4, ctx.fillStyle, null);
ctx.shadowBlur = 0;
});
// HUD
MGAPI.text(ctx, `🍎 ${score} / ${WIN_SCORE}`, 8, 14,
{ align: 'left', size: 13, color: theme.primary });
// Ergebnis-Screen
if (dead) {
MGAPI.resultScreen(ctx, W, H, score >= WIN_SCORE,
score >= WIN_SCORE ? `${score} Äpfel gefressen!` : `Nur ${score} Äpfel — nächstes Mal!`);
}
}
raf = requestAnimationFrame(loop);
return {
stop() {
stopped = true;
cancelAnimationFrame(raf);
clearTimeout(endTimer);
document.removeEventListener('keydown', onKey);
},
};
}
// ── Vollständiges Spiel (game.html) ──────────────────────────────────────
function launch(wrap, W, H, cfg) {
return run(wrap, W, H, cfg, won => MGAPI.onResult(won));
}
// ── Editor-Vorschau (Test-Popup) ─────────────────────────────────────────
function preview(wrap, W, H, cfg) {
return run(wrap, W, H, { ...cfg, winScore: 3 }, won => MGAPI.onResult(won));
}
return { id: ID, emoji: EMOJI, name: NAME, desc: DESC, controls: CONTROLS, multi: MULTI, launch, preview };
})();
/* ═══ flappy.js ═══ */
/**
* minigames/flappy.js
* 🐦 Flappy Bird — Klicke oder Leertaste, um durch die Röhren zu fliegen!
*/
window.MG_flappy = (function() {
const ID = 'flappy';
const EMOJI = '🐦';
const NAME = 'Flappy Bird';
const DESC = 'Klick oder Leertaste, um zu fliegen. 3 Hindernisse schaffen = Sieg!';
const CONTROLS = 'Klick / Leertaste';
const MULTI = 1;
function run(wrap, W, H, cfg, onDone) {
const { canvas, ctx } = MGAPI.makeCanvas(wrap, W, H);
const theme = cfg.theme || { primary: '#06b6d4' };
const WIN_PIPES = cfg.winPipes || 3;
const GRAV = 0.5, JUMP = -8, PW = 38, GAP = 85;
let bird = { y: H / 2, vy: 0 };
let pipes = [{ x: W, gap: Math.random() * (H - 100) + 30 }];
let score = 0;
let dead = false;
let started = false;
let stopped = false;
let raf, endTimer;
const jump = () => { if (!dead) { bird.vy = JUMP; started = true; } };
const onKey = e => { if (e.code === 'Space') { e.preventDefault(); jump(); } };
document.addEventListener('keydown', onKey);
canvas.addEventListener('click', jump);
// Touch
canvas.addEventListener('touchstart', e => { e.preventDefault(); jump(); }, { passive: false });
function loop() {
if (stopped) return;
raf = requestAnimationFrame(loop);
ctx.fillStyle = '#050508';
ctx.fillRect(0, 0, W, H);
// Hintergrund-Gradient
const grad = ctx.createLinearGradient(0, 0, 0, H);
grad.addColorStop(0, '#0a0a1a');
grad.addColorStop(1, '#050508');
ctx.fillStyle = grad;
ctx.fillRect(0, 0, W, H);
if (started && !dead) {
bird.vy += GRAV;
bird.y += bird.vy;
pipes.forEach(p => p.x -= 2.8);
if (pipes[pipes.length - 1].x < W - 170)
pipes.push({ x: W, gap: Math.random() * (H - 100) + 30 });
pipes = pipes.filter(p => p.x > -PW);
pipes.forEach(p => { if (p.x + PW < 50 && !p.passed) { p.passed = true; score++; } });
if (bird.y < 0 || bird.y + 20 > H) dead = true;
pipes.forEach(p => {
if (50 < p.x + PW && 70 > p.x && (bird.y < p.gap || bird.y + 20 > p.gap + GAP))
dead = true;
});
if (dead && !endTimer)
endTimer = setTimeout(() => onDone(score >= WIN_PIPES), 1000);
if (score >= WIN_PIPES && !dead && !endTimer)
endTimer = setTimeout(() => onDone(true), 400);
}
// Röhren zeichnen
pipes.forEach(p => {
// Röhren-Körper
MGAPI.roundRect(ctx, p.x, 0, PW, p.gap - 8, 4, `${theme.primary}cc`, null);
MGAPI.roundRect(ctx, p.x - 3, p.gap - 12, PW + 6, 12, 4, `${theme.primary}ee`, null);
MGAPI.roundRect(ctx, p.x, p.gap + GAP + 8, PW, H - p.gap - GAP - 8, 4, `${theme.primary}cc`, null);
MGAPI.roundRect(ctx, p.x - 3, p.gap + GAP, PW + 6, 12, 4, `${theme.primary}ee`, null);
});
// Vogel
ctx.shadowColor = dead ? '#ef4444' : theme.primary;
ctx.shadowBlur = 12;
ctx.fillStyle = dead ? '#ef4444' : theme.primary;
ctx.beginPath();
ctx.ellipse(50 + 14, bird.y + 10, 14, 10, bird.vy * 0.04, 0, Math.PI * 2);
ctx.fill();
// Auge
ctx.shadowBlur = 0;
ctx.fillStyle = '#fff';
ctx.beginPath();
ctx.arc(50 + 20, bird.y + 7, 4, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = '#000';
ctx.beginPath();
ctx.arc(50 + 21, bird.y + 7, 2, 0, Math.PI * 2);
ctx.fill();
// HUD
MGAPI.text(ctx, `🐦 ${score} / ${WIN_PIPES}`, 8, 14,
{ align: 'left', size: 13, color: theme.primary });
if (!started) {
MGAPI.text(ctx, 'Klicken oder Leertaste', W / 2, H / 2 + 40,
{ size: 13, color: 'rgba(255,255,255,0.7)' });
}
if (dead) {
MGAPI.resultScreen(ctx, W, H, score >= WIN_PIPES,
score >= WIN_PIPES ? `${score} Hindernisse geschafft!` : `Nur ${score} — flieg weiter!`);
}
}
raf = requestAnimationFrame(loop);
return {
stop() {
stopped = true;
cancelAnimationFrame(raf);
clearTimeout(endTimer);
document.removeEventListener('keydown', onKey);
canvas.removeEventListener('click', jump);
},
};
}
function launch(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
function preview(wrap, W, H, cfg) { return run(wrap, W, H, { ...cfg, winPipes: 3 }, won => MGAPI.onResult(won)); }
return { id: ID, emoji: EMOJI, name: NAME, desc: DESC, controls: CONTROLS, multi: MULTI, launch, preview };
})();
/* ═══ memory.js ═══ */
/**
* minigames/memory.js
* 🃏 Memory — Finde alle Paare, so schnell wie möglich!
*/
window.MG_memory = (function() {
const ID = 'memory';
const EMOJI = '🃏';
const NAME = 'Memory';
const DESC = 'Finde alle Paare — so schnell wie möglich!';
const CONTROLS = 'Mausklick / Tippen';
const MULTI = 1;
function run(wrap, W, H, cfg, onDone) {
const { canvas, ctx } = MGAPI.makeCanvas(wrap, W, H);
const theme = cfg.theme || { primary: '#8b5cf6' };
const EMOJIS = cfg.emojis || ['🐱','🐶','🦊','🐸','🦋','🐠'];
const all = [...EMOJIS, ...EMOJIS].sort(() => Math.random() - 0.5);
let cards = all.map((e, i) => ({ e, i, open: false }));
let flipped = [], matched = [], checking = false, moves = 0;
let stopped = false, raf, startTime = null, elapsed = 0;
// Layout: 4×3
const COLS = 4, ROWS = Math.ceil(all.length / 4);
const PAD = 8;
const cw = Math.floor((W - PAD * (COLS + 1)) / COLS);
const ch = Math.floor((H - PAD * (ROWS + 2) - 24) / ROWS);
const ox = (W - COLS * cw - PAD * (COLS - 1)) / 2;
const oy = 30;
function cardAt(mx, my) {
for (let ri = 0; ri < ROWS; ri++) {
for (let ci = 0; ci < COLS; ci++) {
const idx = ri * COLS + ci;
if (idx >= cards.length) continue;
const x = ox + ci * (cw + PAD);
const y = oy + ri * (ch + PAD);
if (mx >= x && mx < x + cw && my >= y && my < y + ch) return cards[idx];
}
}
return null;
}
function onClick(e) {
if (checking) return;
const rect = canvas.getBoundingClientRect();
const scaleX = canvas.width / rect.width;
const scaleY = canvas.height / rect.height;
const mx = (e.clientX - rect.left) * scaleX;
const my = (e.clientY - rect.top) * scaleY;
const card = cardAt(mx, my);
if (!card || card.open || matched.includes(card.i)) return;
if (!startTime) startTime = performance.now();
card.open = true;
flipped.push(card);
if (flipped.length === 2) {
moves++;
checking = true;
setTimeout(() => {
if (flipped[0].e === flipped[1].e) {
matched.push(flipped[0].i, flipped[1].i);
if (matched.length === cards.length) {
setTimeout(() => onDone(true), 600);
}
} else {
flipped.forEach(c => c.open = false);
}
flipped = [];
checking = false;
}, 700);
}
}
canvas.addEventListener('click', onClick);
// Karten-Flip-Animation (progress 01)
const flipAnim = new Map(); // card.i → { prog, dir }
function loop(ts) {
if (stopped) return;
raf = requestAnimationFrame(loop);
if (startTime) elapsed = (performance.now() - startTime) / 1000;
ctx.fillStyle = '#050508';
ctx.fillRect(0, 0, W, H);
// HUD
MGAPI.text(ctx, `🃏 ${matched.length / 2} / ${EMOJIS.length} | Züge: ${moves}`, W / 2, 16,
{ size: 12, color: theme.primary });
// Karten zeichnen
for (let ri = 0; ri < ROWS; ri++) {
for (let ci = 0; ci < COLS; ci++) {
const idx = ri * COLS + ci;
if (idx >= cards.length) continue;
const card = cards[idx];
const x = ox + ci * (cw + PAD);
const y = oy + ri * (ch + PAD);
const isM = matched.includes(card.i);
const isOpen = card.open || isM;
if (isM) {
MGAPI.roundRect(ctx, x, y, cw, ch, 8,
'rgba(16,185,129,0.15)', '#10b981');
} else if (isOpen) {
MGAPI.roundRect(ctx, x, y, cw, ch, 8,
`${theme.primary}22`, theme.primary);
} else {
MGAPI.roundRect(ctx, x, y, cw, ch, 8,
'rgba(255,255,255,0.04)', 'rgba(255,255,255,0.1)');
}
if (isOpen) {
ctx.font = `${Math.min(cw, ch) * 0.55}px serif`;
ctx.textAlign = 'center';
ctx.fillText(card.e, x + cw / 2, y + ch / 2 + ch * 0.15);
} else {
MGAPI.text(ctx, '?', x + cw / 2, y + ch / 2,
{ size: Math.floor(ch * 0.35), color: 'rgba(255,255,255,0.2)' });
}
}
}
}
raf = requestAnimationFrame(loop);
return {
stop() {
stopped = true;
cancelAnimationFrame(raf);
canvas.removeEventListener('click', onClick);
},
};
}
function launch(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
function preview(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
return { id: ID, emoji: EMOJI, name: NAME, desc: DESC, controls: CONTROLS, multi: MULTI, launch, preview };
})();
/* ═══ quiz.js ═══ */
/**
* minigames/quiz.js
* ❓ Quiz — Beantworte die Frage richtig!
*/
window.MG_quiz = (function() {
const ID = 'quiz';
const EMOJI = '❓';
const NAME = 'Quiz';
const DESC = 'Beantworte die Frage richtig!';
const CONTROLS = 'Mausklick / Tippen';
const MULTI = 99; // unbegrenzt, je Quiz-Feld eine Frage
function run(wrap, W, H, cfg, onDone) {
const theme = cfg.theme || { primary: '#f59e0b' };
const quizData = cfg.quizData || [];
const fieldIdx = cfg.fieldIndex ?? null;
// Passende Frage suchen
let q = null;
if (fieldIdx !== null) q = quizData.find(d => d.fieldIndex === fieldIdx);
if (!q && quizData.length > 0) q = quizData[Math.floor(Math.random() * quizData.length)];
// Fallback wenn keine Frage hinterlegt
if (!q || !q.question) {
wrap.innerHTML = `
<div style="text-align:center;padding:40px 20px;font-family:'Nunito',sans-serif">
<div style="font-size:3rem;margin-bottom:12px">❓</div>
<div style="color:#a7a3c2;font-size:14px;margin-bottom:20px">Keine Quiz-Frage für dieses Feld hinterlegt.</div>
<button onclick="MGAPI.onResult(true)"
style="background:linear-gradient(135deg,#7c3aed,#f5a623);color:#fff;font-family:'Fredoka One',cursive;
font-size:1rem;border:none;border-radius:10px;padding:12px 28px;cursor:pointer">
✅ Trotzdem bestanden!
</button>
</div>`;
return { stop() {} };
}
// HTML-Quiz (kein Canvas — besser lesbar)
const answers = q.answers || [];
const correct = q.correct ?? 0;
const COLORS = ['#7c3aed','#2563eb','#059669','#d97706'];
const LABELS = ['A','B','C','D'];
const container = document.createElement('div');
container.style.cssText = `
display:flex;flex-direction:column;gap:10px;padding:16px;
font-family:'Nunito',sans-serif;width:100%;box-sizing:border-box;
`;
// Frage
const qEl = document.createElement('div');
qEl.style.cssText = `
background:rgba(255,255,255,0.05);border-radius:12px;padding:16px;
color:#fff;font-size:15px;font-weight:700;line-height:1.5;text-align:center;
`;
qEl.textContent = q.question;
container.appendChild(qEl);
// Antworten
let answered = false;
answers.forEach((a, i) => {
if (!a) return;
const btn = document.createElement('button');
btn.style.cssText = `
background:${COLORS[i] || '#333'}22;border:2px solid ${COLORS[i] || '#333'}88;
color:#fff;border-radius:10px;padding:12px 16px;cursor:pointer;
font-family:'Nunito',sans-serif;font-size:13px;font-weight:700;
text-align:left;transition:all 0.2s;display:flex;gap:10px;align-items:center;
`;
btn.innerHTML = `<span style="background:${COLORS[i]};border-radius:6px;padding:2px 8px;font-size:12px">${LABELS[i]}</span> ${a}`;
btn.addEventListener('click', () => {
if (answered) return;
answered = true;
const won = (i === correct);
// Feedback-Farben
answers.forEach((_, j) => {
const b = container.querySelectorAll('button')[j];
if (!b) return;
if (j === correct) {
b.style.background = 'rgba(16,185,129,0.3)';
b.style.borderColor = '#10b981';
} else if (j === i && !won) {
b.style.background = 'rgba(239,68,68,0.3)';
b.style.borderColor = '#ef4444';
}
b.style.cursor = 'default';
});
// Ergebnis-Text
const result = document.createElement('div');
result.style.cssText = `
text-align:center;font-family:'Fredoka One',cursive;font-size:1.2rem;
padding:10px;color:${won ? '#10b981' : '#ef4444'};
`;
result.textContent = won ? '🎉 Richtig!' : `❌ Falsch! Richtig wäre: ${answers[correct]}`;
container.appendChild(result);
setTimeout(() => onDone(won), 1400);
});
container.appendChild(btn);
});
wrap.appendChild(container);
return { stop() { wrap.innerHTML = ''; } };
}
function launch(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
function preview(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
return { id: ID, emoji: EMOJI, name: NAME, desc: DESC, controls: CONTROLS, multi: MULTI, launch, preview };
})();
/* ═══ reaction.js ═══ */
/**
* minigames/reaction.js
* ⚡ Reaktionstest — Drück den Knopf so schnell wie möglich!
*/
window.MG_reaction = (function() {
const ID = 'reaction';
const EMOJI = '⚡';
const NAME = 'Reaktionstest';
const DESC = 'Wenn der Kreis GRÜN wird — so schnell wie möglich klicken!';
const CONTROLS = 'Klick / Leertaste';
const MULTI = 3;
function run(wrap, W, H, cfg, onDone) {
const { canvas, ctx } = MGAPI.makeCanvas(wrap, W, H);
const theme = cfg.theme || { primary: '#ef4444' };
const ROUNDS = 3;
const WIN_MS = 600;
let phase = 'wait';
let waitEnd = 0;
let reStart = 0;
let times = [];
let best = Infinity;
let stopped = false;
let raf, endTimer;
function nextWait() {
phase = 'wait';
waitEnd = performance.now() + (2 + Math.random() * 3) * 1000;
}
nextWait();
const react = () => {
if (phase === 'ready') {
const t = performance.now() - reStart;
times.push(t);
best = Math.min(best, t);
if (times.length >= ROUNDS) {
clearTimeout(endTimer);
endTimer = setTimeout(() => onDone(best < WIN_MS), 800);
phase = 'done';
} else {
nextWait();
}
} else if (phase === 'wait') {
phase = 'toosoon';
setTimeout(nextWait, 1000);
}
};
const onKey = e => { if (e.code === 'Space') { e.preventDefault(); react(); } };
document.addEventListener('keydown', onKey);
canvas.addEventListener('click', react);
function loop(ts) {
if (stopped) return;
raf = requestAnimationFrame(loop);
if (phase === 'wait' && ts > waitEnd) {
phase = 'ready';
reStart = performance.now();
}
// Hintergrund
const bg = phase === 'ready' ? '#14532d'
: phase === 'toosoon' ? '#7f1d1d'
: phase === 'done' ? '#0f0e17'
: '#050508';
ctx.fillStyle = bg;
ctx.fillRect(0, 0, W, H);
const cx = W / 2, cy = H / 2;
if (phase === 'wait') {
// Pulsierender Kreis (rot = warten)
const pulse = 0.85 + 0.15 * Math.sin(ts * 0.003);
ctx.beginPath();
ctx.arc(cx, cy, 60 * pulse, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(239,68,68,0.2)';
ctx.fill();
ctx.strokeStyle = '#ef444488';
ctx.lineWidth = 3;
ctx.stroke();
MGAPI.text(ctx, '⏳', cx, cy - 6, { size: 36 });
MGAPI.text(ctx, 'Warte...', cx, cy + 44, { size: 14, color: '#a7a3c2' });
MGAPI.text(ctx, `${times.length} / ${ROUNDS} Runden`, cx, H - 20, { size: 12, color: '#64748b' });
}
if (phase === 'ready') {
// Leuchtender grüner Kreis
ctx.shadowColor = '#22c55e';
ctx.shadowBlur = 40;
ctx.beginPath();
ctx.arc(cx, cy, 65, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(22,163,74,0.4)';
ctx.fill();
ctx.strokeStyle = '#22c55e';
ctx.lineWidth = 4;
ctx.stroke();
ctx.shadowBlur = 0;
MGAPI.text(ctx, '⚡', cx, cy - 8, { size: 44 });
MGAPI.text(ctx, 'JETZT!', cx, cy + 48,
{ size: 22, family: "'Fredoka One',cursive", color: '#fff', shadow: '#22c55e', shadowBlur: 15 });
MGAPI.text(ctx, 'Klick oder Leertaste!', cx, cy + 78, { size: 13, color: 'rgba(255,255,255,0.6)' });
}
if (phase === 'toosoon') {
MGAPI.text(ctx, '😅', cx, cy - 10, { size: 48 });
MGAPI.text(ctx, 'Zu früh!', cx, cy + 46,
{ size: 22, family: "'Fredoka One',cursive", color: '#fca5a5' });
}
if (phase === 'done') {
MGAPI.resultScreen(ctx, W, H, best < WIN_MS,
best < WIN_MS ? `${Math.round(best)} ms — super schnell!` : `${Math.round(best)} ms — noch etwas langsam`);
}
// Statistik
if (times.length > 0 && phase !== 'done') {
const last = times[times.length - 1];
MGAPI.text(ctx, `Letzte: ${Math.round(last)} ms | Beste: ${Math.round(best)} ms`,
cx, H - 14, { size: 11, color: 'rgba(255,255,255,0.4)' });
}
}
raf = requestAnimationFrame(loop);
return {
stop() {
stopped = true;
cancelAnimationFrame(raf);
clearTimeout(endTimer);
document.removeEventListener('keydown', onKey);
canvas.removeEventListener('click', react);
},
};
}
function launch(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
function preview(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
return { id: ID, emoji: EMOJI, name: NAME, desc: DESC, controls: CONTROLS, multi: MULTI, launch, preview };
})();
/* ═══ basketball.js ═══ */
/**
* minigames/basketball.js
* 🏀 Basketball — Wirf den Ball zum richtigen Zeitpunkt!
*/
window.MG_basketball = (function() {
const ID = 'basketball';
const EMOJI = '🏀';
const NAME = 'Basketball';
const DESC = 'Drücke zum richtigen Zeitpunkt, um den Ball zu werfen!';
const CONTROLS = 'Klick / Leertaste';
const MULTI = 3;
function run(wrap, W, H, cfg, onDone) {
const { canvas, ctx } = MGAPI.makeCanvas(wrap, W, H);
const theme = cfg.theme || { primary: '#f97316' };
const WIN_BASKETS = cfg.winBaskets || 2;
// Korb-Position
const HOOP_X = W * 0.72;
const HOOP_Y = H * 0.28;
const HOOP_W = 54;
const BALL_R = 18;
const BALL_START = { x: W * 0.18, y: H * 0.72 };
let ballX = BALL_START.x;
let ballY = BALL_START.y;
let vx = 0, vy = 0;
let flying = false;
let score = 0;
let misses = 0;
let stopped = false;
let raf, endTimer;
let result = null; // 'win' | 'lose' | null
// Powerbar (zeigt an wie weit der Balken)
let power = 0;
let powerDir = 1;
let powerMax = 100;
function shoot() {
if (flying || result) return;
// Wurfkraft aus power (0100), Winkel Richtung Korb
const dx = HOOP_X - BALL_START.x;
const dy = HOOP_Y - BALL_START.y - 20;
const speed = 4 + power * 0.09;
const angle = Math.atan2(dy, dx) - 0.18 - (power - 50) * 0.005;
vx = Math.cos(angle) * speed;
vy = Math.sin(angle) * speed;
flying = true;
ballX = BALL_START.x;
ballY = BALL_START.y;
}
const onAction = e => {
if (e.type === 'keydown' && e.code !== 'Space') return;
if (e.type === 'keydown') e.preventDefault();
shoot();
};
document.addEventListener('keydown', onAction);
canvas.addEventListener('click', onAction);
canvas.addEventListener('touchstart', e => { e.preventDefault(); shoot(); }, { passive: false });
function reset() {
flying = false;
ballX = BALL_START.x;
ballY = BALL_START.y;
}
function drawHoop() {
// Brett
ctx.fillStyle = '#e5e7eb';
ctx.fillRect(HOOP_X + HOOP_W * 0.4, HOOP_Y - 50, 8, 50);
// Korb-Ring
ctx.strokeStyle = '#ef4444';
ctx.lineWidth = 5;
ctx.beginPath();
ctx.ellipse(HOOP_X + HOOP_W / 2, HOOP_Y, HOOP_W / 2, 8, 0, 0, Math.PI * 2);
ctx.stroke();
// Netz (einfach als Linien)
ctx.strokeStyle = 'rgba(255,255,255,0.5)';
ctx.lineWidth = 1.5;
for (let i = 0; i <= 4; i++) {
const nx = HOOP_X + (HOOP_W / 4) * i;
ctx.beginPath();
ctx.moveTo(nx, HOOP_Y + 8);
ctx.lineTo(HOOP_X + HOOP_W / 2 + (i - 2) * 3, HOOP_Y + 36);
ctx.stroke();
}
}
function drawPower() {
if (flying || result) return;
const bx = 12, by = H - 28, bw = W * 0.45, bh = 14;
MGAPI.roundRect(ctx, bx, by, bw, bh, 6, 'rgba(255,255,255,0.1)', 'rgba(255,255,255,0.2)');
const fill = Math.max(0, Math.min(1, power / powerMax));
const color = fill < 0.4 ? '#22c55e' : fill < 0.7 ? '#f59e0b' : '#ef4444';
MGAPI.roundRect(ctx, bx + 2, by + 2, (bw - 4) * fill, bh - 4, 4, color, null);
MGAPI.text(ctx, 'Kraft', bx + bw / 2, by + bh / 2, { size: 10, color: '#fff' });
}
function loop(ts) {
if (stopped) return;
raf = requestAnimationFrame(loop);
ctx.fillStyle = '#050508';
ctx.fillRect(0, 0, W, H);
// Boden
MGAPI.roundRect(ctx, 0, H - 10, W, 10, 0, '#1e293b', null);
drawHoop();
if (!flying && !result) {
// Power-Bar animieren
power += powerDir * 1.8;
if (power >= powerMax) powerDir = -1;
if (power <= 0) powerDir = 1;
}
if (flying) {
vy += 0.38; // Schwerkraft
ballX += vx;
ballY += vy;
// Korb-Treffer prüfen
const inHoopX = ballX > HOOP_X && ballX < HOOP_X + HOOP_W;
const inHoopY = Math.abs(ballY - HOOP_Y) < 18;
if (inHoopX && inHoopY && vy > 0) {
score++;
if (score >= WIN_BASKETS && !endTimer)
endTimer = setTimeout(() => { result = 'win'; setTimeout(() => onDone(true), 900); }, 300);
reset();
}
// Boden oder aus dem Bild
if (ballY > H + 20 || ballX > W + 20 || ballX < -20) {
misses++;
if (misses >= 4 && score < WIN_BASKETS && !endTimer)
endTimer = setTimeout(() => { result = 'lose'; setTimeout(() => onDone(false), 900); }, 300);
reset();
}
}
// Ball
ctx.shadowColor = theme.primary;
ctx.shadowBlur = 15;
ctx.fillStyle = theme.primary;
ctx.beginPath();
ctx.arc(ballX, ballY, BALL_R, 0, Math.PI * 2);
ctx.fill();
// Linien auf Ball
ctx.shadowBlur = 0;
ctx.strokeStyle = 'rgba(0,0,0,0.35)';
ctx.lineWidth = 2;
ctx.beginPath(); ctx.arc(ballX, ballY, BALL_R, 0, Math.PI * 2); ctx.stroke();
ctx.beginPath(); ctx.moveTo(ballX - BALL_R, ballY); ctx.lineTo(ballX + BALL_R, ballY); ctx.stroke();
drawPower();
// HUD
MGAPI.text(ctx, `🏀 ${score} / ${WIN_BASKETS}`, W / 2, 18, { size: 14, color: theme.primary });
if (!flying && !result)
MGAPI.text(ctx, 'Klick oder Leertaste zum Werfen', W / 2, H - 48, { size: 11, color: 'rgba(255,255,255,0.45)' });
if (result)
MGAPI.resultScreen(ctx, W, H, result === 'win',
result === 'win' ? `${score} Körbe getroffen!` : `Nur ${score} — weiter üben!`);
}
raf = requestAnimationFrame(loop);
return {
stop() {
stopped = true;
cancelAnimationFrame(raf);
clearTimeout(endTimer);
document.removeEventListener('keydown', onAction);
canvas.removeEventListener('click', onAction);
},
};
}
function launch(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
function preview(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
return { id: ID, emoji: EMOJI, name: NAME, desc: DESC, controls: CONTROLS, multi: MULTI, launch, preview };
})();
/* ═══ catch.js ═══ */
/**
* minigames/catch.js
* 🍎 Äpfel fangen — Bewege den Korb und fange fallende Früchte!
*/
window.MG_catch = (function() {
const ID = 'catch';
const EMOJI = '🍎';
const NAME = 'Äpfel fangen';
const DESC = 'Bewege den Korb mit ← → oder der Maus und fange 5 Äpfel!';
const CONTROLS = '← → / A D / Maus';
const MULTI = 3;
function run(wrap, W, H, cfg, onDone) {
const { canvas, ctx } = MGAPI.makeCanvas(wrap, W, H);
const theme = cfg.theme || { primary: '#22c55e' };
const WIN = cfg.winCatch || 5;
const FRUITS = ['🍎','🍊','🍋','🍇','🍓','🍑'];
const BASKET_W = 70, BASKET_H = 24;
let basket = { x: W / 2 - BASKET_W / 2, speed: 0 };
let items = [];
let score = 0;
let missed = 0;
let frame = 0;
let stopped = false;
let raf, endTimer, result = null;
const keys = {};
let mouseX = null;
const onKey = e => { keys[e.code] = e.type === 'keydown'; };
const onMouse = e => {
const rect = canvas.getBoundingClientRect();
mouseX = (e.clientX - rect.left) * (canvas.width / rect.width) - BASKET_W / 2;
};
const onTouch = e => {
e.preventDefault();
const rect = canvas.getBoundingClientRect();
mouseX = (e.touches[0].clientX - rect.left) * (canvas.width / rect.width) - BASKET_W / 2;
};
document.addEventListener('keydown', onKey);
document.addEventListener('keyup', onKey);
canvas.addEventListener('mousemove', onMouse);
canvas.addEventListener('touchmove', onTouch, { passive: false });
function spawnItem() {
items.push({
x: Math.random() * (W - 40) + 20,
y: -30,
vy: 1.8 + Math.random() * 1.4 + score * 0.08,
emoji: FRUITS[Math.floor(Math.random() * FRUITS.length)],
size: 26 + Math.random() * 10,
});
}
function loop() {
if (stopped) return;
raf = requestAnimationFrame(loop);
frame++;
// Basket bewegen
if (mouseX !== null) {
basket.x += (mouseX - basket.x) * 0.18;
} else {
if (keys['ArrowLeft'] || keys['KeyA']) basket.x -= 5.5;
if (keys['ArrowRight'] || keys['KeyD']) basket.x += 5.5;
}
basket.x = Math.max(0, Math.min(W - BASKET_W, basket.x));
// Früchte spawnen
const spawnRate = Math.max(30, 70 - score * 3);
if (frame % spawnRate === 0 && !result) spawnItem();
// Update
items.forEach(it => { it.y += it.vy; });
// Fangen / Vermissen
items = items.filter(it => {
const basketTop = H - 50 - BASKET_H;
if (it.y + it.size / 2 > basketTop &&
it.x > basket.x && it.x < basket.x + BASKET_W) {
score++;
if (score >= WIN && !endTimer)
endTimer = setTimeout(() => { result = 'win'; setTimeout(() => onDone(true), 900); }, 200);
return false;
}
if (it.y > H + 20) {
missed++;
if (missed >= 4 && score < WIN && !endTimer)
endTimer = setTimeout(() => { result = 'lose'; setTimeout(() => onDone(false), 900); }, 200);
return false;
}
return true;
});
// ── Zeichnen ──
ctx.fillStyle = '#050508';
ctx.fillRect(0, 0, W, H);
// Boden-Linie
ctx.strokeStyle = 'rgba(255,255,255,0.08)';
ctx.lineWidth = 1;
ctx.beginPath(); ctx.moveTo(0, H - 50); ctx.lineTo(W, H - 50); ctx.stroke();
// Früchte
ctx.font = '28px serif';
ctx.textAlign = 'center';
items.forEach(it => ctx.fillText(it.emoji, it.x, it.y + it.size));
// Korb
const bx = basket.x, by = H - 50 - BASKET_H;
MGAPI.roundRect(ctx, bx, by, BASKET_W, BASKET_H, 6, `${theme.primary}33`, theme.primary);
ctx.lineWidth = 2.5;
// Korb-Linien
for (let i = 1; i < 4; i++) {
ctx.strokeStyle = `${theme.primary}66`;
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(bx + (BASKET_W / 4) * i, by);
ctx.lineTo(bx + (BASKET_W / 4) * i, by + BASKET_H);
ctx.stroke();
}
ctx.font = '22px serif';
ctx.fillText('🧺', bx + BASKET_W / 2, by + BASKET_H + 20);
// HUD
MGAPI.text(ctx, `🍎 ${score} / ${WIN} 💔 ${missed} / 4`, W / 2, 18, { size: 13, color: theme.primary });
if (!result)
MGAPI.text(ctx, '← → oder Maus bewegen', W / 2, H - 10, { size: 10, color: 'rgba(255,255,255,0.3)' });
if (result)
MGAPI.resultScreen(ctx, W, H, result === 'win',
result === 'win' ? `${score} Früchte gefangen!` : `${missed} verpasst — nächstes Mal!`);
}
raf = requestAnimationFrame(loop);
return {
stop() {
stopped = true;
cancelAnimationFrame(raf);
clearTimeout(endTimer);
document.removeEventListener('keydown', onKey);
document.removeEventListener('keyup', onKey);
canvas.removeEventListener('mousemove', onMouse);
canvas.removeEventListener('touchmove', onTouch);
},
};
}
function launch(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
function preview(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
return { id: ID, emoji: EMOJI, name: NAME, desc: DESC, controls: CONTROLS, multi: MULTI, launch, preview };
})();
/* ═══ maze.js ═══ */
/**
* minigames/maze.js
* 🌀 Labyrinth — Finde den Ausgang!
*/
window.MG_maze = (function() {
const ID = 'maze';
const EMOJI = '🌀';
const NAME = 'Labyrinth';
const DESC = 'Steuere mit den Pfeiltasten durch das Labyrinth zum Ausgang!';
const CONTROLS = 'Pfeiltasten / WASD';
const MULTI = 3;
// ── Maze-Generator (Recursive Backtracker) ────────────────────────────────
function generateMaze(COLS, ROWS) {
const cells = Array.from({ length: ROWS }, () =>
Array.from({ length: COLS }, () => ({ n: true, s: true, e: true, w: true, visited: false }))
);
const stack = [];
let cur = { c: 0, r: 0 };
cells[0][0].visited = true;
stack.push(cur);
while (stack.length) {
const { c, r } = stack[stack.length - 1];
const neighbors = [];
if (r > 0 && !cells[r-1][c].visited) neighbors.push({ c, r: r-1, dir: 'n' });
if (r < ROWS-1 && !cells[r+1][c].visited) neighbors.push({ c, r: r+1, dir: 's' });
if (c < COLS-1 && !cells[r][c+1].visited) neighbors.push({ c: c+1, r, dir: 'e' });
if (c > 0 && !cells[r][c-1].visited) neighbors.push({ c: c-1, r, dir: 'w' });
if (!neighbors.length) { stack.pop(); continue; }
const next = neighbors[Math.floor(Math.random() * neighbors.length)];
cells[r][c][next.dir] = false;
const opp = { n:'s', s:'n', e:'w', w:'e' }[next.dir];
cells[next.r][next.c][opp] = false;
cells[next.r][next.c].visited = true;
stack.push({ c: next.c, r: next.r });
}
return cells;
}
function run(wrap, W, H, cfg, onDone) {
const { canvas, ctx } = MGAPI.makeCanvas(wrap, W, H);
const theme = cfg.theme || { primary: '#6366f1' };
const COLS = 9, ROWS = 7;
const cellW = Math.floor((W - 16) / COLS);
const cellH = Math.floor((H - 40) / ROWS);
const OX = (W - COLS * cellW) / 2;
const OY = 32;
const WALL = 2;
const maze = generateMaze(COLS, ROWS);
let px = 0, py = 0;
let stopped = false;
let raf, endTimer, won = false;
let moveTimer = null;
function tryMove(dc, dr) {
const cell = maze[py][px];
const dir = dc === 1 ? 'e' : dc === -1 ? 'w' : dr === 1 ? 's' : 'n';
if (cell[dir]) return; // Wand
px += dc; py += dr;
if (px === COLS - 1 && py === ROWS - 1 && !endTimer) {
won = true;
endTimer = setTimeout(() => onDone(true), 900);
}
}
const held = {};
const onKey = e => {
const map = {
ArrowUp: [0,-1], ArrowDown: [0,1], ArrowLeft: [-1,0], ArrowRight: [1,0],
w: [0,-1], s: [0,1], a: [-1,0], d: [1,0],
};
const d = map[e.key];
if (!d) return;
e.preventDefault();
if (e.type === 'keydown') {
if (!held[e.key]) tryMove(d[0], d[1]);
held[e.key] = true;
} else {
held[e.key] = false;
}
};
// Touch-Swipe
let touchStart = null;
canvas.addEventListener('touchstart', e => {
touchStart = { x: e.touches[0].clientX, y: e.touches[0].clientY };
}, { passive: true });
canvas.addEventListener('touchend', e => {
if (!touchStart) return;
const dx = e.changedTouches[0].clientX - touchStart.x;
const dy = e.changedTouches[0].clientY - touchStart.y;
if (Math.abs(dx) > Math.abs(dy)) {
tryMove(dx > 0 ? 1 : -1, 0);
} else {
tryMove(0, dy > 0 ? 1 : -1);
}
}, { passive: true });
document.addEventListener('keydown', onKey);
document.addEventListener('keyup', onKey);
function drawMaze() {
for (let r = 0; r < ROWS; r++) {
for (let c = 0; c < COLS; c++) {
const x = OX + c * cellW;
const y = OY + r * cellH;
const cell = maze[r][c];
ctx.strokeStyle = `${theme.primary}88`;
ctx.lineWidth = WALL;
if (cell.n && r === 0) { ctx.beginPath(); ctx.moveTo(x,y); ctx.lineTo(x+cellW,y); ctx.stroke(); }
if (cell.w && c === 0) { ctx.beginPath(); ctx.moveTo(x,y); ctx.lineTo(x,y+cellH); ctx.stroke(); }
if (cell.s) { ctx.beginPath(); ctx.moveTo(x,y+cellH); ctx.lineTo(x+cellW,y+cellH); ctx.stroke(); }
if (cell.e) { ctx.beginPath(); ctx.moveTo(x+cellW,y); ctx.lineTo(x+cellW,y+cellH); ctx.stroke(); }
}
}
}
function loop() {
if (stopped) return;
raf = requestAnimationFrame(loop);
ctx.fillStyle = '#050508';
ctx.fillRect(0, 0, W, H);
// Start & Ziel markieren
MGAPI.roundRect(ctx, OX, OY, cellW, cellH, 4, 'rgba(16,185,129,0.2)', null);
MGAPI.roundRect(ctx,
OX + (COLS-1) * cellW, OY + (ROWS-1) * cellH,
cellW, cellH, 4, 'rgba(245,166,35,0.25)', null);
drawMaze();
// Start/Ziel-Label
ctx.font = '14px serif'; ctx.textAlign = 'center';
ctx.fillText('🟢', OX + cellW/2, OY + cellH/2 + 6);
ctx.fillText('🏁', OX + (COLS-0.5)*cellW, OY + (ROWS-0.5)*cellH + 6);
// Spieler
const plX = OX + px * cellW + cellW / 2;
const plY = OY + py * cellH + cellH / 2;
ctx.shadowColor = theme.primary;
ctx.shadowBlur = 14;
ctx.fillStyle = theme.primary;
ctx.beginPath();
ctx.arc(plX, plY, Math.min(cellW, cellH) * 0.32, 0, Math.PI * 2);
ctx.fill();
ctx.shadowBlur = 0;
// HUD
MGAPI.text(ctx, `🌀 Finde den Ausgang!`, W / 2, 16, { size: 12, color: theme.primary });
MGAPI.text(ctx, '← ↑ → ↓', W / 2, H - 10, { size: 10, color: 'rgba(255,255,255,0.3)' });
if (won)
MGAPI.resultScreen(ctx, W, H, true, 'Ausgang gefunden!');
}
raf = requestAnimationFrame(loop);
return {
stop() {
stopped = true;
cancelAnimationFrame(raf);
clearTimeout(endTimer);
document.removeEventListener('keydown', onKey);
document.removeEventListener('keyup', onKey);
},
};
}
function launch(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
function preview(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
return { id: ID, emoji: EMOJI, name: NAME, desc: DESC, controls: CONTROLS, multi: MULTI, launch, preview };
})();
/* ═══ simon.js ═══ */
/**
* minigames/simon.js
* 🔴 Simon Says — Merke und wiederhole die Farb-Sequenz!
*/
window.MG_simon = (function() {
const ID = 'simon';
const EMOJI = '🔴';
const NAME = 'Simon Says';
const DESC = 'Merke die Farb-Reihenfolge und tippe sie nach!';
const CONTROLS = 'Mausklick / Tippen';
const MULTI = 3;
const COLORS = [
{ id: 0, fill: '#22c55e', glow: 'rgba(34,197,94,0.6)', label: '🟢' },
{ id: 1, fill: '#ef4444', glow: 'rgba(239,68,68,0.6)', label: '🔴' },
{ id: 2, fill: '#3b82f6', glow: 'rgba(59,130,246,0.6)', label: '🔵' },
{ id: 3, fill: '#f59e0b', glow: 'rgba(245,158,11,0.6)', label: '🟡' },
];
function run(wrap, W, H, cfg, onDone) {
const { canvas, ctx } = MGAPI.makeCanvas(wrap, W, H);
const WIN_ROUNDS = cfg.winRounds || 4;
// Layout: 2×2 Grid
const PAD = 16;
const GW = (W - PAD * 3) / 2;
const GH = (H - PAD * 3 - 32) / 2;
const POS = [
{ x: PAD, y: 32 + PAD },
{ x: PAD*2+GW, y: 32 + PAD },
{ x: PAD, y: 32 + PAD*2 + GH },
{ x: PAD*2+GW, y: 32 + PAD*2 + GH },
];
let sequence = [];
let userSeq = [];
let showIdx = -1; // welcher Schritt der Anzeige läuft
let phase = 'show'; // 'show' | 'input' | 'result'
let litIdx = -1;
let stopped = false;
let raf, stepTimer, endTimer, result = null;
function addStep() { sequence.push(Math.floor(Math.random() * 4)); }
function startShow() {
phase = 'show';
litIdx = -1;
showIdx = 0;
userSeq = [];
stepTimer = setInterval(() => {
litIdx = (litIdx === -1) ? sequence[showIdx] : -1;
if (litIdx === -1) {
showIdx++;
if (showIdx >= sequence.length) {
clearInterval(stepTimer);
litIdx = -1;
phase = 'input';
}
}
}, 500);
}
function checkInput(colorId) {
if (phase !== 'input') return;
userSeq.push(colorId);
const idx = userSeq.length - 1;
if (userSeq[idx] !== sequence[idx]) {
// Falsch
clearTimeout(endTimer);
result = 'lose';
endTimer = setTimeout(() => onDone(false), 1000);
phase = 'result';
return;
}
if (userSeq.length === sequence.length) {
if (sequence.length >= WIN_ROUNDS) {
clearTimeout(endTimer);
result = 'win';
endTimer = setTimeout(() => onDone(true), 900);
phase = 'result';
} else {
// Nächste Runde
phase = 'wait';
setTimeout(() => {
addStep();
startShow();
}, 800);
}
}
}
// Klick auf Farb-Button
canvas.addEventListener('click', e => {
if (phase !== 'input') return;
const rect = canvas.getBoundingClientRect();
const mx = (e.clientX - rect.left) * (canvas.width / rect.width);
const my = (e.clientY - rect.top) * (canvas.height / rect.height);
POS.forEach((p, i) => {
if (mx >= p.x && mx < p.x + GW && my >= p.y && my < p.y + GH)
checkInput(i);
});
});
// Starten
addStep();
startShow();
function loop() {
if (stopped) return;
raf = requestAnimationFrame(loop);
ctx.fillStyle = '#050508';
ctx.fillRect(0, 0, W, H);
// Felder zeichnen
POS.forEach((p, i) => {
const col = COLORS[i];
const isLit = litIdx === i;
const inUser = phase === 'input' && userSeq[userSeq.length - 1] === i;
ctx.shadowColor = isLit || inUser ? col.glow : 'transparent';
ctx.shadowBlur = isLit || inUser ? 30 : 0;
MGAPI.roundRect(ctx, p.x, p.y, GW, GH, 12,
isLit || inUser ? col.fill : `${col.fill}44`,
isLit || inUser ? col.fill : `${col.fill}88`);
ctx.shadowBlur = 0;
// Emoji mittig
ctx.font = `${Math.min(GW, GH) * 0.4}px serif`;
ctx.textAlign = 'center';
ctx.fillText(col.label, p.x + GW / 2, p.y + GH / 2 + GH * 0.14);
});
// HUD
const phaseText = phase === 'show' ? '👀 Schau zu...'
: phase === 'input' ? '👆 Deine Runde!'
: phase === 'wait' ? '✅ Richtig!'
: '';
MGAPI.text(ctx, phaseText, W / 2, 18,
{ size: 13, color: phase === 'input' ? '#f59e0b' : '#a7a3c2' });
MGAPI.text(ctx, `Runde ${sequence.length} / ${WIN_ROUNDS}`, W / 2, H - 10,
{ size: 11, color: 'rgba(255,255,255,0.35)' });
if (result)
MGAPI.resultScreen(ctx, W, H, result === 'win',
result === 'win' ? `${sequence.length} Runden gemeistert!` : 'Falsche Farbe!');
}
raf = requestAnimationFrame(loop);
return {
stop() {
stopped = true;
clearInterval(stepTimer);
clearTimeout(endTimer);
cancelAnimationFrame(raf);
},
};
}
function launch(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
function preview(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
return { id: ID, emoji: EMOJI, name: NAME, desc: DESC, controls: CONTROLS, multi: MULTI, launch, preview };
})();
/* ═══ typing.js ═══ */
/**
* minigames/typing.js
* ⌨️ Tipp-Rennen — Tippe den Text so schnell wie möglich!
*/
window.MG_typing = (function() {
const ID = 'typing';
const EMOJI = '⌨️';
const NAME = 'Tipp-Rennen';
const DESC = 'Tippe das angezeigte Wort so schnell wie möglich!';
const CONTROLS = 'Tastatur';
const MULTI = 3;
const WORD_POOLS = {
easy: ['Katze','Hund','Baum','Haus','Ball','Buch','Schule','Spiel','Kind','Mond'],
medium: ['Abenteuer','Computer','Programm','Zauber','Kristall','Phantom','Roboter','Galaxie'],
hard: ['Dinosaurier','Wissenschaft','Programmierung','Abenteuerland','Weltentdecker'],
};
function run(wrap, W, H, cfg, onDone) {
const { canvas, ctx } = MGAPI.makeCanvas(wrap, W, H);
const theme = cfg.theme || { primary: '#f43f5e' };
const WIN_WPM = cfg.winWpm || 30; // mind. 30 WPM zum Gewinnen
const ROUNDS = 3;
const allWords = [...WORD_POOLS.easy, ...WORD_POOLS.medium];
let words = [];
for (let i = 0; i < ROUNDS; i++) {
const pool = i < 2 ? WORD_POOLS.easy : WORD_POOLS.medium;
words.push(pool[Math.floor(Math.random() * pool.length)]);
}
let round = 0;
let typed = '';
let startTs = null;
let times = [];
let stopped = false;
let raf, endTimer, result = null;
// HTML-Input über dem Canvas
const input = document.createElement('input');
input.type = 'text';
input.autocomplete = 'off';
input.autocorrect = 'off';
input.autocapitalize = 'none';
input.spellcheck = false;
input.style.cssText = `
position:absolute;left:-9999px;top:0;opacity:0;width:1px;height:1px;
`;
wrap.style.position = 'relative';
wrap.appendChild(input);
setTimeout(() => input.focus(), 100);
canvas.addEventListener('click', () => input.focus());
input.addEventListener('input', () => {
typed = input.value;
if (!startTs && typed.length > 0) startTs = performance.now();
const word = words[round];
if (typed.toLowerCase() === word.toLowerCase()) {
const elapsed = (performance.now() - startTs) / 1000 / 60; // Minuten
const wpm = Math.round(word.length / 5 / elapsed); // Standard: 5 Zeichen = 1 Wort
times.push({ word, wpm });
typed = '';
input.value = '';
startTs = null;
round++;
if (round >= ROUNDS) {
const avgWpm = Math.round(times.reduce((a, b) => a + b.wpm, 0) / times.length);
result = avgWpm >= WIN_WPM ? 'win' : 'lose';
endTimer = setTimeout(() => onDone(result === 'win'), 1200);
}
}
});
function loop(ts) {
if (stopped) return;
raf = requestAnimationFrame(loop);
ctx.fillStyle = '#050508';
ctx.fillRect(0, 0, W, H);
if (round >= ROUNDS) {
const avgWpm = times.length
? Math.round(times.reduce((a,b) => a+b.wpm, 0) / times.length)
: 0;
MGAPI.resultScreen(ctx, W, H, result === 'win',
result === 'win' ? `${avgWpm} WPM — richtig schnell!` : `${avgWpm} WPM — weiter üben!`);
return;
}
const word = words[round];
const elapsed = startTs ? (ts - startTs) / 1000 : 0;
// Fortschrittsbalken (Timing-Druck)
const timeLimit = 10;
const prog = Math.min(1, elapsed / timeLimit);
if (prog >= 1 && !endTimer && !result) {
result = 'lose';
endTimer = setTimeout(() => onDone(false), 800);
}
const barW = W - 40;
MGAPI.roundRect(ctx, 20, H - 28, barW, 10, 4, 'rgba(255,255,255,0.07)', null);
const barColor = prog < 0.6 ? theme.primary : prog < 0.8 ? '#f59e0b' : '#ef4444';
MGAPI.roundRect(ctx, 20, H - 28, barW * (1 - prog), 10, 4, barColor, null);
// Rundenanzeige
MGAPI.text(ctx, `⌨️ Runde ${round + 1} / ${ROUNDS}`, W / 2, 20, { size: 12, color: theme.primary });
// Zu tippendes Wort
MGAPI.roundRect(ctx, W/2-140, H*0.2, 280, 60, 12,
'rgba(255,255,255,0.05)', `${theme.primary}44`);
MGAPI.text(ctx, word, W / 2, H * 0.2 + 34,
{ size: 28, family: "'Fredoka One',cursive", color: '#fff' });
// Eingabe-Anzeige (zeichenweiser Vergleich)
const charW = 26;
const startX = W / 2 - (word.length * charW) / 2;
const charY = H * 0.55;
MGAPI.text(ctx, 'Tippe:', W / 2, charY - 24, { size: 11, color: 'rgba(255,255,255,0.4)' });
for (let i = 0; i < word.length; i++) {
const cx = startX + i * charW + charW / 2;
const tc = (typed[i] || '').toLowerCase();
const wc = word[i].toLowerCase();
let color;
if (!typed[i]) color = 'rgba(255,255,255,0.2)';
else if (tc === wc) color = '#22c55e';
else color = '#ef4444';
MGAPI.roundRect(ctx, startX + i * charW, charY - 4, charW - 2, 32, 4,
'rgba(255,255,255,0.04)', `${color}66`);
MGAPI.text(ctx, typed[i] || word[i], cx, charY + 12, { size: 18, color });
}
// Cursor-Blinken
if (startTs || typed.length === 0) {
const cx = startX + Math.min(typed.length, word.length) * charW + 2;
if (Math.floor(ts / 500) % 2 === 0) {
ctx.fillStyle = theme.primary;
ctx.fillRect(cx, charY, 3, 32);
}
}
// letzten WPM anzeigen
if (times.length > 0) {
const last = times[times.length - 1];
MGAPI.text(ctx, `Letztes: ${last.wpm} WPM`, W / 2, H - 42, { size: 11, color: 'rgba(255,255,255,0.35)' });
}
}
raf = requestAnimationFrame(loop);
return {
stop() {
stopped = true;
clearTimeout(endTimer);
cancelAnimationFrame(raf);
if (input.parentNode) input.parentNode.removeChild(input);
},
};
}
function launch(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
function preview(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
return { id: ID, emoji: EMOJI, name: NAME, desc: DESC, controls: CONTROLS, multi: MULTI, launch, preview };
})();
/* ═══ puzzle.js ═══ */
/**
* minigames/puzzle.js
* 🧩 Zahlen-Puzzle — Schiebe die Kacheln in die richtige Reihenfolge! (15-Puzzle)
*/
window.MG_puzzle = (function() {
const ID = 'puzzle';
const EMOJI = '🧩';
const NAME = 'Zahlen-Puzzle';
const DESC = 'Schiebe die Kacheln in die richtige Reihenfolge (18)!';
const CONTROLS = 'Mausklick / Pfeiltasten';
const MULTI = 1;
function run(wrap, W, H, cfg, onDone) {
const { canvas, ctx } = MGAPI.makeCanvas(wrap, W, H);
const theme = cfg.theme || { primary: '#14b8a6' };
const SIZE = 3; // 3×3
const PAD = 20;
const cellW = Math.floor((W - PAD * 2) / SIZE);
const cellH = Math.floor((H - PAD * 2 - 30) / SIZE);
const OX = (W - SIZE * cellW) / 2;
const OY = 30 + (H - 30 - SIZE * cellH) / 2;
// Ziel: 1 2 3 / 4 5 6 / 7 8 _
const GOAL = [1,2,3,4,5,6,7,8,0];
let board = [...GOAL];
let moves = 0;
let stopped = false;
let raf, endTimer, solved = false;
// Mischeln (100 zufällige Züge)
function shuffle() {
for (let i = 0; i < 100; i++) {
const ei = board.indexOf(0);
const er = Math.floor(ei / SIZE), ec = ei % SIZE;
const nbr = [];
if (er > 0) nbr.push(ei - SIZE);
if (er < SIZE-1) nbr.push(ei + SIZE);
if (ec > 0) nbr.push(ei - 1);
if (ec < SIZE-1) nbr.push(ei + 1);
const ni = nbr[Math.floor(Math.random() * nbr.length)];
[board[ei], board[ni]] = [board[ni], board[ei]];
}
}
shuffle();
function slideAt(idx) {
if (solved) return;
const ei = board.indexOf(0);
const er = Math.floor(ei / SIZE), ec = ei % SIZE;
const tr = Math.floor(idx / SIZE), tc = idx % SIZE;
const adj = (er === tr && Math.abs(ec - tc) === 1) ||
(ec === tc && Math.abs(er - tr) === 1);
if (!adj) return;
[board[ei], board[idx]] = [board[idx], board[ei]];
moves++;
if (board.join() === GOAL.join()) {
solved = true;
endTimer = setTimeout(() => onDone(true), 900);
}
}
canvas.addEventListener('click', e => {
const rect = canvas.getBoundingClientRect();
const mx = (e.clientX - rect.left) * (canvas.width / rect.width);
const my = (e.clientY - rect.top) * (canvas.height / rect.height);
for (let i = 0; i < SIZE * SIZE; i++) {
const c = i % SIZE, r = Math.floor(i / SIZE);
const x = OX + c * cellW, y = OY + r * cellH;
if (mx >= x && mx < x + cellW - 4 && my >= y && my < y + cellH - 4)
slideAt(i);
}
});
const onKey = e => {
const ei = board.indexOf(0);
const map = { ArrowUp: SIZE, ArrowDown: -SIZE, ArrowLeft: 1, ArrowRight: -1 };
const di = map[e.key];
if (di && ei + di >= 0 && ei + di < SIZE * SIZE) {
e.preventDefault();
slideAt(ei + di);
}
};
document.addEventListener('keydown', onKey);
function loop() {
if (stopped) return;
raf = requestAnimationFrame(loop);
ctx.fillStyle = '#050508';
ctx.fillRect(0, 0, W, H);
MGAPI.text(ctx, `🧩 Züge: ${moves}`, W / 2, 18, { size: 12, color: theme.primary });
for (let i = 0; i < SIZE * SIZE; i++) {
const val = board[i];
const c = i % SIZE, r = Math.floor(i / SIZE);
const x = OX + c * cellW, y = OY + r * cellH;
if (val === 0) {
// Leerfeld
MGAPI.roundRect(ctx, x+2, y+2, cellW-8, cellH-8, 8, 'rgba(255,255,255,0.03)', null);
continue;
}
const isCorrect = val === GOAL[i];
MGAPI.roundRect(ctx, x+2, y+2, cellW-8, cellH-8, 10,
isCorrect ? `${theme.primary}33` : 'rgba(255,255,255,0.07)',
isCorrect ? theme.primary : 'rgba(255,255,255,0.15)');
MGAPI.text(ctx, String(val), x + cellW/2 - 2, y + cellH/2 + 2,
{ size: Math.floor(cellH * 0.38), family: "'Fredoka One',cursive",
color: isCorrect ? theme.primary : '#fff' });
}
if (solved)
MGAPI.resultScreen(ctx, W, H, true, `In ${moves} Zügen gelöst!`);
}
raf = requestAnimationFrame(loop);
return {
stop() {
stopped = true;
clearTimeout(endTimer);
cancelAnimationFrame(raf);
document.removeEventListener('keydown', onKey);
},
};
}
function launch(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
function preview(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
return { id: ID, emoji: EMOJI, name: NAME, desc: DESC, controls: CONTROLS, multi: MULTI, launch, preview };
})();
/* ═══ spotdiff.js ═══ */
/**
* minigames/spotdiff.js
* 🔍 Fehler finden — Finde alle Unterschiede zwischen den zwei Bildern!
*/
window.MG_spotdiff = (function() {
const ID = 'spotdiff';
const EMOJI = '🔍';
const NAME = 'Fehler finden';
const DESC = 'Finde alle Unterschiede zwischen den zwei Bildern!';
const CONTROLS = 'Mausklick';
const MULTI = 1;
// ── Bild-Sets (canvas-gezeichnete Szenen) ────────────────────────────────
// Jede Szene besteht aus drawA(ctx,W,H) und drawB(ctx,W,H),
// plus einer Liste von Unterschied-Hotspots { x, y, r } (relativ, 01)
const SCENES = [
{
name: 'Bauernhof',
drawA(ctx, W, H) {
// Himmel
ctx.fillStyle = '#7dd3fc'; ctx.fillRect(0, 0, W, H * 0.55);
// Gras
ctx.fillStyle = '#4ade80'; ctx.fillRect(0, H * 0.55, W, H * 0.45);
// Sonne
ctx.fillStyle = '#fbbf24'; ctx.beginPath(); ctx.arc(W*0.15, H*0.18, H*0.1, 0, Math.PI*2); ctx.fill();
// Haus
ctx.fillStyle = '#f87171'; ctx.fillRect(W*0.3, H*0.3, W*0.25, H*0.28);
ctx.fillStyle = '#7f1d1d'; ctx.beginPath(); ctx.moveTo(W*0.27,H*0.3); ctx.lineTo(W*0.425,H*0.12); ctx.lineTo(W*0.58,H*0.3); ctx.fill();
// Fenster (2)
ctx.fillStyle = '#bae6fd'; ctx.fillRect(W*0.34, H*0.38, W*0.06, H*0.07);
ctx.fillStyle = '#bae6fd'; ctx.fillRect(W*0.45, H*0.38, W*0.06, H*0.07);
// Tür
ctx.fillStyle = '#78350f'; ctx.fillRect(W*0.39, H*0.46, W*0.05, H*0.12);
// Baum (3 Kreise)
ctx.fillStyle = '#16a34a'; ctx.beginPath(); ctx.arc(W*0.75, H*0.38, W*0.06, 0, Math.PI*2); ctx.fill();
ctx.fillStyle = '#15803d'; ctx.beginPath(); ctx.arc(W*0.72, H*0.46, W*0.05, 0, Math.PI*2); ctx.fill();
ctx.fillStyle = '#14532d'; ctx.beginPath(); ctx.arc(W*0.79, H*0.44, W*0.05, 0, Math.PI*2); ctx.fill();
ctx.fillStyle = '#78350f'; ctx.fillRect(W*0.74, H*0.5, W*0.02, H*0.08);
// Wolke
ctx.fillStyle = '#fff';
ctx.beginPath(); ctx.arc(W*0.55, H*0.14, W*0.05, 0, Math.PI*2); ctx.fill();
ctx.beginPath(); ctx.arc(W*0.62, H*0.11, W*0.06, 0, Math.PI*2); ctx.fill();
ctx.beginPath(); ctx.arc(W*0.69, H*0.14, W*0.05, 0, Math.PI*2); ctx.fill();
},
drawB(ctx, W, H) {
// Himmel (UNTERSCHIED 1: dunkleres Blau)
ctx.fillStyle = '#38bdf8'; ctx.fillRect(0, 0, W, H * 0.55);
// Gras
ctx.fillStyle = '#4ade80'; ctx.fillRect(0, H * 0.55, W, H * 0.45);
// Sonne (UNTERSCHIED 2: weiter oben)
ctx.fillStyle = '#fbbf24'; ctx.beginPath(); ctx.arc(W*0.15, H*0.10, H*0.1, 0, Math.PI*2); ctx.fill();
// Haus
ctx.fillStyle = '#f87171'; ctx.fillRect(W*0.3, H*0.3, W*0.25, H*0.28);
ctx.fillStyle = '#7f1d1d'; ctx.beginPath(); ctx.moveTo(W*0.27,H*0.3); ctx.lineTo(W*0.425,H*0.12); ctx.lineTo(W*0.58,H*0.3); ctx.fill();
// Fenster — nur EINES (UNTERSCHIED 3)
ctx.fillStyle = '#bae6fd'; ctx.fillRect(W*0.34, H*0.38, W*0.06, H*0.07);
ctx.fillStyle = '#f87171'; ctx.fillRect(W*0.45, H*0.38, W*0.06, H*0.07); // rotes Fenster
// Tür
ctx.fillStyle = '#78350f'; ctx.fillRect(W*0.39, H*0.46, W*0.05, H*0.12);
// Baum (kleiner — UNTERSCHIED 4)
ctx.fillStyle = '#16a34a'; ctx.beginPath(); ctx.arc(W*0.75, H*0.42, W*0.04, 0, Math.PI*2); ctx.fill();
ctx.fillStyle = '#15803d'; ctx.beginPath(); ctx.arc(W*0.72, H*0.48, W*0.035, 0, Math.PI*2); ctx.fill();
ctx.fillStyle = '#14532d'; ctx.beginPath(); ctx.arc(W*0.79, H*0.46, W*0.035, 0, Math.PI*2); ctx.fill();
ctx.fillStyle = '#78350f'; ctx.fillRect(W*0.74, H*0.5, W*0.02, H*0.08);
// Wolke fehlt (UNTERSCHIED 5)
},
// Hotspots in Bild B (relativ 0-1)
spots: [
{ x: 0.42, y: 0.12, r: 0.07, label: 'Himmelfarbe' },
{ x: 0.15, y: 0.10, r: 0.08, label: 'Sonne' },
{ x: 0.48, y: 0.41, r: 0.06, label: 'Rotes Fenster' },
{ x: 0.75, y: 0.44, r: 0.07, label: 'Kleinerer Baum' },
{ x: 0.62, y: 0.13, r: 0.08, label: 'Fehlende Wolke' },
],
},
];
function run(wrap, W, H, cfg, onDone) {
const scene = SCENES[0];
const theme = cfg.theme || { primary: '#84cc16' };
// Zwei Canvas nebeneinander
const halfW = Math.floor((W - 8) / 2);
const imgH = H - 64;
const container = document.createElement('div');
container.style.cssText = 'position:relative;width:100%;';
wrap.appendChild(container);
const canvasA = document.createElement('canvas');
canvasA.width = halfW; canvasA.height = imgH;
canvasA.style.cssText = `display:inline-block;border-radius:8px;cursor:default;`;
const canvasB = document.createElement('canvas');
canvasB.width = halfW; canvasB.height = imgH;
canvasB.style.cssText = `display:inline-block;border-radius:8px;cursor:crosshair;margin-left:8px;`;
container.appendChild(canvasA);
container.appendChild(canvasB);
// HUD-Canvas
const hud = document.createElement('canvas');
hud.width = W; hud.height = 48;
hud.style.display = 'block';
container.appendChild(hud);
const ctxA = canvasA.getContext('2d');
const ctxB = canvasB.getContext('2d');
const ctxH = hud.getContext('2d');
scene.drawA(ctxA, halfW, imgH);
scene.drawB(ctxB, halfW, imgH);
let found = new Set();
let marks = []; // { x, y, ok }
let stopped = false;
let endTimer;
function drawMarks() {
scene.drawB(ctxB, halfW, imgH); // neu zeichnen
marks.forEach(m => {
ctxB.strokeStyle = m.ok ? '#22c55e' : '#ef4444';
ctxB.lineWidth = 3;
ctxB.beginPath();
ctxB.arc(m.x, m.y, 18, 0, Math.PI * 2);
ctxB.stroke();
if (m.ok) {
ctxB.fillStyle = 'rgba(34,197,94,0.25)';
ctxB.fill();
}
});
}
function drawHUD() {
ctxH.clearRect(0, 0, W, 48);
MGAPI.text(ctxH, `🔍 ${found.size} / ${scene.spots.length} Unterschiede gefunden`, W/2, 16,
{ size: 13, color: theme.primary });
MGAPI.text(ctxH, 'Klicke auf die Unterschiede im rechten Bild', W/2, 36,
{ size: 11, color: 'rgba(255,255,255,0.4)' });
}
canvasB.addEventListener('click', e => {
if (found.size >= scene.spots.length) return;
const rect = canvasB.getBoundingClientRect();
const mx = (e.clientX - rect.left) * (canvasB.width / rect.width);
const my = (e.clientY - rect.top) * (canvasB.height / rect.height);
// Nächsten Spot suchen
let hit = null;
scene.spots.forEach((s, i) => {
if (found.has(i)) return;
const sx = s.x * halfW, sy = s.y * imgH;
const d = Math.sqrt((mx - sx) ** 2 + (my - sy) ** 2);
if (d < s.r * Math.min(halfW, imgH)) hit = i;
});
if (hit !== null) {
found.add(hit);
const sx = scene.spots[hit].x * halfW;
const sy = scene.spots[hit].y * imgH;
marks.push({ x: sx, y: sy, ok: true });
// Auch in Bild A markieren
ctxA.strokeStyle = '#22c55e';
ctxA.lineWidth = 3;
ctxA.beginPath(); ctxA.arc(sx, sy, 18, 0, Math.PI * 2); ctxA.stroke();
ctxA.fillStyle = 'rgba(34,197,94,0.2)'; ctxA.fill();
} else {
marks.push({ x: mx, y: my, ok: false });
setTimeout(() => {
marks = marks.filter(m => m.ok);
drawMarks(); drawHUD();
}, 600);
}
drawMarks();
drawHUD();
if (found.size >= scene.spots.length && !endTimer) {
endTimer = setTimeout(() => onDone(true), 900);
// Overlay
ctxH.fillStyle = 'rgba(16,185,129,0.9)';
MGAPI.roundRect(ctxH, W/2-120, 4, 240, 38, 8, 'rgba(16,185,129,0.9)', null);
MGAPI.text(ctxH, '🎉 Alle Unterschiede gefunden!', W/2, 24,
{ size: 14, family: "'Fredoka One',cursive", color: '#fff' });
}
});
drawHUD();
return {
stop() {
stopped = true;
clearTimeout(endTimer);
},
};
}
function launch(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
function preview(wrap, W, H, cfg) { return run(wrap, W, H, cfg, won => MGAPI.onResult(won)); }
return { id: ID, emoji: EMOJI, name: NAME, desc: DESC, controls: CONTROLS, multi: MULTI, launch, preview };
})();
</script>
<script>
// ── Initialisierung — läuft NACH allen Modulen ──────────────────────────────
s1init();
updatePB();
if (ST.highestStep > 0) {
for (let i = 0; i < ST.highestStep && i < 4; i++) {
document.getElementById('s' + i).classList.remove('active');
document.getElementById('s' + i).style.display = 'none';
}
cur = ST.highestStep;
document.getElementById('s' + cur).classList.add('active');
updatePB();
showSummary(cur);
if (cur === 1) s2init();
if (cur === 2) s3init();
if (cur === 3) buildQuiz();
if (cur === 4) buildReview();
}
</script>
</body>
</html>