🎮

Adventure Builder Pro

Das vollständige Kompendium · Für Designer & Spielemacher
Version 5.0 Editor + Player Offline · Chrome/Edge Kein Code nötig

📋 Inhaltsverzeichnis

🚀
Schnellstart
In 5 Minuten zum ersten spielbaren Spiel
🆕
Neu in v4.5: ODER-Verknüpfung bei Conditional Exits · Flag-Auswahllisten statt Freitext · Bedingte Geschenke (givesItems mit requireFlag/requireFlagNot/requireItem) · noDrop mit sichtbarem 🗑️-Knopf bei hinterlegter Meldung · funktionierendes Start-Inventar (Item-Häkchen + zentrale Liste in den Einstellungen) · 🧰 Item-Verhalten (noDrop/maxCount) immer sichtbar, nicht mehr in der Kampf-Sektion versteckt. Bugfixes: Parser respektiert requiredFlag an Ausgängen und noDrop bei LEGE AB · Doppel-Bedingung an Ausgängen wirkt jetzt korrekt als UND · Geschenk-Buttons erscheinen nur bei erfüllter Bedingung · „Ausgang bearbeiten“ speichert den Item-Namen statt der ID.

Neu in v4.6 (Rückport aus dem eingestellten 5er-Zweig): 📚 Serie-Tab mit Kapitel-Editor (öffnet sich beim Laden einer serie.json) · 🔢 Variablen-Tab sowie varActions an Aktionen, Tauschen und Dialog-Antworten · requireAllFlags/requireNoneFlags an Dialog-Antworten.

Neu in v5.0: 🗝️ QR-Modus — Geheimwörter mit QR-Scan verbinden das Spiel mit echten Orten (verschlüsselt im JSON, 📷 Kamera-Scan im Player) · 🗝️ QR-Bogen-Generator als neues Werkzeug für Stationen und druckfertige Kärtchen. Alles optional — Spiele ohne Geheimwörter verhalten sich exakt wie bisher. → Kapitel 28.

Neu in v5.1: 📷 QR-Tor (qrGate) an Ausgängen und Objekt-Aktionen — der Scanner öffnet sich beim Klick, und nach dem richtigen Wort läuft die Handlung sofort weiter. Dazu der 🔍 Flag-Inspektor im Tab 🚩 Flags: Er zeigt für jedes Flag, wo es geprüft und gesetzt wird — und warnt, wenn es ins Leere läuft. Der QR-Modus wird im Tab 🎨 Anzeige ein-/ausgeschaltet (qrModeEnabled) und reiht sich damit neben Parser- und Nur-Text-Modus — aber ohne Live-Umschalter, denn er ändert die Lösbarkeit, nicht die Darstellung. Im Editor sind der 🔢 Variablen- und der 🏆 Achievements-Tab jetzt unter „⚙️ Features" freischaltbar — Anleitung dazu in Kapitel 12 & 14.

Was ist Adventure Builder Pro?

Adventure Builder Pro ist ein Werkzeug für alle, die Text-Adventure-Spiele erstellen möchten – ohne Programmieren zu müssen. Du gestaltest alles im Browser: Orte, Gegenstände, Charaktere, Rätsel und Geschichte. Das Ergebnis ist eine JSON-Datei, die du mit dem Player spielen kannst.

ℹ️
Alles läuft offline – du brauchst kein Internet. Öffne einfach adventure-editor.html und adventure-player.html in Chrome oder Edge.

Der Arbeitsablauf

1
Editor öffnen adventure-editor.html im Browser öffnen. Für ein bestehendes Spiel: "📂 Spiel laden" und JSON-Datei wählen.
2
Spiel aufbauen Die Tabs im Editor führen dich durch alle Bereiche: Orte → Objekte → NPCs → Flags → Rezepte → Cutscenes → Enden.
3
Exportieren "💾 JSON exportieren" – die Datei speichert alles was du gebaut hast.
4
Spielen & testen adventure-player.html öffnen, JSON laden, spielen. Fehler entdeckt? Zurück zum Editor.

Die Editor-Tabs auf einen Blick

TabInhaltWann benutzen?
📍 OrteRäume, Ausgänge, Objekte, NPCsAls erstes – die Welt aufbauen
📦 ObjekteAlle Items zentral definierenItems die Orte und NPCs brauchen
🗨️ NPCsCharaktere, Dialoge, Tausch, KampfFür lebendige Figuren
🚩 FlagsSpielzustände definierenVor Rezepten und Enden – Flags zuerst anlegen
🔮 RezepteCrafting: Item + Item = neues ItemBraucht Items und ggf. Flags
🎬 CutscenesStory-Sequenzen mit Bild/TextWerden von NPCs und Enden aufgerufen
🏁 EndenSieg- und NiederlagebedingungenBraucht Flags und ggf. Cutscenes
🔊 SoundsZentrale Sound-Bibliothek verwaltenSounds einmal hochladen, überall referenzieren
⚙️ FeaturesKampfsystem, Parser, Aufgaben, TTS aktivierenEinmalig konfigurieren
🎨 AnzeigeInventar, Layout, Schriftgröße, ThemesZum Schluss, für das Feintuning
🗺️ GraphVisueller Orts-Graph mit Drag & ZoomÜberblick bei komplexen Spielen

Neue Editor-Features

FeatureBeschreibungShortcut
↩️ Undo / ↪️ RedoBis zu 50 Schritte rückgängig machenStrg+Z / Strg+Y
🔍 Globale SucheFindet Orte, NPCs, Items und Flags sofort – Klick springt direkt dahinSuchfeld oben rechts
🗺️ Graph-TabCanvas-Graph aller Orte und Verbindungen, Knoten verschiebbar, Zoom per ScrollTab-Klick
📌 Orts-Liste verbessertMiniaturvorschau des Ortsbildes, Status-Badges (👤 NPCs, 📦 Objekte, 🚪 Ausgänge)
▶ TestenÖffnet den Player direkt aus dem Editor – kein manuelles Exportieren nötig. Spiel wird einmalig über den Browser-Speicher übergeben.Button oben rechts im Editor

Minimalstruktur eines Spiels (JSON)

Jedes Spiel besteht im Kern aus diesen Bausteinen:

{
 "title": "Mein Abenteuer",
 "author": "Dein Name",
 "startLocation": "ort_id", // Startort des Spielers
 "defaultTheme": "modern", // Visuelles Thema
 "locations": {}, // Alle Orte
 "items": {}, // Alle Gegenstände
 "npcs": {}, // Alle Charaktere
 "recipes": [], // Kombinierrezepte
 "flags": {}, // Spielzustände
 "sounds": {}, // 🔊 Sound-Bibliothek (optional)
 "gameEnds": { "win": [], "lose": [] },
 "cutscenes": {}, // Story-Sequenzen
 "displaySettings": {} // Layout-Einstellungen
}
🗺️
Orte & Ausgänge
Räume, Bereiche und wie man zwischen ihnen wechselt

Ort-Eigenschaften

{
 "ort_id": {
 "name": "Dunkler Keller",
 "description": "Es riecht modrig hier unten.",
 "image": "https://...", // Bild oder Video (WebM/MP4)
 "imageLoop": true, // Video wiederholen?
 "sound": "data:audio/...", // Hintergrundmusik
 "soundLoop": true,
 "silence": false, // Alle Sounds stummschalten
 "theme": "dark", // Ort-spezifisches Theme
 "exitTransition": "fade", // Übergangseffekt beim Verlassen
 "exits": {},
 "objects": [],
 "npcs": [],
 "conditionalNpcs": [],
 "playCutscene": "keller_intro", // Cutscene beim Betreten
 "playCutsceneOnce": true
 }
}
EigenschaftPflicht?Beschreibung
name✅ JaAnzeigename des Ortes
description✅ JaBeschreibungstext
image○ Opt.URL, Base64 oder Data-URL (Bild oder Video)
sound○ Opt.Hintergrundmusik (MP3/OGG als Data-URL)
theme○ Opt.Überschreibt das globale Theme für diesen Ort
exitTransition○ Opt.fade, slide-left, slide-right, zoom, dissolve
silence○ Opt.true = kein Sound in diesem Ort
soundRequireFlag○ Opt.🎚️ Musik spielt nur, wenn dieses Flag gesetzt ist (z.B. strom_an). Reagiert sofort beim Flag-Wechsel – auch wenn der Spieler im Raum steht.
soundRequireFlagNot○ Opt.🎚️ Musik spielt nur, wenn dieses Flag NICHT gesetzt ist. Umkehrung – z.B. für eine „Ausfall“-Stimmung bis zum Stromfix.

HTML in Beschreibungen verwenden

Orts- und Objekt-Beschreibungen werden im Grafik- und Parser-Modus als HTML dargestellt. Du kannst sie also mit einfachen HTML-Tags formatieren – fett, kursiv, farbig, mit Zeilenumbrüchen und mehr. Es gibt keine feste Liste erlaubter Tags; sinnvoll fürs Formatieren sind vor allem diese:

TagWirkungBeispiel
<b> / <strong>fettEs ist <b>stockdunkel</b>.
<i> / <em>kursiv<i>Irgendwo</i> tropft Wasser.
<u>unterstrichen<u>Achtung</u>
<br>ZeilenumbruchZeile 1<br>Zeile 2
<p>Absatz<p>Erster Absatz.</p>
<span style="color:#c00">Textfarbe<span style="color:#c00">Gefahr!</span>
<ul> / <li>Aufzählung<ul><li>Tür</li></ul>
<small>kleiner<small>(kaum lesbar)</small>
<mark>hervorgehoben<mark>Schlüssel</mark>
⚠️
Achtung Textmodus: Im reinen Text-/Terminal-Modus werden Beschreibungen als reiner Text ausgegeben – HTML-Tags erscheinen dort wörtlich (z.B. <b>dunkel</b>). Wenn dein Spiel auch im Textmodus spielbar sein soll, setze HTML in Beschreibungen sparsam ein oder verzichte darauf.
💡
Schließe Tags immer sauber (<b>…</b>) – offenes HTML kann das Layout stören. Für einen Zeilenumbruch brauchst du <br>; ein einfacher Umbruch im Editor-Textfeld wird in der Grafikansicht nicht übernommen. Das gilt verlässlich für Orts- und Objekt-Beschreibungen.

Ausgänge (Exits)

Neu: Überarbeiteter Tab Anzeige v4.4

Der Tab Anzeige ist in 5 thematische Sektionen gegliedert:

  • 🎨 Darstellung & Theme – Standard-Theme, Kompakt-Modus, Container-Größe
  • 🖼️ Bilder & Thumbnail-Größen – Objekte, NPC Portraits, Modals
  • 📦 Objekte & Ausgänge – Ausgänge (Bild/Farbe/Layout), Raum-Layout
  • 🎒 Inventar – Thumbnail, Position, Mechanik, Spalten, Button-Modus
  • 👁️ Sichtbarkeit & Spielmodi – Text-Anzeige, Parser, Nur-Text, Unterstützung, Ziele

A) Einfache Ausgänge

Richtwörter als Keys oder beliebige Texte – was du schreibst, erscheint als Button.

"exits": {
 "N": "wald_nord", // Standard: N S O W H R
 "Durch die Tür": "raum_2", // Eigener Text möglich
 "Ins Wasser": "see"
}

B) Ausgang mit Flag-Bedingung

Der Ausgang ist nur nutzbar wenn eine bestimmte Flag gesetzt ist.

"exits": {
 "N": {
 "to": "geheimraum",
 "requiredFlag": "tuer_offen",
 "deniedMessage": "Die Tür ist noch verschlossen."
 }
}

C) Ausgang mit Item-Bedingung

Der Spieler muss ein bestimmtes Item im Inventar haben.

"exits": {
 "O": {
 "to": "schatzkammer",
 "requiredItem": "goldener_schluessel",
 "deniedMessage": "Du brauchst den goldenen Schlüssel!"
 }
}

D) Ausgang mit kombinierten Bedingungen

"exits": {
 "Portal": {
 "to": "andere_dimension",
 "requiredFlag": "portal_aktiviert",
 "requiredItem": "magischer_kristall",
 "deniedMessage": "Das Portal reagiert nicht..."
 }
}
Praxisbeispiel: Klassische Schlüssel-Tür-Mechanik

Spieler findet Schlüssel → benutzt ihn an einer Eisentür → Flag tuer_offen wird gesetzt → Ausgang im Norden ist jetzt nutzbar.

// Objekt im Ort: Eisentür
{
 "itemName": "Eisentür",
 "canTake": false,
 "usableWith": [{
 "itemId": "rost_schluessel",
 "success": "Die Tür quietscht auf!",
 "setFlag": "tuer_offen",
 "removeItem": true
 }]
}

// Ausgang des Ortes
"N": {
 "to": "naechster_raum",
 "requiredFlag": "tuer_offen",
 "deniedMessage": "Die Tür ist verschlossen!"
}

E) ODER-Verknüpfung zweier Bedingungen 🆕 v4.5

Sind requiredFlag und requiredItem gesetzt, gilt normalerweise UND (beides nötig). Mit conditionLogic: "OR" genügt eine erfüllte Bedingung – z. B. „Taschenlampe im Inventar oder Strom ist an“.

"Teeküche": {
 "to": "kueche",
 "requiredItem": "Taschenlampe",
 "requiredFlag": "strom_an",
 "conditionLogic": "OR"
}
🖱️
Im Editor: ➕ Ausgang bzw. ✏️ Ausgang bearbeiten → beide Häkchen im Block 🔐 Conditional Exit setzen → das Feld „🔗 Verknüpfung der beiden Bedingungen“ erscheint (UND/ODER). Das Flag wählst du seit v4.5 bequem aus einer Liste vorhandener Flags.
✍️
Schreibweise: Bei Standard-Ausgängen heißen die Felder requiredFlag/requiredItem (mit „d“) – so speichert sie der Editor. Die Kurzform ohne „d“ wird vom Player ab v4.5 toleriert, überall sonst (Aktionen, Tausch, Geschenke, Enden) gilt weiterhin requireFlag ohne „d“. Verhalten: Unerfüllte Bedingungen blenden den Ausgangs-Button aus; die deniedMessage erscheint nur im Parser-Modus (GEHE …). Mit discoveryMessage begrüßt der Ausgang den Spieler, sobald er sichtbar wird.

Objekte im Ort

Objekte sind Dinge, die der Spieler sieht und mit denen er interagieren kann – anfassen, untersuchen, ein Item darauf anwenden.

A) Einfaches nehmbares Objekt

{
 "itemId": "rost_schluessel", // Referenz auf ein definiertes Item
 "canTake": true
}

B) Objekt mit Item-Anwendung (usableWith)

Was passiert, wenn ein Spieler ein bestimmtes Item aus dem Inventar auf dieses Objekt anwendet?

{
 "itemId": "truhe",
 "canTake": false,
 "failMessage": "Das bringt hier nichts.",
 "usableWith": [{
 "itemId": "schluessel",
 "actionLabel": "🔓 Aufschließen",
 "success": "Die Truhe öffnet sich!",
 "changeObject": "offene_truhe", // Objekt wird ersetzt
 "spawnObject": "gold", // Neues Objekt erscheint
 "spawnCanTake": true,
 "removeItem": true, // Schlüssel wird verbraucht
 "setFlag": "truhe_geoeffnet",
 "playCutscene": "truhe_oeffnen"
 }]
}
Eigenschaft in usableWithBedeutung
itemId / itemNameWelches Item muss der Spieler anwenden?
actionLabelButton-Text (leer = "Anwenden")
successNachricht bei Erfolg
givesItemIdItem erscheint im Inventar (Transformation)
requireItemIdZusätzliches Item muss im Inventar sein
requireFlagNotAktion gesperrt wenn diese Flag gesetzt ist
changeObjectObjekt wird ersetzt durch… (Item-Name)
spawnObjectNeues Objekt erscheint im Raum
spawnCanTakeKann das gespawnte Objekt aufgenommen werden?
removeObjectObjekt verschwindet komplett
removeItemVerwendetes Item wird verbraucht
setFlag / clearFlagFlag setzen oder löschen
teleportToSpieler wird teleportiert
playCutsceneCutscene abspielen danach
requireVarVariable-Bedingung: {"name":"geld","op":">=","val":5}
addVarVariable ändern: {"name":"energie","val":-1}
varActionsMehrere Variablen auf einmal: [{"name":"geld","val":-5},{"name":"punkte","val":10}]

🔗 spawnObjectId – usableWith aus Item-Definition erben v4.4

Wenn ein gespawntes Objekt sofort interaktiv sein soll, reicht spawnObject allein nicht – das erzeugte Objekt hätte ein leeres usableWith. Mit spawnObjectId verweist die Aktion auf den Item-Eintrag im items{}-Dict, und der Player übernimmt dessen usableWith automatisch.

"usableWith": [{
  "actionLabel": "🔍 Mauer absuchen",
  "requireFlag": "fackel_entzuendet",
  "removeObject": true,
  "spawnObject": "Hebel",
  "spawnObjectId": "hebel",  // ← verknüpft mit items["hebel"]
  "spawnCanTake": false,
  "message": "Du entdeckst einen verborgenen Hebel!"
}]

💡 Der Editor setzt spawnObjectId automatisch wenn du im Spawn-Dropdown ein Item auswählst.

⚠️ spawnObject ohne spawnObjectId – altes Verhalten, weiterhin gültig.

E) Variablen in Objekt-Aktionen

Aktionen können Variablen prüfen (Bedingung) und ändern (Effekt). Der Editor zeigt den blauen 🔢 Variable-Block im Aktions-Modal.

🗺️ Orte → Objekt → ✏️ Bearbeiten → Aktion → 🔢 Variable (Bedingung & Aktion)
// Kühlschrank: gibt Apfel, kostet 1 Energie
{
 "actionLabel": "Apfel holen",
 "success": "Du nimmst einen Apfel. (-1 Energie)",
 "givesItem": "Apfel",
 "addVar": { "name": "energie", "val": -1 }
}

// Münzbrunnen: braucht min. 1€, kostet 1€, gibt 5 Punkte
{
 "actionLabel": "Wunsch machen (1 €)",
 "requireVar": { "name": "geld", "op": ">=", "val": 1 },
 "success": "Du wirfst eine Münze ins Wasser. +5 Punkte!",
 "varActions": [
 { "name": "geld", "val": -1 },
 { "name": "punkte", "val": 5 }
 ]
}

// Backofen: braucht Energie ≥ 2 + Flag, gibt Kuchen + Punkte
{
 "actionLabel": "🎂 Kuchen backen!",
 "requireFlag": "zutaten_gekauft",
 "requireVar": { "name": "energie", "op": ">=", "val": 2 },
 "success": "Du backst einen Geburtstagskuchen! +50 Punkte!",
 "givesItem": "Geburtstagskuchen",
 "setFlag": "kuchen_gebacken",
 "varActions": [
 { "name": "energie", "val": -2 },
 { "name": "punkte", "val": 50 }
 ]
}

C) Direkte Aktion (ohne Item) Direct Action

Ein Button der immer sichtbar ist – zum Untersuchen, Zählen, Aktivieren.

"usableWith": [{
 "itemName": "", // Leer = kein Item nötig
 "actionLabel": "🔍 Untersuchen",
 "success": "Du findest einen versteckten Hinweis!",
 "spawnObject": "hinweis",
 "spawnCanTake": true
}]

D) Mehrfach-Verwendung (Quantity)

Der Button ist nur eine begrenzte Anzahl von Malen nutzbar.

"usableWith": [{
 "itemName": "",
 "actionLabel": "🍪 Keks nehmen",
 "success": "Lecker! Du nimmst einen Keks.",
 "quantity": 5,
 "quantityMessage": "Die Dose ist leer!",
 "spawnObject": "keks",
 "spawnCanTake": true
}]

E) Bedingte NPCs im Ort

Manche Charaktere erscheinen nur unter bestimmten Bedingungen.

"conditionalNpcs": [
 { "npcId": "geist_id", "requireFlag": "mitternacht" },
 { "npcId": "drache_id", "forbidFlag": "drache_besiegt" }
]

F) Ausgänge erweitern: Bild, Farbe & Layout v4.4

Seit v4.4 können Ausgangs-Buttons optisch aufgewertet werden. Alle Einstellungen im Editor unter Tab Anzeige → 🚪 Ausgänge.

🖼️ Bild für einen Ausgang

Im Ausgang-Modal (Ort bearbeiten → Ausgang ✏️) kannst du ein Bild hochladen. Das Bild bestimmt dann die Größe des Buttons – der Text erscheint darunter oder daneben.

"exits": {
  "N": {
    "to": "dunkler_gang",
    "image": "data:image/png;base64,..."
  }
}

🎨 Ausgangs-Farbe (global)

Im Tab Anzeige → 🚪 Ausgänge → Button-Farbe kannst du eine CSS-Farbe eingeben, die alle Ausgangs-Buttons überschreibt. Leer = Theme-Farbe.

"displaySettings": {
  "exitButtonColor": "#1e1f1e",
  "exitButtonStyle": "compact",
  "exitLayout": "horizontal",
  "thumbSizeExits": 80
}
FeldWerteBedeutung
exitButtonColor"#ff6600", "red", leerFarbe aller Exit-Buttons (überschreibt Theme)
exitButtonStyle"normal", "compact"Normal = volle Grid-Breite, Kompakt = Inhalt bestimmt
exitLayout"vertical", "horizontal", "image-only"Layout wenn Ausgang ein Bild hat
thumbSizeExits40–200Bildgröße in Pixeln

🔐 Bedingter Ausgang: Item im Inventar

Das requiredItem-Feld prüft den Anzeigenamen des Items. Im Editor gibt es ein Dropdown mit allen vorhandenen Item-Namen.

"N": {
  "to": "dunkler_gang",
  "requiredItem": "Fackel",
  "deniedMessage": "Es ist zu dunkel ohne Licht."
}

💡 requiredItem enthält den Anzeigenamen, nicht die interne ID.

🔀 Konditionale Ausgänge (neu in v5.0)

Zwei Sorten Ausgänge — und der Unterschied ist wichtig:

ArtVerhaltenKann prüfen
Normaler AusgangImmer sichtbar, ggf. gesperrt (mit Verwehr-Text)Items & Flags
Konditionaler AusgangUnsichtbar, bis die Bedingung stimmt — dann erscheint er plötzlichFlags und Zahlen (🔢 Variablen)

Anlegen: Tab 📍 Orte → Ort öffnen → Akkordeon „Ausgänge“ → ganz unten „➕ Konditionaler Ausgang“. Zielort wählen, Anzeigename eintippen, Bedingung setzen.

💡
Der Aha-Moment: „Der Tresor öffnet sich!“ — ein Weg, der erst erscheint, wenn 12 Zahnräder beisammen sind (zahnraeder ≥ 12). Normale Ausgänge können keine Zahlen prüfen — dafür gibt es genau diesen Baustein.

🚫 Verwehr-Text (neu in v5.0)

Jeder Ausgang hat ein Feld „Verwehr-Text, wenn Bedingungen fehlen“. Es ersetzt das nichtssagende „Weg versperrt“ durch deinen eigenen Satz — und ist der wichtigste Satz im QR-Modus: Er darf ruhig verraten, wo das Fehlende zu finden ist.

🚫
Beispiel: „Die Tür ist zu — hier braucht ihr BEIDES: 🔦 die Taschenlampe (Requisitentisch im Backstage) UND den Türcode von der echten Technikraum-Tür.“ Das entscheidet über Frust oder Aha-Moment.
📦
Items & Inventar
Gegenstände definieren und das Inventar steuern

Items definieren

Alle Items werden zentral im Tab 📦 Objekte angelegt. Jedes Item bekommt eine eindeutige ID – so kann es überall im Spiel referenziert werden, ohne dass das Spiel kaputt geht wenn du den Namen änderst.

"items": {
 "goldener_schluessel": {
 "id": "goldener_schluessel",
 "name": "🔑 Goldener Schlüssel",
 "description": "Ein prächtiger Schlüssel aus purem Gold.",
 "image": "data:image/png;base64,...", // auch WebM/MP4 möglich
 "sfx": "snd_1234_abc" // 🔊 Sound-ID aus der Bibliothek – spielt beim Aufnehmen
 }
}
💡
Emojis machen das Spiel bunter! Windows: Win + . | Mac: Cmd + Ctrl + Space

Selbst-Verwendung (selfUse)

Was passiert, wenn der Spieler ein Item direkt im Inventar benutzt? Es gibt zwei Felder: selfUse: true macht das Item benutzbar, onUse definiert was passiert. Im Player zeigt jedes benutzbare Item dann automatisch einen grünen ▶️-Knopf direkt im Inventar (neben dem ℹ️-Knopf) – ein Klick benutzt es sofort. Items ohne selfUse zeigen den Knopf nicht.

📦 Objekte → Item auswählen → ☑️ „Sofort benutzen (ohne Ziel)" → Text, Variable, ☑️ verbrauchen
// Beispiel 1: Heiltrank (HP)
"heiltrank": {
 "name": "💊 Heiltrank",
 "selfUse": true,
 "onUse": {
 "message": "Du trinkst den Heiltrank. +20 HP!",
 "healHP": 20,
 "removeItem": true
 }
}

// Beispiel 2: Apfel gibt +4 Energie (Variable)
"apfel": {
 "name": "🍎 Apfel",
 "selfUse": true,
 "onUse": {
 "message": "Mmm, lecker! +4 Energie!",
 "removeItem": true,
 "varActions": [{ "name": "energie", "val": 4 }]
 }
}

// Beispiel 3: Zaubertrank – HP und Energie gleichzeitig
"zaubertrank": {
 "name": "✨ Zaubertrank",
 "selfUse": true,
 "onUse": {
 "message": "Du trinkst den Trank. +10 HP, +5 Energie!",
 "healHP": 10,
 "removeItem": true,
 "varActions": [{ "name": "energie", "val": 5 }]
 }
}
onUse-FeldBedeutung
messageText beim Benutzen
removeItemItem wird verbraucht
healHPHP wiederherstellen (Kampfsystem)
setFlagFlag auf true setzen
clearFlagFlag auf false setzen (z.B. um einen Zustand rückgängig zu machen)
varActionsVariablen ändern (Array, mehrere möglich)
💡
Der Editor setzt selfUse: true automatisch wenn „Sofort benutzen" aktiviert wird – du musst es nicht manuell eintragen.

Item-Obergrenze & nicht ablegbare Items

Zwei optionale Item-Felder steuern, wie viele Exemplare existieren dürfen und ob sich ein Item ablegen lässt.

Maximale Anzahl (maxCount)

maxCount begrenzt, wie viele Exemplare eines Items gleichzeitig in der Welt existieren dürfen (Raum-Objekte + Inventar zusammengezählt). Besonders nützlich bei Items, die per spawnObject erzeugt oder per Rezept gecraftet werden – so entstehen nie versehentlich zwei.

📦 Objekte → Item auswählen → 🔢 „Maximale Anzahl (maxCount)" (leer = unbegrenzt)
"tasse_wasser": {
"name": "Tasse mit heißem Wasser",
"maxCount": 1
}
💡
Ein Wasserkocher mit spawnObject: "Tasse mit heißem Wasser" und maxCount: 1 kann beliebig oft angeklickt werden, ohne dass je zwei Tassen herumstehen.

Nicht ablegbar (noDrop)

noDrop: true verhindert, dass der Spieler ein Item fallen lässt – auch der Textbefehl LEGE AB wird abgewiesen (v4.5). Über noDropMessage steuerst du das Verhalten: Mit Meldung bleibt der 🗑️-Knopf sichtbar und antwortet beim Klick im LucasArts-Stil („Das behalte ich lieber…“); ohne Meldung wird der 🗑️-Knopf komplett ausgeblendet. So verhinderst du Sierra-Sackgassen, ohne auf Charaktermomente zu verzichten.

📦 Objekte → Item auswählen → 🔒 „Nicht ablegbar (noDrop)" + optionale Meldung
"amulett": {
"name": "🔮 Verfluchtes Amulett",
"noDrop": true,
"noDropMessage": "Das Amulett klebt wie festgewachsen an dir – du wirst es nicht mehr los."
}
💡
Ideal für Schlüssel-Gegenstände, die nicht verloren gehen dürfen, oder für erzählerische Effekte wie ein verfluchtes Amulett, das man nie wieder ablegen kann.

Start-Inventar (🎒) 🆕 v4.5

Items mit "startInventory": true liegen ab Spielbeginn im Inventar des Spielers.

"programmheft": {
 "name": "Programmheft",
 "startInventory": true
}
🖱️
Zwei gleichwertige Wege im Editor: das 🎒-Häkchen am Item (Tab 📦 Objekte → Sektion 🧰 Item-Verhalten) oder die zentrale Liste unter ⚙️ Einstellungen → 🎒 Start-Inventar. Beide schreiben dasselbe Feld – Items mit 🎒 sind in der Objekte-Liste markiert. Hinweis: Bis v4.4 war das Häkchen ohne Funktion (wurde nie gespeichert); seit v4.5 funktioniert es.

Inventar-Freischaltung

Normalerweise ist das Inventar von Anfang an sichtbar. Mit dieser Mechanik bleibt es versteckt, bis der Spieler ein bestimmtes Objekt aufnimmt – eine Tasche, einen Rucksack, eine magische Truhe.

Warum das sinnvoll ist: Ohne Inventar-Sperre kann der Spieler von Anfang an alles einsammeln. Mit der Sperre gibt es einen logischen Grund, warum man Gegenstände tragen kann. Das Freischalt-Item ist das Inventar – es erscheint deshalb nicht als Gegenstand darin.
🎨 Anzeige → Inventar → "Inventar zu Beginn ausblenden" ✅ → "Freischalt-Item ID"
1
Item anlegen (Tab 📦 Objekte) Erstelle z.B. id: "rucksack", Name: "Roter Rucksack".
2
Als Raumobjekt platzieren (Tab 📍 Orte) Das Item als Objekt am Startort hinzufügen (canTake: ✅).
3
Inventar sperren (Tab 🎨 Anzeige) "Inventar zu Beginn ausblenden" aktivieren, ID: rucksack eintragen.
JSON-FeldWertBedeutung
inventoryHiddenAtStarttrue / falseInventar beim Start versteckt?
unlockInventoryItemIdItem-IDDieses Item schaltet das Inventar frei
allowInventoryChangetrue / falseDarf der Spieler die Position ändern?
inventoryPositionright / left / bottomStandard-Position des Inventars
⚠️
Das Freischalt-Item darf nie als Tausch-Item von einem NPC eingefordert werden – sonst verliert der Spieler das Inventar und alle darin enthaltenen Gegenstände.

E) usableWith direkt auf Item-Definitionen v4.4

Items im items{}-Dict können selbst ein usableWith-Array haben. Wird das Item per spawnObjectId als Raum-Objekt gespawnt, übernimmt der Player diese Aktionen automatisch.

"items": {
  "hebel": {
    "id": "hebel", "name": "Hebel",
    "usableWith": [
      {
        "actionLabel": "🔧 Hebel drücken",
        "requireFlagNot": "tor_offen",
        "setFlag": "tor_offen",
        "message": "Das Tor schwingt auf!"
      }
    ]
  }
}
FeldBeschreibung
actionLabelText des Buttons
messageNachricht beim Klick
requireFlagNur sichtbar wenn Flag gesetzt
requireFlagNotNur sichtbar wenn Flag NICHT gesetzt
setFlagSetzt Flag bei Ausführung

💡 Im Editor: Items → bearbeiten → „🎯 Direkte Aktionen" direkt über dem Speichern-Button.

🔢 Mengen: gestapelte Items (neu in v5.0)

Items lassen sich stapeln. Hat der Spieler mehr als eines, zeigt das Inventar ein Zähler-Abzeichen („12x“) auf dem Item-Bild.

Ich will …Feld im Editor
Eine Aktion soll mehrere Stück geben („Du findest 5 Zahnräder“) Objekt-Aktion → 🎁 Gibt Item — mit Anzahl
Ein Tor soll eine Anzahl verlangen („12 Zahnräder“) Ausgang → 🔢 Benötigte Anzahl (Standard 1)
Das Abzeichen sitzt ungünstig Tab 🎨 Anzeige → 🔢 Mengen-Abzeichen im Inventar (↖️ links oben ist Standard, weil rechts die ℹ️/🗑️-Knöpfe sitzen)
⚠️
Die Fundstellen-Regel — bitte merken: Jedes Objekt, das etwas hergibt, muss danach seinen Zustand ändern — sonst ist es eine Gelddruckmaschine (der Spieler klickt einfach zehnmal). Nutze an der Objekt-Aktion das Feld changeObject („Leere Zahnrad-Kiste“) oder removeObject. Das Objekt verliert dabei seine Aktion und ist erledigt.
🗨️
NPCs & Charaktere
Dialoge, Tausch, Kampf und lebendige Figuren

Basis-Definition

"haendler": {
 "name": "Alter Händler",
 "dialog": "Willkommen! Was darf es sein?", // Statischer Text
 "portrait": "data:image/png;base64,...", // Bild oder Video
 "portraitSize": "medium", // small/medium/large/full
 "playCutscene": "haendler_intro", // Cutscene VOR Dialog
 "playCutsceneOnce": true,
 "playCutsceneAfter": "haendler_abschied", // Cutscene NACH Dialog
 "givesItems": [],
 "receivesItems": [],
 "dialogTree": {} // Verzweigter Dialog → Kapitel 5
}
ℹ️
Wenn ein NPC einen dialogTree hat, übernimmt dieser den statischen dialog. Beide können koexistieren – der Baum hat Vorrang.

NPC gibt Items (givesItems)

Der Spieler erhält beim Gespräch ein oder mehrere Items – kostenlos, ohne Gegenleistung.

"givesItems": [{
 "name": "Heiltrank",
 "description": "Stellt Lebenspunkte wieder her",
 "playCutscene": "trank_geschenk",
 "playCutsceneOnce": true
}]

Bedingte Geschenke 🆕 v4.5

Ein Geschenk kann an Bedingungen geknüpft werden – der 🎁-Knopf erscheint erst, wenn alle gesetzten Bedingungen erfüllt sind:

"givesItems": [{
 "name": "Teebeutel",
 "requireFlag": "strom_an",
 "requireFlagNot": "konzert_gestartet",
 "requireItem": "Ausweis"
}]
🎒
requireItem prüft nur, ob das Item im Inventar liegt – es wird nicht verbraucht („Zeig mir deinen Ausweis, dann bekommst du den Schlüssel“). Soll der NPC das Item behalten, ist das ein Tausch → receivesItems.
🖱️
Im Editor: Tab 🗨️ NPCs → Sektion 📦 Gibt Items (kostenlos)➕ Item hinzufügen → Block 🔒 Bedingungen (optional) mit drei Auswahlfeldern.

NPC nimmt Items (receivesItems – Tausch)

A) Einfacher Tausch

"receivesItems": [{
 "itemId": "altes_schwert",
 "message": "Ein feines Stück! Hier, nimm das dafür.",
 "givesItemId": "neues_schwert",
 "setFlag": "upgrade_erhalten"
}]

B) Tausch mit Bedingungen

"receivesItems": [{
 "itemId": "brief",
 "message": "Danke für die Lieferung!",
 "givesItemId": "belohnung",
 "requireFlag": "quest_aktiv", // Muss gesetzt sein
 "requireFlagNotSet": "brief_abgegeben", // Muss NICHT gesetzt sein
 "failTitle": "❌ Abgelehnt",
 "failMessage": "Das kann ich jetzt nicht annehmen.",
 "setFlag": "brief_abgegeben"
}]
Praxisbeispiel: Item-Übergabe im Dialog-Baum

Wenn ein NPC einen Dialog-Baum hat und receivesItems definiert ist, erscheint automatisch ein grüner "🎁 [Item] übergeben"-Button im Gespräch – sobald der Spieler das entsprechende Item im Inventar hat.

Kampfsystem (HP-basiert)

Wenn ein NPC maxHP gesetzt hat, kann er mit Items angegriffen werden. Der Spieler klickt auf den NPC → wählt ein Waffen-Item → der NPC verliert HP. Bei 0 HP: onDefeat.

"drache": {
 "name": "Roter Drache",
 "maxHP": 100,
 "counterDamage": 15, // Schaden beim Gegenschlag (opt.)
 "usableWith": [{
 "itemName": "Drachenschwert",
 "damage": 25,
 "success": "Du triffst den Drachen!",
 "onDefeat": {
 "message": "Der Drache ist besiegt! 🎉",
 "givesItem": "drachenschuppe",
 "teleportTo": "thronsaal",
 "setFlag": "drache_besiegt",
 "clearFlag": "drache_lebt",
 "playCutscene": "sieg_drache"
 }
 }]
}
FeldBedeutung
maxHPMaximale HP (macht NPC kämpfbar)
counterDamageSchadenspunkte beim Gegenschlag (nur wenn Spieler-HP aktiv)
damageSchaden pro Treffer
onDefeatWas passiert bei 0 HP (Belohnung, Teleport, Flags, Cutscene)
ℹ️
Spieler-HP: Muss im Tab "🎨 Anzeige" aktiviert werden. Bei 0 HP wird automatisch die Flag player_dead gesetzt – damit lässt sich eine Verlier-Bedingung bauen.

F) Fake-Kampfsystem mit requireFlag / requireFlagNot v4.4

Zwei usableWith-Einträge mit demselben Item simulieren einen Kampf mit unterschiedlichem Ausgang je nach Flag. Der Spieler sieht immer nur einen Button:

"usableWith": [
  {
    "itemName": "Holzschwert",
    "actionLabel": "⚔️ Kämpfen! (trainiert)",
    "requireFlag": "trainiert",
    "setFlag": "krieger_besiegt",
    "message": "🏆 Sieg!"
  },
  {
    "itemName": "Holzschwert",
    "actionLabel": "⚔️ Kämpfen! (ohne Training)",
    "requireFlagNot": "trainiert",
    "setFlag": "krieger_verloren",
    "message": "💀 Niederlage!"
  }
]

Besiegte NPCs mit conditionalNpcs ausblenden:

"conditionalNpcs": [
  { "npcId": "goblin_wache", "forbidFlag": "goblin_besiegt" }
]
💬
Dialog-Bäume
Verzweigte Gespräche – die Geschichte verändert sich je nach Antwort

Was sind Dialog-Bäume?

Statt einem starren Dialog-Satz kann jeder NPC jetzt einen echten Gesprächsbaum führen. Der Spieler wählt Antworten, die die Geschichte in verschiedene Richtungen lenken. Flags können gesetzt, Items vergeben und Cutscenes ausgelöst werden.

🗨️ NPCs → NPC → 💬 Dialog-Baum → ➕ Knoten hinzufügen

Aufbau: Knoten und Antworten

Ein Dialog-Baum besteht aus Knoten. Jeder Knoten ist ein Gesprächs-Moment. Der Knoten mit der ID start ist immer der Einstieg.

"dialogTree": {
 "start": {
 "npcText": "Was kann ich für dich tun?",
 "choices": [
 {
 "text": "Ich brauche Informationen.",
 "next": "info_knoten"
 },
 {
 "text": "Hier ist der Brief für dich.",
 "next": "brief_uebergeben",
 "requireFlag": "brief_gefunden" // Nur sichtbar wenn Flag gesetzt
 },
 {
 "text": "Auf Wiedersehen!",
 "next": null // null = Gespräch endet
 }
 ]
 },

 "info_knoten": {
 "npcText": "Der Schlüssel liegt im alten Turm!",
 "setFlag": "hinweis_erhalten", // Flag beim Betreten
 "choices": [
 { "text": "Danke!", "next": null }
 ]
 }
}
Feld (Knoten)Bedeutung
npcTextWas der NPC sagt
setFlagFlag wird gesetzt sobald dieser Knoten geöffnet wird
flagBranchAutomatische Umleitung je nach Flag-Stand (s.u.)
choicesListe der Antwortmöglichkeiten
Feld (Antwort/Choice)Bedeutung
textDer Text auf dem Antwort-Button
nextID des nächsten Knotens (null = Gespräch endet)
setFlagFlag setzen beim Wählen
givesItemIdDieses Item bekommt der Spieler
requireFlagAntwort nur sichtbar wenn Flag gesetzt
requireFlagNotAntwort nur sichtbar wenn Flag NICHT gesetzt
playCutsceneCutscene abspielen (statt weiter zum nächsten Knoten)

flagBranch: Automatische Umleitung

Wenn der Spieler denselben NPC nach einem wichtigen Ereignis erneut anspricht, soll dieser anders reagieren. Dafür gibt es flagBranch: Wenn eine Flag gesetzt ist, leitet der Spieler automatisch zu einem anderen Knoten um.

"start": {
 "flagBranch": [
 { "flag": "brummi_zurueck", "goto": "nach_brummi" },
 { "flagNot": "quest_aktiv", "goto": "kein_quest" }
 ],
 "npcText": "Ich fahre nicht ohne Brummi!",
 // Wird nur gezeigt wenn KEIN Branch greift
 ...
},
"nach_brummi": {
 "npcText": "BRUMMI! 🎉 Jetzt bin ich bereit!",
 "choices": [
 { "text": "Na dann – ab ins Kino!", "next": null }
 ]
}
Praxisbeispiel: Basti vor und nach der Teddy-Übergabe

Situation: Basti vermisst seinen Teddy. Sobald der Spieler ihn zurückgibt (basti_gluecklich = true), soll Basti beim nächsten Gespräch glücklich reagieren.

Lösung: flagBranch auf dem start-Knoten leitet zu nach_brummi um, sobald basti_gluecklich gesetzt ist. Kein separater Code nötig.

Einrichten im Editor

1
Startknoten anlegen Tab NPCs → NPC → Bereich "💬 Dialog-Baum" → "➕ Knoten hinzufügen". ID: start (Pflicht – das ist der Einstieg).
2
NPC-Text und Antworten füllen Text eingeben, "➕ Antwort hinzufügen" für jede Option. "Weiter zu" wählen.
3
Weitere Knoten anlegen Für jede Abzweigung einen neuen Knoten. Knoten-ID muss mit dem "Weiter zu"-Feld übereinstimmen.
4
flagBranch optional konfigurieren Im Knoten-Editor: gelbe "🔀 flagBranch"-Sektion → "➕ Branch hinzufügen" → Flag + Ziel-Knoten wählen.
💡
Autosave: Der Dialog-Baum-Editor speichert nach 800ms Pause automatisch. Du kannst das Modal jederzeit schließen ohne zu verlieren.

Variablen in Dialog-Bäumen

Sowohl Nodes (was der NPC sagt) als auch Choices (Spieler-Antworten) können Variablen ändern.

👥 NPCs → NPC → Dialog-Knoten bearbeiten → 🔢 Variable beim Betreten ändern
👥 NPCs → NPC → Dialog-Knoten → Antwort → 🔢 Variable bei dieser Wahl
// Node: Mama gibt Geld beim Betreten des Knotens
"geld_geben": {
 "npcText": "Hier sind 8 €! Kauf Mehl, Zucker und Butter.",
 "setFlag": "geld_bekommen",
 "varActions": [{ "name": "geld", "val": 8 }]
}

// Choice: Backzutaten kaufen – kostet Geld, gibt Punkte
"choices": [{
 "text": "Ich kaufe die Backzutaten (5 €)",
 "next": "kaufen",
 "requireVar": { "name": "geld", "op": ">=", "val": 5 },
 "varActions": [
 { "name": "geld", "val": -5 },
 { "name": "punkte", "val": 10 }
 ]
}]
KontextFeldWirkung
Node (NPC-Text)varActionsWird ausgeführt wenn Knoten angezeigt wird
NodegivesItemItem geht ins Inventar beim Betreten
Choice (Spieler-Wahl)varActionsWird ausgeführt wenn Spieler diese Wahl wählt
ChoicerequireVarWahl nur sichtbar wenn Bedingung erfüllt
ℹ️
varActions vs. addVar: varActions ist ein Array – damit kannst du mehrere Variablen auf einmal ändern. addVar ist die Kurzform für genau eine Variable.
🚩
Flags & Bedingungen
Spielzustände merken und Aktionen davon abhängig machen

Was sind Flags?

Eine Flag ist ein einfacher Schalter: entweder ein (true) oder aus (false). Damit kann das Spiel sich merken, was der Spieler schon gemacht hat: eine Tür geöffnet, einen Kampf gewonnen, einen Brief abgegeben.

"flags": {
 "tuer_offen": false,
 "schatz_gefunden": false,
 "quest_aktiv": true // true = Flag startet schon gesetzt
}

Flags setzen und löschen

Flags können an vielen Stellen gesetzt oder gelöscht werden:

WoJSON-FeldWann
usableWith (Objekt)"setFlag": "name"Nach Item-Anwendung
usableWith (Objekt)"clearFlag": "name"Flag wird auf false gesetzt
NPC receivesItems"setFlag": "name"Nach Tausch
Dialog-Wahl (choice)"setFlag": "name"Beim Wählen der Antwort
Dialog-Knoten"setFlag": "name"Beim Betreten des Knotens
onDefeat (NPC)"setFlag": "name"Nach NPC-Besiegung

Automatische Flags

FlagWird automatisch gesetzt wenn…
player_deadSpieler-HP sinkt auf 0 (HP-System aktiviert)
npc_defeated_[id]NPC bei HP-System auf 0 HP gebracht

Flags als Bedingungen verwenden

Fast überall im System kann eine Flag als Bedingung geprüft werden:

FeldBedeutungEinsatzort
requireFlagFlag muss TRUE seinExits, NPC-Tausch, Game Ends, Dialog-Antworten
requireFlagNotSetFlag muss FALSE seinNPC receivesItems
requireFlagFalseFlag muss FALSE seinGame Ends
requireFlagNotFlag muss FALSE seinusableWith (Objekt)
forbidFlagFlag darf NICHT gesetzt seinconditionalNpcs
💡
Flag-Namen dürfen nur Kleinbuchstaben, Zahlen und Unterstriche enthalten. Sprechende Namen helfen enorm: tuer_offen, boss_besiegt, brief_abgegeben.
🎬
Cutscenes
Story-Sequenzen mit Bild, Text, Musik und Übergangseffekten

Was ist eine Cutscene?

Eine Cutscene ist eine Abfolge von Slides – jede mit einem Bild (oder Video), einem Text und optionaler Musik. Der Spieler klickt sich durch und sieht so eine Geschichte, eine Erklärung oder einen dramatischen Moment.

"cutscenes": {
 "wald_intro": [
 {
 "image": "data:image/png;base64,...",
 "text": "Es war einmal ein dunkler Wald...",
 "bgm": "data:audio/mpeg;base64,...",
 "bgmLoop": true,
 "sfx": "snd_abc123", // 💥 Einmal-Effekt beim Erscheinen
 "theme": "dark",
 "transition": "fade"
 },
 {
 "image": "data:image/png;base64,...",
 "text": "Ein Held betrat ihn..."
 }
 ]
}
Slide-EigenschaftTypBeschreibung
imagestringURL, Base64 oder Data-URL (Bild oder Video)
imageLoopbooleanVideo-Loop? (Standard: true)
textstringText-Overlay über dem Bild
bgmstringHintergrundmusik für diese Slide
bgmLoopbooleanMusik loopen? (Standard: true)
sfxstring💥 Soundeffekt, der beim Erscheinen der Slide einmal abgespielt wird – parallel zur Musik (Bibliotheks-ID, Data-URL oder Dateipfad). Kombinierbar mit silence: Musik stoppt und der Effekt spielt – perfekt für einen Blackout („ZISCH!“).
noSkipboolean⛔ Trägt irgendein Slide noSkip: true, ist die gesamte Cutscene nicht überspringbar (Überspringen-Knopf ausgeblendet, ESC gesperrt). Editor: Checkbox „⛔ Nicht überspringbar“ im Cutscene-Kopf. Wichtig, wenn spätere Slides Musik stoppen (🔇 Stille) oder Effekte tragen: Wer überspringt, würde den Stille-Slide nie erreichen – die Musik liefe ungewollt ins Spiel weiter.
themestringTheme für diese Slide (13 verfügbar)
transitionstringÜbergang: fade, slide-left, slide-right, zoom, dissolve
💡
game_intro: Eine Cutscene mit dieser genauen ID spielt automatisch beim Spielstart – perfekt für eine Einleitung!

10 Trigger – überall einsetzbar

Cutscenes können an 10 verschiedenen Stellen ausgelöst werden. Alle sind vollständig im Editor konfigurierbar:

1🎬 Game Intro
Tab: 🎬 Cutscenes → ID "game_intro" anlegen
Wann: Beim Spielstart (automatisch)
2🚪 Ort betreten
Tab: 📍 Orte → Ort → 🎬 Cutscene-Dropdown
Wann: Beim Betreten des Ortes
3💬 NPC-Dialog VOR
Tab: 🗨️ NPCs → NPC bearbeiten → Cutscene VOR Dialog
Wann: Bevor der Dialog erscheint
4💬 NPC-Dialog NACH
Tab: 🗨️ NPCs → NPC bearbeiten → Cutscene NACH Dialog
Wann: Wenn Spieler "Zurück" klickt
5🏁 Spielende
Tab: 🏁 Enden → Ende bearbeiten → Cutscene vor Ende
Wann: Bevor Sieg/Niederlage-Meldung
6🔧 Objekt verwendet
Tab: 📍 Orte → Objekt → Item-Verwendung → Cutscene
Wann: Nach erfolgreicher Item-Anwendung
7🎁 NPC gibt Item
Tab: 🗨️ NPCs → Gibt Items → Item → Cutscene
Wann: Nach Itemerhalt vom NPC
8🔄 NPC Tausch
Tab: 🗨️ NPCs → Nimmt Items → Item → Cutscene
Wann: Nach erfolgreichem Tausch
9⚗️ Rezept gecraftet
Tab: ⚗️ Rezepte → Rezept → Cutscene-Feld
Wann: Nach erfolgreicher Kombination
10🚩 Flag-basiert (Ort)
Tab: 📍 Orte → 🎬 Bedingte Cutscenes → ➕ Trigger
Wann: Ort betreten + bestimmte Flag gesetzt

JSON für Flag-basierten Trigger (Nr. 10)

"cutsceneTriggers": [{
 "requireFlag": "schatz_gefunden",
 "playCutscene": "siegesfeier",
 "playOnce": true
}]
💡
playCutsceneOnce: true sollte fast immer gesetzt sein – sonst spielt die Cutscene jedes Mal wenn der Spieler den Ort betritt oder den NPC anspricht.
⚗️
Rezepte & Crafting
Zwei Items kombinieren – ein neues entsteht

So funktioniert Crafting

Der Spieler wählt im Inventar zwei Items aus und klickt "Kombinieren". Gibt es ein passendes Rezept, verschwinden beide Items und das Ergebnis erscheint. Gibt es keins – passiert nichts.

"recipes": [
 {
 "item1Id": "eimer_wasser", // Item-ID (empfohlen)
 "item2Id": "seife",
 "resultId": "eimer_seifenwasser",
 "message": "Du mischst die Seife ins Wasser – es schäumt!",
 "playCutscene": "misch_animation", // Optional
 "playCutsceneOnce": true,
 "sfx": "snd_1234_abc" // 🔊 Sound aus der Bibliothek (optional)
 }
]
Praxisbeispiel: Seifenschwamm für die Autowäsche

Schritt 1: Eimer + Wasserhahn (givesItemId) → Befüllter Wassereimer

Schritt 2: Wassereimer + Seife (Rezept) → Seifenwasser

Schritt 3: Schwamm + Seifenwasser (Rezept) → Seifenschwamm

Schritt 4: Seifenschwamm auf Auto anwenden → Auto ist sauber 🚗✨

💡
Das Rezept ist reihenfolge-unabhängig. Item1 + Item2 = Item2 + Item1.
🏁
Spielenden
Sieg und Niederlage – mit Cutscene, Teleport und Meldung

Aufbau einer Endbedingung

Ein Ende besteht aus einer Bedingung (was muss eingetreten sein?) und optional zusätzlichen Bedingungen, einer Cutscene, einem Teleport und der Abschlussmeldung.

"gameEnds": {
 "win": [{
 "type": "flag", // item | flag | location
 "value": "papa_informiert", // ID oder Name je nach Typ
 "requireFlag": "basti_gluecklich", // Zusatzbedingung
 "playCutscene": "fahrt_ins_kino", // Cutscene davor
 "teleportTo": "kino", // Ort nach Cutscene
 "message": {
 "title": "🎬 ZOO VERRÜCKT 3!",
 "message": "Du hast den Samstag gerettet!",
 "buttonText": "🍿 Film ab!"
 }
 }],
 "lose": [{
 "type": "flag",
 "value": "player_dead",
 "message": "Du bist gestorben..."
 }]
}

Alle Felder einer Endbedingung

FeldPflicht?Beschreibung
type✅ Jaitem = Spieler hat Item, flag = Flag gesetzt, location = Spieler am Ort
value✅ JaItem-ID, Flag-Name oder Ort-ID
requireFlag○ Opt.Zusätzlich: diese Flag muss TRUE sein
requireFlagFalse○ Opt.Zusätzlich: diese Flag muss FALSE sein
playCutscene○ Opt.Cutscene vor der Meldung abspielen
teleportTo○ Opt.Nach der Cutscene zu diesem Ort wechseln
message✅ JaString oder Objekt mit title/message/buttonText
image○ Opt.Bild in der Abschlussmeldung

Reihenfolge der Ereignisse

1
Bedingung erfüllt – Item erhalten / Flag gesetzt / Ort betreten
2
Cutscene startet (falls hinterlegt) – Spieler klickt "Fertig"
3
Teleport (falls hinterlegt) – Spieler sieht den Zielort
4
Sieg/Niederlage-Meldung erscheint mit Konfetti und Neustart-Button
⚠️
Wichtig: Die erste erfüllte Bedingung in der Liste gewinnt. Die Reihenfolge bestimmt die Priorität – daher kannst du spezifische Bedingungen weiter oben eintragen und einen allgemeinen Fallback (z.B. player_dead ohne requireFlag) weiter unten.

Tod-Szenarien mit verschiedenen Meldungen

"lose": [
 {
 "type": "flag", "value": "player_dead",
 "requireFlag": "vergiftet",
 "message": "Das Gift war zu stark..."
 },
 {
 "type": "flag", "value": "player_dead",
 "requireFlag": "im_kampf",
 "message": "Du wurdest im Kampf besiegt..."
 },
 {
 "type": "flag", "value": "player_dead",
 "message": "Du bist gestorben." // Fallback
 }
]
🎯
Aufgaben-System
Fortschrittsbalken · Geheimziele · Benachrichtigungen

Was ist das Aufgaben-System?

Mit dem Aufgaben-System kannst du dem Spieler eine sichtbare Liste von Zielen mit Fortschrittsbalken anzeigen. Jedes Ziel ist an ein Flag gebunden – sobald das Flag im Spielverlauf gesetzt wird, gilt das Ziel als erfüllt und wird visuell abgehakt.

ℹ️
Das System ist vollständig optional. Wenn im Editor keine Ziele definiert sind, erscheint nichts im Player. Hinweis: Dies ist das aktuelle, im Player voll funktionierende System. Ein früheres „Quests“-Feld (siehe Kapitel 27) war nie implementiert und ist durch dieses Aufgaben-System abgelöst.

Einrichten im Editor

Tab 🎨 Anzeige → Abschnitt 🎯 Aufgaben / Ziele.

EinstellungBeschreibung
AktivierenCheckbox – schaltet das System global ein/aus
TitelAnzeigename der Sektion (z.B. „🎯 Meine Aufgaben")
PositionSidebar · Sidebar aufklappbar · Modal (🎯-Button im Header)
ZielePro Ziel: Aufgaben-Text + Flag-Dropdown + optional Geheimziel
GeheimzielCheckbox + Platzhaltertext (z.B. „???") bis Flag erfüllt

JSON-Struktur

{
 "displaySettings": {
 "goalsEnabled": true,
 "goalsTitle": "🎯 Aufgaben",
 "goalsPosition": "sidebar", // "sidebar" | "accordion" | "modal"
 "goals": [
 {
 "text": "Pizza bestellen",
 "flag": "pizza_bestellt",
 "secret": false
 },
 {
 "text": "Geheimende finden",
 "flag": "geheim_ende",
 "secret": true,
 "secretLabel": "???" // bis Flag erfüllt
 },
 {
 "text": "Den Kater gestreichelt",
 "flag": "kater_gestreichelt",
 "hiddenUntilDone": true // 🫥 taucht erst NACH Erfüllung auf
 }
 ]
 }
}
🔒 Geheimziel vs. 🫥 „Erst sichtbar, wenn erfüllt“ – der Unterschied: Ein Geheimziel (secret) steht von Anfang an in der Liste, zeigt aber nur den Platzhalter (z.B. ???) – der Spieler weiß, dass es etwas zu entdecken gibt. Ein Ziel mit hiddenUntilDone existiert für den Spieler gar nicht, bis es erfüllt ist: Es steht nicht in der Liste und zählt nicht im Fortschrittsbalken. Erst mit dem Flag taucht es abgehakt auf (mit Benachrichtigung) – wie ein verstecktes Achievement („Ach, das war auch eine Aufgabe!“). Im Editor: Checkbox 🫥 Erst sichtbar, wenn erfüllt am jeweiligen Ziel.
⛓️ Nacheinander freischalten (Sequenz-Modus): Mit "goalsSequential": true (Editor: Checkbox ⛓️ Nacheinander freischalten über der Ziele-Liste) erscheinen die Aufgaben der Reihe nach: Ein Ziel wird erst sichtbar, wenn das vorherige erfüllt ist – die Reihenfolge in der Liste ist die Kette. Einzelne Ziele lassen sich per "alwaysVisible": true (Editor: 📌 Immer sichtbar) von der Kette ausnehmen, z.B. ein Dauer-Ziel wie „Alle Münzen finden“. Die Regeln im Zusammenspiel: Erfüllte Ziele sind immer sichtbar (abgehakt) · 🫥 gewinnt über 📌 und die Kette · 🫥- und 📌-Ziele stehen außerhalb der Kette und blockieren sie nicht · der Fortschrittsbalken zählt nur sichtbare Ziele.

Die drei Anzeigeoptionen

PositionVerhaltenIdeal für
sidebarImmer sichtbar über dem Inventar, mit FortschrittsbalkenSpiele mit vielen Zielen
accordionSidebar, aber eingeklappt – Klick auf Titel öffnet/schließt, Anzahl im TitelPlatzsparend bei langen Ziellisten
modalUnsichtbar – 🎯-Button im Header öffnet Vollbild-Übersicht mit BalkenSauberes UI ohne Sidebar-Platz

Features im Player

FeatureBeschreibung
✅ Ziele abhakenErfüllte Ziele werden grün mit Durchstreichung angezeigt
📊 FortschrittsbalkenZeigt z.B. „2/5" + visuellen Balken
🔒 GeheimzieleZeigen „???" bis das Flag erfüllt ist – dann erscheint der echte Text
🔔 BenachrichtigungGrüne Notification oben: „🎯 Ziel erreicht: Pizza bestellen"
💡
Die Reihenfolge der Ziele im Editor bestimmt die Anzeigereihenfolge im Player. Setze wichtige Hauptziele nach oben, optionale Geheimziele nach unten.
🗣️
Text-to-Speech (TTS)
Hover-gesteuertes Vorlesen – der Spieler bestimmt das Tempo

Konzept

ABP nutzt die im Browser eingebaute Web Speech API (kein Internet nötig, DSGVO-konform). Fährt der Spieler mit der Maus über ein Element, wird dessen Text vorgelesen. Der Spieler steuert vollständig was und wann vorgelesen wird.

ℹ️
Beste Browser-Unterstützung: Chrome (Google-Stimme), Edge (Microsoft Katja), Firefox (OS-Stimmen). Die Stimme und Geschwindigkeit werden dauerhaft im localStorage gespeichert.

Was wird vorgelesen?

ElementVorgelesen beiText
Ortsname + BeschreibungHoverName + vollständige Beschreibung
Raumobjekte, Items, NPCsHoverName des Elements
AusgängeHoverRichtung oder benutzerdefinierter Name
Dialog-Text (NPC)HoverVollständiger Dialog-Text
Dialog-ChoicesHoverText der Antwortmöglichkeit
Inventar-AktionsbuttonsHover + automatisch beim Erscheinen„Benutzen", „Ziel wählen", „Kombinieren"
🎯 Tipps/ZieleHoverZiel-Text + „erledigt" wenn abgehakt
Fortschrittsanzeige (1/3)Hover + automatisch bei Änderung„Fortschritt: 1 von 3"
🏆 Ziel erreichtAutomatisch„Ziel erreicht: [Text]"
🎒 Inventar-ÜberschriftHover„Inventar"
🔢 Variablen-HUDHover + automatisch bei Wertänderung„Energie: plus 4. Jetzt 10 von 10."
❤️ HP-AnzeigeHover + automatisch bei HP-Änderung„Lebenspunkte: 14 von 20"
⏱️ Spielzeit-HUDHover„Spielzeit: 3 Minuten und 12 Sekunden"
⚙️ Einstellungen (alle Elemente)HoverBeschriftung des Elements
🏆 Trophäe freigeschaltetAutomatisch„Trophäe freigeschaltet: [Titel]"
🎬 Cutscene-SlideAutomatischSlide-Text beim Erscheinen
💡
Hover-TTS hat einen 300ms Debounce – schnelles Durchfahren mehrerer Elemente löst kein Vorlesen aus.

Automatische Stimmen-Auswahl

Beim ersten Start wählt ABP automatisch die beste verfügbare deutsche Stimme nach dieser Priorität:

PrioritätBrowserStimme
1ChromeGoogle Deutsch (Online)
2EdgeMicrosoft Katja (Neural, Online)
3AlleAndere Microsoft-Online-Stimmen (de-DE)
4FallbackBeste verfügbare Offline-Stimme (Hedda, Stefan)

Die manuelle Wahl des Spielers wird in localStorage gespeichert (abp_tts_voice, abp_tts_rate) und beim nächsten Start automatisch geladen. Das Dropdown im Einstellungsmenü zeigt 🌐 Online-Stimmen und 📴 Offline-Stimmen.

Zeitansagen in natürlichem Deutsch

Zeiten werden nicht als 01:23 (TTS: „1 Uhr 23") sondern als natürliche Sprache ausgegeben:

// Beispiele für TTS-Zeitansagen
17 Sekunden // statt „00:17"
1 Minute und 23 Sekunden // statt „01:23"
1 Stunde und 5 Minuten und 30 Sekunden

Designer-Einstellungen

⚙️ Features → 🗣️ Text-to-Speech → Standard: an/aus · Emojis filtern
JSON-FeldStandardBeschreibung
tts.defaultEnabledfalseTTS beim Spielstart sofort aktiv
tts.stripEmojistrueEmojis aus vorgelesenen Texten entfernen
🔢
Variablen & Zähler
Geld, Punkte, Energie – Werte die sich dynamisch verändern

Was sind Variablen?

🧩
Neu in v5.0 — Tab freischalten: Der 🔢-Variablen-Tab ist im Editor ab Werk ausgeblendet, damit die Werkzeugleiste schlank bleibt. Einschalten: Tab „⚙️ Features" → Akkordeon „🔢 Variablen-System" → Häkchen setzen. Sobald dein Spiel Variablen enthält, bleibt der Tab von selbst sichtbar.

Variablen sind benannte Zahlenwerte die sich während des Spiels verändern. Im Gegensatz zu Flags (true/false) können Variablen beliebige ganzzahlige Werte annehmen – perfekt für Geld, Punkte, Energie, Schlüsselanzahl oder jeden anderen Zähler.

💡
Faustregel: Wenn etwas nur an/aus ist → Flag. Wenn etwas zählt oder sich verändert → Variable.

Definition in der JSON

{
 "variables": {
 "geld": {
 "default": 0, // Startwert
 "min": 0, // Minimum (optional)
 "max": 50, // Maximum (optional)
 "label": "💰 Geld", // Anzeigename im HUD
 "showInHUD": true // In Sidebar anzeigen
 }
 }
}

Mit showInHUD: true erscheint die Variable in der Spieler-Sidebar. Ist ein max-Wert gesetzt, wird ein Fortschrittsbalken angezeigt.

Aktionen – Variablen verändern

AktionBedeutungBeispiel
addVarAddiert einen Wert (negativ = subtrahieren) – eine Variable{"name":"geld","val":8}
setVarSetzt einen fixen Wert – eine Variable{"name":"punkte","val":0}
varActionsMehrere Variablen auf einmal – Array von Aktionen[{"name":"geld","val":-5},{"name":"punkte","val":10}]
// Eine Variable: addVar
"addVar": { "name": "geld", "val": 8 }

// Mehrere Variablen gleichzeitig: varActions-Array
"varActions": [
 { "name": "geld", "val": -5 },
 { "name": "punkte", "val": 10 }
]
💡
Faustregel: Wenn du nur eine Variable änderst → addVar. Wenn du zwei oder mehr änderst → varActions-Array.

Editor-Wege – Wo stelle ich was ein?

KontextEditor-PfadWas erscheint
Item benutzen (Apfel → +4 Energie)📦 Objekte → Item → ☑️ „Sofort benutzen" → 🔢 VariableDropdown + Wert
Objekt-Aktion (Kühlschrank → -1 Energie)🗺️ Orte → Objekt → Aktion → 🔢 VariableBedingung + Aktion
Dialog-Node (Mama → +8 Geld)👥 NPCs → NPC → Knoten → 🔢 Variable beim BetretenDropdown + Wert
Dialog-Choice (Spieler-Wahl → -5 Geld)👥 NPCs → NPC → Knoten → Antwort → 🔢 VariableDropdown + Wert

Bedingungen – Variablen prüfen

opBedeutung
>=Größer gleich (Standard)
<=Kleiner gleich
==Genau gleich
!=Ungleich
>Größer
<Kleiner
"requireVar": { "name": "geld", "op": ">=", "val": 8 }

Wo funktionieren Variablen?

KontextAktionenBedingungen
usableWith (Objekt-Aktion)✅ addVar, setVar✅ requireVar
NPC-Tausch (receivesItems)✅ addVar, setVar
Dialog-Nodes & Choices✅ addVar, setVar
onDefeat (Kampf-Niederlage)✅ addVar, setVar
Ausgänge (conditionalExits)✅ requireVar
Konditionale Bilder✅ requireVar
Konditionale NPCs✅ requireVar

Beispiel 1: Taschengeld kauft Pizza

Sophie startet mit 3€. Mama gibt ihr 5€. Die Pizza kostet 8€.

// Variable definieren
"geld": { "default": 3, "min": 0, "label": "💰 Geld", "showInHUD": true }

// NPC Mama – Dialog gibt Geld
"dialogTree": {
 "start": {
 "text": "Hier sind 5€ Taschengeld!",
 "addVar": { "name": "geld", "val": 5 }
 }
}

// Objekt Handy – Pizza bestellen, nur mit genug Geld
"usableWith": [{
 "itemName": "Handy",
 "requireVar": { "name": "geld", "op": ">=", "val": 8 },
 "success": "Du bestellst eine Pizza! (-8€)",
 "addVar": { "name": "geld", "val": -8 },
 "setFlag": "pizza_bestellt"
}]

Beispiel 2: Punkte bei Kampf-Sieg

Für jeden besiegten Gegner gibt es 50 Punkte – direkt im onDefeat-Block.

"punkte": { "default": 0, "label": "⭐ Punkte", "showInHUD": true }

"usableWith": [{
 "itemName": "Schwert",
 "damage": 30,
 "onDefeat": {
 "message": "Drache besiegt! +50 Punkte!",
 "addVar": { "name": "punkte", "val": 50 },
 "setFlag": "drache_besiegt"
 }
}]
ℹ️
onDefeat unterstützt addVar und setVar neben setFlag, givesItem und teleportTo. HP und Skill-Level bleiben eigene Systeme – Variablen ergänzen sie.

Beispiel 3: Energie-Balken

Rennen kostet Energie, Schlafen lädt auf. Ohne Energie ist der Wald-Ausgang gesperrt.

"energie": { "default": 10, "min": 0, "max": 10, "label": "⚡ Energie", "showInHUD": true }

// Bett: Energie aufladen
{ "actionLabel": "Schlafen", "success": "Du schläfst. (+5⚡)", "addVar": { "name": "energie", "val": 5 } }

// Ausgang: nur mit Energie > 0
{ "direction": "norden", "targetLocation": "wald",
 "requireVar": { "name": "energie", "op": ">", "val": 0 } }

Variablen vs. Flags vs. HP

SituationEmpfehlung
Tür ist offen / NPC wurde gesehenFlag
Spieler-Lebenspunkte (Kampfsystem)HP-System (playerHP)
Kampf-Skill / LevelSkill-System (combatSkill)
Geld, Punkte, SchlüsselanzahlVariable
Energie, Hunger, MüdigkeitVariable mit min/max
erzeugt eine einzige HTML mit allem eingebettet
💾
Speichern & Laden
Spielstände sichern und wiederherstellen

3 Speicherslots im Einstellungen-Menü

ABP bietet ein eingebautes Speicher-System ohne Server oder Backend. Alle Spielstände liegen im localStorage des Browsers – funktioniert lokal und auf dem Webserver.

⚙️ Einstellungen → 💾 Spielstand → Slot 1/2/3
ButtonFunktion
💾 SpeichernAktuellen Spielstand in diesen Slot schreiben
📂 LadenSpielstand aus Slot wiederherstellen (Bestätigung nötig)
🗑️ LöschenSlot leeren

Leere Slots zeigen nur den 💾-Button. Belegte Slots zeigen Ortsname und Datum/Uhrzeit des letzten Speichervorgangs.

Was wird gespeichert?

Der komplette gameState wird gesichert:

GespeichertBedeutung
Aktueller OrtcurrentLocation
InventarAlle Items mit Mengen
FlagsAlle gesetzten/nicht gesetzten Flags
VariablenGeld, Energie, Punkte etc.
HP & SkillLebenspunkte und Kampf-Level
NPC-GesundheitTrefferpunkte aller Gegner

Technische Details

Der localStorage-Schlüssel ist spieltitelgebunden – verschiedene Spiele überschreiben sich nicht gegenseitig:

// Schlüssel-Format
abp_save_{spieltitel}_slot1
abp_save_{spieltitel}_slot2
abp_save_{spieltitel}_slot3

// Beispiel: "Sophies großer Tag" → Slot 2
abp_save_Sophies_grosser_Tag_slot2
ℹ️
localStorage ist browser- und gerätespezifisch. Ein Spielstand auf dem Desktop ist nicht auf dem Handy verfügbar. Wenn der Browser-Cache geleert wird, gehen Spielstände verloren.
💡
Für Workshops: Erkläre den Teilnehmenden, dass die Spielstände im Browser gespeichert sind – nicht auf dem Schulserver. Nach einem „Alles löschen im Browser" wären sie weg.
🏆
Achievements & Trophäen
Automatische Belohnungen für besondere Leistungen

Was sind Achievements?

🧩
Neu in v5.0 — Tab freischalten: Der 🏆-Achievements-Tab ist ab Werk ausgeblendet. Einschalten: Tab „⚙️ Features" → Akkordeon „🏆 Achievements" → Häkchen setzen. Verwendet dein Spiel bereits Achievements, ist der Tab automatisch da.

Achievements sind unsichtbare Bedingungen die der Designer vorab definiert. Sobald ein Spieler die Bedingung erfüllt, erscheint automatisch eine goldene Toast-Meldung – einmalig, 5 Sekunden sichtbar, kein Klicken nötig. Mit aktiviertem TTS wird die Trophäe auch vorgelesen.

🏆 Achievements → ➕ Neue Trophäe → ID · Titel · Beschreibung · Bedingungen

JSON-Format

"achievements": {
 "sparfuchs": {
 "title": "💰 Sparfuchs!",
 "message": "Du hast noch 5 € übrig nach dem Einkauf.",
 "requireFlag": "zutaten_gekauft",
 "requireVar": { "name": "geld", "op": ">=", "val": 5 }
 },
 "blitzlieferung": {
 "title": "⚡ Blitzlieferung!",
 "message": "Kuchen in unter 3 Minuten fertig!",
 "requireFlag": "kuchen_uebergeben",
 "requireMaxTime": 180
 }
}
FeldBedeutung
titleÜberschrift der Toast-Meldung
messageBeschreibung (optional)
requireFlagFlag muss gesetzt sein
requireFlagNotFlag darf NICHT gesetzt sein
requireVarVariable-Bedingung: {"name","op","val"}
requireItemItem-Name muss im Inventar sein
requireMaxTimeSpielzeit in Sekunden darf nicht überschritten werden
requireMinTimeMindest-Spielzeit in Sekunden (für Gründlichkeit)
ℹ️
Alle gesetzten Bedingungen müssen gleichzeitig erfüllt sein. Nicht gesetzte Felder werden ignoriert.

Übersicht im Player

Achievements sind nicht nur Toast-Meldungen – der Spieler kann sie jederzeit einsehen:

WoWas
⚙️ EinstellungsmenüButton 🏆 Meine Trophäen – erscheint automatisch wenn das Spiel Achievements hat
Spielende (Sieg/Niederlage)Button 🏆 Trophäen ansehen – optional, steuerbar über achievementsShowAtEnd
Trophäen-ModalFortschrittsbalken (z.B. 3 von 5 = 60%) · erreichte Trophäen gold · offene mit 🔒
💡
Nach dem Schließen der Trophäen-Ansicht am Spielende kehrt der Spieler automatisch zur Siegmeldung zurück – er kann das Spiel normal beenden.
⚙️ Features → 🏆 Achievements → ☑️ Am Spielende automatisch anzeigen

Praktische Beispiele

// Trophäe für Vollständigkeit: alle Räume besucht
"entdecker": {
 "title": "🗺️ Entdecker!",
 "message": "Du hast jeden Winkel erkundet.",
 "requireFlag": "alle_raeume_besucht"
}

// Trophäe für hohe Punktzahl
"punktekoenig": {
 "title": "⭐ Punktekönig!",
 "requireVar": { "name": "punkte", "op": ">=", "val": 100 }
}

// Trophäe für Speedrun (unter 2 Minuten)
"speedrunner": {
 "title": "🚀 Speedrunner!",
 "requireFlag": "spiel_gewonnen",
 "requireMaxTime": 120
}

// Trophäe für Gründlichkeit (mindestens 5 Minuten gespielt)
"gruendlich": {
 "title": "🔍 Gründlich!",
 "requireFlag": "spiel_gewonnen",
 "requireMinTime": 300
}
💡
Achievements sind ideal für Workshops: Teilnehmende können gezielt auf versteckte Trophäen spielen ohne dass es den Spielfluss stört.
⏱️
Spielzeit-Tracking
Spielzeit messen, anzeigen und für Achievements nutzen

Wie es funktioniert

ABP misst die Spielzeit automatisch im Hintergrund – ab dem Moment wenn das Spiel startet bis zum Spielende. Die Zeit läuft auch wenn der Spieler das ⚙️-Menü öffnet. Beim Neustart wird die Uhr zurückgesetzt.

💡
Die Spielzeit ist immer verfügbar – auch wenn sie nicht angezeigt wird. Sie kann jederzeit in Achievements als Bedingung genutzt werden.

Timer in der Sidebar anzeigen

⚙️ Features → Anzeige → ☑️ Timer in der Sidebar anzeigen

Wenn aktiviert, erscheint ein grüner ⏱️ Spielzeit-Kasten in der Sidebar. Das Format ist MM:SS (unter einer Stunde) oder H:MM:SS (ab einer Stunde). Mit TTS vorlesbar durch Hover.

In der JSON: "displaySettings": { "showTimerInHUD": true }

Spielzeit am Spielende

Die finale Spielzeit erscheint automatisch in der Sieg- oder Niederlage-Meldung – als grüner Balken unterhalb des Textes. Das kann nicht deaktiviert werden. Mit TTS wird die Zeit in natürlicher Sprache vorgelesen:

// Anzeige: 01:23
// TTS liest: "Spielzeit: 1 Minute und 23 Sekunden"

Spielzeit in Achievements

Die Zeit lässt sich als Bedingung in Achievements nutzen – für Speedrun- oder Gründlichkeits-Trophäen:

// Speedrun: Spiel in unter 3 Minuten gewonnen
"speedrunner": {
 "title": "🚀 Speedrunner!",
 "message": "Spiel in unter 3 Minuten abgeschlossen!",
 "requireFlag": "kuchen_uebergeben",
 "requireMaxTime": 180
}

// Gründlich: Mindestens 10 Minuten gespielt
"gruendlich": {
 "title": "🔍 Gründlicher Entdecker!",
 "requireFlag": "kuchen_uebergeben",
 "requireMinTime": 600
}
FeldBedeutungEinheit
requireMaxTimeSpielzeit darf diesen Wert nicht überschreitenSekunden
requireMinTimeSpielzeit muss mindestens diesen Wert erreicht habenSekunden
ℹ️
Zeitangaben immer in Sekunden: 60 = 1 Minute, 300 = 5 Minuten, 3600 = 1 Stunde.
🎨
Themes & Darstellung
Stimmung durch visuelle Gestaltung

Verfügbare Themes

Theme-IDBeschreibungTipp für
modernHell, bunt, Comic Sans – StandardTeilnehmende, Casual-Games
darkDunkler Hintergrund, dezentKrimis, Thriller
lightSehr hell, cleanAlltag, Schule
classicRetro-Sepia, Paper-TexturKlassische Adventures
cyberpunkNeon-Glow, schwarzSci-Fi, Dystopie
fantasyPergament, BrauntöneMittelalter, Magie
jungleDunkelgrün, organischNatur, Dschungel
spaceDunkles Lila, SterneWeltraum, Zukunft
undergroundGrau, cave-artigDungeon, Höhlen
minecraftPixelig, BlockyTeilnehmende, Pixel-Art
retroGrüner CRT-Monitor-Look8-Bit-Ästhetik
lcarsStar Trek LCARS-InterfaceSci-Fi, Star Trek
kawaiiPastellrosa, runde Ecken, Punkte-MusterNiedlich, Teilnehmende, Manga
💡
Jeder Ort kann ein eigenes Theme haben – damit wechselt die Stimmung automatisch beim Raumwechsel. Zum Beispiel: normale Orte im classic-Theme, der Endbosskampf plötzlich in cyberpunk.

Anzeige-Einstellungen (displaySettings)

"displaySettings": {
 // ── Inventar ──────────────────────────────────────────────
 "inventoryPosition": "right", // right | left | bottom
 "allowInventoryChange": true,
 "inventoryHiddenAtStart":false,
 "unlockInventoryItemId": "",
 "inventoryLayout": "vertical", // horizontal | vertical
 "inventoryColumns": "1",
 "inventoryWidth": "300",

 // ── Thumbnails ────────────────────────────────────────────
 "thumbSizeInventory": 70,
 "thumbSizeRoomObjects": 80,
 "thumbSizeNPCs": 80,
 "thumbSizeModal": 300,

 // ── Layout ────────────────────────────────────────────────
 "roomLayout": "horizontal",
 "compactMode": "normal",
 "locationImageSize": "full", // hidden | small | medium | full
 "containerMaxWidth": 1400,
 "showObjectText": true,
 "showNPCText": true,
 "showInventoryText": true,
 "hideEmptySectionTitles":false,

 // ── 3-Wege-Spielmodus ──────────────────────────────────────
 "parserEnabled": true,
 "textOnlyMode": false,
 "textModeImages": true,
 "terminalWidth": "full", // full | 600px | 700px | 800px …
 "showModeGrafik": true,
 "showModeParser": true,
 "showModeText": true,

 // ── HP-System ─────────────────────────────────────────────
 "playerHPEnabled": false,
 "playerStartHP": 100,
 "playerMaxHP": 100,
 "hpSectionTitle": "❤️ Spieler",
 "hpUnit": "HP",

 // ── Skill-System ──────────────────────────────────────────
 "skillSystemEnabled": false,
 "skillStartValue": 0,
 "skillMaxValue": 100,
 "skillSectionTitle": "⭐ Erfahrung",
 "skillLabel": "XP",

 // ── Aufgaben-System ────────────────────────────────────────
 "goalsEnabled": false,
 "goalsTitle": "🎯 Aufgaben",
 "goalsPosition": "sidebar", // sidebar | accordion | modal
 "goals": [
 { "text": "Ziel-Text", "flag": "flag_name", "secret": false }
 ]
}
 

Layout-Engine – HUD & Inventar positionieren

Mit der Layout-Engine können HUD (Status-Sidebar mit HP, Zielen, Skill) und Inventar frei positioniert werden: links, rechts, oben, unten oder ausgeblendet. Das Layout wird in displaySettings definiert und ist abwärtskompatibel – fehlen die Felder, nutzt der Player das klassische Standard-Layout.

JSON-Format
"displaySettings": {
  "containerMaxWidth": "1400",
  "containerMaxHeight": "700",
  "hud": {
    "position": "left",       // left | right | top | bottom | hidden
    "size": "220",            // Breite in px (bei left/right) oder Höhe (top/bottom)
    "sections": ["hp", "goals", "skill"]  // Sichtbare HUD-Elemente
  },
  "inventory": {
    "position": "right",      // left | right | top | bottom | hidden
    "size": "280",            // Breite in px
    "layout": "list"          // list | grid2 | row
  }
}
FeldWerteBedeutung
hud.positionleft · right · top · bottom · hiddenWo HUD erscheint
hud.sizeZahl als String z.B. "220"Breite (side) oder Höhe (top/bottom)
hud.sections["hp","goals","skill","timer"]Angezeigte HUD-Elemente
inventory.positionleft · right · top · bottom · hiddenWo Inventar erscheint
inventory.sizeZahl als String z.B. "280"Breite der Inventar-Sidebar
inventory.layoutlist · grid2 · rowDarstellung der Items im Inventar
💡
Spieler-Freiheit: Der Spieler kann die Inventar-Position in den Einstellungen ändern (sofern allowInventoryChange: true). Die HUD-Position ist vom Designer fixiert und kann nur über das JSON geändert werden.
🛠️
Layouter-Tool: Das optionale Layouter-Tool (layouter.html) ermöglicht die visuelle Konfiguration aller Layout-Einstellungen mit Live-Vorschau. Das fertige JSON kann direkt in die Game-JSON exportiert oder im Player getestet werden.
🖼️
Konditionelle Bilder
Bilder die sich je nach Spielzustand automatisch ändern – bei Orten und Items

Was sind konditionelle Bilder?

Jeder Ort hat ein Standard-Bild. Zusätzlich können beliebig viele konditionelle Bilder definiert werden, die das Standard-Bild ersetzen sobald ein Flag-Kriterium erfüllt ist. Der Player prüft die Liste von oben nach unten – das erste passende Bild gewinnt.

ℹ️
Das Bild wechselt sofort nach einer NPC-Tausch-Interaktion – kein Ortswechsel nötig. Alle Formate werden unterstützt: JPG · PNG · GIF · WebP · AVIF · WebM · MP4.

Im Editor einstellen

Ort auswählen → Tab 🖼️ Standard für das Basis-Bild, dann Tab 🔀 Konditional für flagabhängige Bilder.

Pro konditionellem Bild zwei optionale Bedingungen:

FeldBedeutung
requireFlagBild erscheint nur wenn dieses Flag gesetzt ist
forbidFlagBild erscheint nur wenn dieses Flag nicht gesetzt ist
imageLoopBoolean: Video/GIF wiederholen? Standard: true – gilt pro konditionalem Eintrag unabhängig vom Standard-Bild

Praxisbeispiel: Pizza-Katastrophe – Haustür

Drei Zustände, drei verschiedene Bilder – alles automatisch:

JSON-Struktur (Ort „Haustür")
"tuer": {
 "name": "Haustür",
 "image": "haustuer_leer.jpg", // Bild A – Standard
 "conditionalImages": [
 {
 "image": "haustuer_pizza_weg.jpg", // Bild C – Bote weg
 "requireFlag": "pizza_bekommen" // ← geprüft zuerst!
 },
 {
 "image": "haustuer_marco.jpg", // Bild B – Bote wartet
 "requireFlag": "pizza_bestellt"
 }
 ]
}
💡
Reihenfolge ist entscheidend! Bild C muss vor Bild B stehen. Wenn pizza_bekommen gesetzt ist, gilt immer auch pizza_bestellt – käme B zuerst, würde C nie angezeigt.
Zustandpizza_bestelltpizza_bekommenBild
SpielstartA – leere Tür
Pizza bestelltB – Marco wartet
Pizza bezahltC – Marco weg, Pizza in Hand

Wann werden Flags gesetzt?

Das Flag pizza_bestellt wird im Telefon-Objekt via usableWith → setFlag gesetzt. Das Flag pizza_bekommen wird im NPC Pizza-Bote Marco via receivesItems → setFlag gesetzt – sobald der Spieler 8 Euro oder Kekse übergibt. Der Player erkennt Flags aus allen Quellen:

  • usableWith → setFlag (Objekt-Aktionen)
  • receivesItems → setFlag (NPC-Tausch) ← pizza_bekommen
  • dialogTree → setFlag (Dialog-Bäume)
🎛️
3-Wege-Spielmodus
Grafik, Parser und Nur-Text – alles in einer Engine · plus der QR-Modus

Die drei Modi

ModusSteuerungDarstellungIdeal für
🖼️ GrafikMausklick / TastaturBilder, Karten, ButtonsEinsteiger, Teilnehmende
⌨️ ParserFreitext + KlickGrafik + Parser-LeisteGemischte Zielgruppe
📟 Nur-TextFreitext-BefehleTerminal, scrollendes LogKlassische IF, Zork-Stil
📷
Und der vierte: der QR-Modus. Er reiht sich in die Familie ein — aber er ist anders geartet. Grafik, Parser und Nur-Text sind Darstellungs-Modi: dasselbe Spiel, andere Haut. Man kann sie live umschalten, weil sich an der Lösbarkeit nichts ändert.

Der QR-Modus (Kapitel 28) ändert dagegen, was der Spieler körperlich tun muss: Er verlangt einen Scan am echten Ort. Deshalb gibt es ihn bewusst NICHT als Live-Umschalter — das wäre ein Schummel-Knopf (QR aus → alle Tore auf → vom Sofa gewinnen).
Eingeschaltet wird er im Editor: Tab 🎨 Anzeige → 📷 QR-Modus.

Der Spieler kann jederzeit umschalten – der Spielstand bleibt erhalten. Der Designer legt im Editor fest welche Buttons überhaupt sichtbar sind.

Im Editor konfigurieren

Tab 🎨 Anzeige → Abschnitt „📟 Nur-Text-Modus":

EinstellungBeschreibung
Nur-Text-Modus aktivierenStartet das Spiel direkt im Terminal
🖼️ Ortsbilder im TextmodusZeigt Ortsbild inline im Log (Stundenglas-Stil)
📐 Terminal-BreiteVoll / 600–1000 px (zentriert)
Sichtbare Modus-ButtonsJe Checkbox: Grafik / Parser / Text anzeigen

Nur-Text-Modus mit Ortsbildern

Wenn „Ortsbilder im Textmodus" aktiviert ist, erscheint das Bild direkt im Log-Fluss – direkt über der Raumbeschreibung. Das Bild scrollt mit dem Text mit, sodass beim Raumwechsel automatisch das neue Bild sichtbar ist. Ein 🖼️-Button im Header blendet alle Bilder ein/aus.

💡
Konditionelle Bilder funktionieren auch im Nur-Text-Modus vollständig – das richtige Bild erscheint abhängig vom aktuellen Flag-Zustand.

Konditionale Bilder bei Items

Nicht nur Orte – auch Items im Inventar und im ℹ️ Info-Modal können je nach Flag-Stand ihr Bild wechseln. Das Prinzip ist identisch: erste passende Bedingung gewinnt, Fallback auf das Standard-Bild.

Item bearbeiten → unter dem Standard-Bild: Abschnitt „🔀 Konditionale Bilder"+ Bild hinzufügen. Jeder Eintrag hat dieselben Felder wie bei Orten: requireFlag, forbidFlag, Bild-Upload.

JSON-Format
"item_schluessel": {
 "name": "Schlüssel",
 "image": "schluessel_rostig.jpg",
 "conditionalImages": [
 {
 "image": "schluessel_glaenzend.jpg",
 "requireFlag": "schluessel_poliert"
 }
 ]
}
Wo sichtbarBeschreibung
Inventar-SidebarThumbnail wechselt je nach Flag-Stand
ℹ️ Info-ModalGroßes Bild im Item-Detail-Modal ebenfalls konditional

Konditionale NPC-Portraits

NPC-Portraits wechseln je nach Flag-Zustand – z.B. trauriges Portrait vor einer Quest, lächelndes Portrait danach.

JSON-Format
"npcs": {
  "papa": {
    "name": "Papa",
    "portrait": "papa_neutral.jpg",
    "conditionalPortraits": [
      {
        "image": "papa_gluecklich.jpg",
        "flag": "papa_gluecklich"
      }
    ]
  }
}

Im Editor: NPC bearbeiten → Konditionale Portraits+ Portrait hinzufügen.

Tastaturkürzel im Grafik- und Parser-Modus

TasteAktion
1–9Ausgang Nr. 1–9 betreten
A, B, C …NPC ansprechen (A = erster NPC im Raum)
↑ ↓ ← →Richtungsausgänge (N/S/O/W)
EnterModal bestätigen / Dialog-Option
EscapeModal schließen
IInventar anzeigen (Parser-Modus)
?Tastaturhilfe
ℹ️
Ausgänge und NPCs bekommen sichtbare Hinweise (1, 2 … bzw. A, B …) direkt auf den Karten angezeigt. Im Parser-Modus sind A–Z für die Texteingabe reserviert und lösen keine NPC-Shortcuts aus.
⌨️
Parser-Modus
Freitext-Eingabe als Alternative zum Klicken

Was ist der Parser-Modus?

Jedes Spiel kann optional per Freitext gespielt werden. Ein Toggle-Button im Player-Header schaltet zwischen Klick-Modus und Parser-Modus um. Beide Modi laufen parallel – der Spieler kann jederzeit wechseln, ohne den Spielstand zu verlieren.

ℹ️
Aktivieren im Editor: Tab 🎨 Anzeige → Abschnitt "⌨️ Parser-Modus" → Checkbox aktivieren. Nur dann erscheint der Toggle-Button im Player.

Vollständiges Vokabular

🗺️ Gehen

VerbenBeispiele
GEHE · GEH · LAUFE · BETRETEGEHE NORDEN · BETRETE KUECHE
Kurzformen: N S O W H RN · NORDEN · SÜD · OSTEN · WESTEN · HOCH · RUNTER
Freie AusgangsnamenGEHE ZUR HAUSTÜR · GEHE IN DIE KÜCHE

📦 Nehmen

NIMM · NEHME · AUFHEBEN · AUFNEHMEN · GREIF · STECKE EIN · SAMMLE

🗑️ Ablegen

LEGE AB · ABLEGEN · WIRF WEG · WEGWERFEN · ABGEBEN

🔍 Untersuchen

UNTERSUCHE · SCHAU AN · BETRACHTE · PRÜFE · INSPIZIERE · X · LOOK · L

Zeigt die Beschreibung eines Objekts oder Items – ohne eine Aktion auszulösen.

🔎 Durchsuchen

DURCHSUCHE · DURCHSUCHEN · SUCHE IN · WÜHLE IN · FILZE · STÖBERE IN · KRAME IN · GRABE IN

Löst Direkt-Aktionen an Raumobjekten aus – ideal für Objekte die man "durchsuchen", "öffnen" oder "aktivieren" kann ohne ein Item zu brauchen.

💡
DURCHSUCHE allein (ohne Ziel) listet alle durchsuchbaren Objekte im Raum auf.

🔧 Benutzen (solo)

BENUTZE · VERWENDE · NUTZE · SETZE EIN · WENDE AN · KOMBINIERE · MISCHE

Erkennt automatisch ob das Argument ein Inventar-Item (→ auf passendes Raumobjekt anwenden) oder ein Raumobjekt (→ Direkt-Aktion) ist.

⚗️ Benutzen mit

MusterBeispiele
BENUTZE [X] MIT [Y]BENUTZE STAUBSAUGER MIT STAUB
KOMBINIERE [X] MIT [Y]KOMBINIERE 5 EURO MIT 3 EURO
MISCHE [X] MIT [Y]MISCHE SEIFE MIT EIMER
BENUTZE [X] AUF [Y] / [X] UND [Y]BENUTZE SCHLÜSSEL AUF TRUHE

Prüft zuerst Rezept (beide Items im Inventar), dann Raumobjekt. Reihenfolge ist egal.

🎁 Geben an NPC

VerbenVerbinderBeispiel
GIB · GEBE · ÜBERGIB · BRINGE · ZEIGEAN · ZU · BEI · DEM · DERGIB STAUBSAUGER AN MAMA

💬 Sprechen · 🚪 Öffnen · 🎒 Inventar · ❓ Hilfe

FunktionVerben
SprechenSPRICH MIT · REDE MIT · FRAG · ANTWORTE
ÖffnenÖFFNE · AUFMACHEN · MACH AUF
SchließenSCHLIESSE · SCHLIEßEN · MACH ZU
InventarINVENTAR · INV · I
UmschauenSCHAU DICH UM · UMGEBUNG · LOOK · L
HilfeHILFE · HELP · H · ?

Parser-Tipps für Game Designer

Synonyme pro Item (Tab 📦 Objekte)

Im Feld Parser-Synonyme kommagetrennte Alternativnamen eintragen. Groß-/Kleinschreibung egal, Teilwörter werden erkannt.

Item: "Goldener Schlüssel"
Synonyme: schluessel, rost, key

NIMM SCHLÜSSEL, NIMM ROST und NIMM KEY funktionieren alle.

Direkt-Aktionen parser-freundlich gestalten

Damit DURCHSUCHE und BENUTZE [Objekt] funktionieren, braucht das Objekt in usableWith einen Eintrag mit leerem itemName:

"usableWith": [{
 "itemName": "",
 "actionLabel": "🔍 Durchsuchen",
 "success": "Du wühlst zwischen den Kissen... 5 Euro!"
}]

Komplettlösung per Parser: Pizza-Katastrophe

SCHAU DICH UM
BENUTZE TELEFON
DURCHSUCHE SOFA-KISSEN
NIMM 5 EURO
GEHE IN DIE KÜCHE
DURCHSUCHE KEKSDOSE
NIMM KEKSE
GEHE ZURÜCK INS ZIMMER
NIMM STAUBSAUGER
BENUTZE STAUBSAUGER MIT STAUB
GIB STAUBSAUGER AN MAMA
NIMM 3 EURO
KOMBINIERE 5 EURO MIT 3 EURO
GEHE ZUR HAUSTÜR
GIB 8 EURO AN MARCO
-- oder: GIB KEKSE AN MARCO
🔊
Sound-Bibliothek & SFX
Soundeffekte zentral verwalten – einmal hochladen, überall einsetzen

Was ist die Sound-Bibliothek?

Neben der Hintergrundmusik pro Ort unterstützt ABP jetzt auch Soundeffekte (SFX) – kurze Klänge die bei konkreten Spielereignissen abgespielt werden. Alle Sounds werden einmalig in der zentralen Bibliothek gespeichert. Objekte, Rezepte und Items referenzieren den Sound dann nur noch per ID – kein doppeltes Speichern derselben Audiodatei.

ℹ️
Tab 🔊 Sounds im Editor – zwischen „🏁 Enden" und „⚙️ Features". Hier verwaltest du die gesamte Bibliothek: hochladen, umbenennen, voranhören, ersetzen, löschen.

JSON-Struktur der Bibliothek

"sounds": {
 "snd_1234_abc": {
 "name": "💥 Explosion",
 "data": "data:audio/mp3;base64,..."
 },
 "snd_5678_xyz": {
 "name": "🔑 Tür knarrt",
 "data": "data:audio/mp3;base64,..."
 }
}

Die IDs werden automatisch generiert. Du referenzierst sie überall im Spiel als einfacher String – z.B. "sfx": "snd_1234_abc".

SFX-Felder – wo einsetzbar

StelleJSON-FeldWann wird er gespielt?
Item aufnehmenitems["id"].sfxSpieler nimmt das Objekt ins Inventar
usableWith ErfolgusableWith[i].sfxItem erfolgreich auf Objekt angewendet
Rezept gecraftetrecipes[i].sfxZwei Items erfolgreich kombiniert
Spieler HP-SchadendisplaySettings.sfx.hitSpieler wird vom NPC getroffen
Spieler HeilungdisplaySettings.sfx.healHeiltrank oder selfUse mit healHP
Skill-Level steigtdisplaySettings.sfx.levelupKampf-Skill erhöht sich
Spieler stirbtdisplaySettings.sfx.deathSpieler-HP sinkt auf 0
NPC besiegtdisplaySettings.sfx.npcDefeatNPC-HP sinkt auf 0 (onDefeat)
💡
Kampf-Sounds (hit, heal, levelup, death, npcDefeat) sind global und gelten für das gesamte Spiel. Sie werden im Tab ⚙️ Features im Abschnitt „🔊 Kampf-Sounds" per Dropdown zugewiesen.

Beispiel: Schlüssel mit Pickup-Sound

"rost_schluessel": {
 "name": "🔑 Rostiger Schlüssel",
 "description": "Ein alter, verrosteter Schlüssel.",
 "sfx": "snd_1234_abc" // Knarr-Sound aus der Bibliothek
}

Beispiel: Tür öffnen mit SFX

"usableWith": [{
 "itemId": "rost_schluessel",
 "success": "Die Tür quietscht auf!",
 "setFlag": "tuer_offen",
 "removeItem": true,
 "sfx": "snd_5678_xyz" // Tür-knarrt-Sound
}]

Sound-Bibliothek im Editor verwalten

AktionBeschreibung
➕ HochladenMP3, OGG oder WAV – Name wird automatisch aus dem Dateinamen vorgeschlagen
▶️ VorschauSound direkt im Editor anhören
✏️ UmbenennenName direkt in der Karte bearbeiten – alle Referenzen bleiben gültig (ID ändert sich nicht)
🔄 ErsetzenNeue Audiodatei hochladen – alle Stellen im Spiel spielen sofort den neuen Sound
🗑️ LöschenWarnung wenn der Sound noch in Verwendung ist (Zähler zeigt wie oft)
⚠️
Wenn ein Sound gelöscht wird der noch referenziert wird, wird er an diesen Stellen stumm – es kommt aber zu keinem Fehler. Der Verwendungs-Zähler in der Bibliothek zeigt dir vorher wie oft ein Sound genutzt wird.

Technische Hinweise

ℹ️
Rückwärtskompatibel: Alte JSON-Dateien die Base64-Audio direkt im sfx-Feld gespeichert haben (statt einer Sound-ID) werden vom Player weiterhin korrekt abgespielt. Eine Migration ist nicht nötig.
ℹ️
SFX unterbricht BGM nicht: Soundeffekte laufen parallel zur Hintergrundmusik. Der globale Sound-an/aus-Schalter im Player gilt für beide.
📚
Spielserie
Mehrere Spiele zu einer Serie mit Hauptmenü verbinden

Konzept

Eine Spielserie verbindet mehrere eigenständige JSON-Spiele (Kapitel) unter einem gemeinsamen Hauptmenü. Jedes Kapitel bleibt dabei auch einzeln spielbar. Der Player zeigt beim Laden einer serie.json automatisch ein Hauptmenü mit Kapitelauswahl, optionalen Extras und – wenn konfiguriert – Hintergrundbild und -musik.

💡
Beispiel: „Sophie schafft das!" mit drei Kapiteln, eigenem Hintergrundbild und einem Bonus-Malbuch das nach dem Durchspielen aller Kapitel freigeschaltet wird.

serie.json – vollständiges Format

"title": "Zuhause-Kosmos",
"author": "Kai Blass",
"description": "Drei Abenteuer in einer Spielwelt",
"chapterSelect": true, // false = lineare Reihenfolge

// Hauptmenü-Design (optional)
"mainmenu": {
 "backgroundImage": "data:image/...", // Base64-Bild
 "backgroundMusic": "data:audio/...", // Base64-Audio
 "musicLoop": true
},

"chapters": [
 {
 "id": "ch1",
 "title": "Pizza-Katastrophe",
 "file": "pizza-katastrophe.json",
 "description": "Ein Kuchen muss her!",
 "previewImage": "data:image/...", // Vorschaubild im Menü
 "startConditions": {
 "playerHP": 100,
 "skillStart": 0,
 "startInventory": [],
 "flags": {}
 }
 }
],

"extras": [
 {
 "title": "Malbuch",
 "file": "malbuch.json",
 "description": "Zum Ausmalen!",
 "unlockCondition": "allChaptersDone", // oder "always"
 "rewardTitle": "🎉 Du hast alle Kapitel gespielt!",
 "rewardText": "Als Belohnung gibt es jetzt das Malbuch.",
 "rewardImage": "data:image/..." // optionales Belohnungsbild
 }
]
FeldBeschreibung
chapterSelecttrue = freie Wahl · false = lineare Reihenfolge
mainmenu.backgroundImageHintergrundbild für das Hauptmenü (Base64)
mainmenu.backgroundMusicHintergrundmusik für das Hauptmenü (Base64, stoppt beim Kapitelstart)
chapters[].previewImageVorschaubild im Kapitelmenü (Base64, 44×44px)
chapters[].startConditionsStartwerte: HP, Skill, Inventar, Flags
extras[].unlockCondition"always" = immer sichtbar · "allChaptersDone" = nach allen Kapiteln
extras[].rewardTitle/Text/ImageBelohnungs-Modal das automatisch erscheint wenn das Extra freigeschaltet wird

Player-Hauptmenü

Das Hauptmenü erscheint automatisch wenn eine serie.json geladen wird:

ElementBeschreibung
▶ Spiel startenSetzt am letzten Stand fort oder startet das erste Kapitel
☰ Kapitel auswählenListe mit Vorschaubildern und Status-Badges (✓ done / ▶ aktiv / 🔒 gesperrt)
★ ExtrasGesperrte Extras als 🔒 sichtbar, freigeschaltete direkt spielbar
Hintergrundbild/-musikMusik stoppt beim Kapitelstart, kehrt zurück beim „‹ Menü"-Button

Belohnungs-System

Wenn der Spieler alle Kapitel abschließt und ein Extra mit unlockCondition: "allChaptersDone" und rewardTitle vorhanden ist, erscheint automatisch ein Belohnungs-Modal:

  1. Letztes Kapitel wird gewonnen
  2. Belohnungs-Modal erscheint mit Titel, Text und optionalem Bild
  3. Button führt direkt zum Hauptmenü
  4. Extras-Button im Hauptmenü leuchtet mit „✨ Extras freigeschaltet!"

Serie konfigurieren (Packager)

Die Serie wird im Packager v2.5 konfiguriert – kein Editor-Tab nötig:

  1. Modus 📚 Spielserie auswählen
  2. Serientitel, Autor, Beschreibung eingeben
  3. Optional: Hintergrundbild + Hintergrundmusik hochladen
  4. Kapitel hinzufügen, JSON hochladen, Vorschaubild hochladen
  5. Extras mit Freischaltungsbedingung und Belohnungstext konfigurieren
  6. Player-HTML hochladen → 🚀 Standalone erstellen
  7. Alternativ: 💾 serie.json speichern für Online-Nutzung
ℹ️
Beim Speichern als serie.json werden die eingebetteten Spieldaten (gameData) nicht mitgespeichert – nur die Struktur. Das ist gewollt: die Online-Version lädt Kapitel per fetch() vom Server.

Laden & Aufrufen

MethodeBeschreibung
Drag & Dropserie.json in den Player ziehen → Hauptmenü erscheint sofort
URL-Parameterplayer.html?serie=datei.json
StandalonePackager v2.5 erstellt eine Single-HTML mit allen Spielinhalten eingebettet
🔗
Spiel per URL laden
?JSON=dateiname – direkt aus der URL starten

Was ist das?

Der Player kann eine JSON-Datei automatisch laden wenn der Dateiname als URL-Parameter übergeben wird. Damit kann ein Spiel direkt über einen Link gestartet werden – ohne dass der Spieler erst eine Datei auswählen muss.

URL-Format

player.html?JSON=pizza-katastrophe
player.html?JSON=pizza-katastrophe.json // .json optional
player.html?game=zoo-verrueckt // auch ?game= wird erkannt
ℹ️
Die JSON-Datei muss im selben Verzeichnis wie player.html auf dem Webserver liegen. Lokal (per file://) funktioniert das aus Sicherheitsgründen nicht – nur auf einem echten Webserver.

Auf der Homepage einsetzen

Statt für jedes Spiel eine eigene Standalone-HTML-Datei (Packager) zu erzeugen, kannst du einfach die JSON-Datei hochladen und direkt verlinken:

<!-- Statt: -->
<a href="pizza-katastrophe.html">Spielen</a>

<!-- Einfacher: -->
<a href="player.html?JSON=pizza-katastrophe">Spielen</a>
VorteilBeschreibung
PlatzsparendNur die kleine JSON-Datei hochladen – kein 8.500-Zeilen-Player pro Spiel
Immer aktuellWenn du den Player verbesserst, profitieren alle Spiele sofort
Einfaches UpdateNeues JSON hochladen – der Link bleibt gleich
📦
Packager – Spiele veröffentlichen
Einzelspiele und Serien für andere zugänglich machen

Konditionale Item-Beschreibungen

Nicht nur das Bild – auch der Beschreibungstext eines Items kann je nach Flag-Stand wechseln. Die Beschreibung erscheint im Info-Modal (wenn der Spieler auf das Objekt klickt) und im Inventar-Detail. Erste passende Bedingung gewinnt, Fallback auf den Standard-Text.

Im Editor: Item bearbeiten → Abschnitt „📝 Konditionale Beschreibungen"+ Beschreibung hinzufügen. Jeder Eintrag hat ein Flag-Dropdown und ein Textfeld.

JSON-Format
"items": {
  "tablet": {
    "name": "Tablet",
    "description": "Das Tablet zeigt: Kein Internetzugang.",
    "conditionalDescriptions": [
      {
        "flag": "internet_frei",
        "description": "Das Tablet ist online! Du kannst jetzt surfen."
      }
    ]
  }
}

Lässt sich beliebig mit konditionalen Bildern kombinieren – so kann das Tablet bei internet_frei = true sowohl ein neues Bild als auch einen neuen Text zeigen.

Item Inline-Editor (Objekte-Tab)

Der Objekte-Tab im Editor arbeitet ohne Popup-Modals. Alle Item-Eigenschaften werden direkt im Hauptbereich bearbeitet: Name, Item-ID, Beschreibung, Tags, Bild/Video, Self-Use (sofort benutzen ohne Ziel), konditionale Bilder und konditionale Beschreibungen. Änderungen werden beim Verlassen eines Felds automatisch gespeichert – ein separater Speichern-Button ist optional.

Die linke Liste zeigt alle Items mit ihrer ID. Klick auf ein Item → sofortiger Wechsel, alle Felder werden neu geladen.

Direct Action: Item sofort ins Inventar

Mit givesItemId in einem usableWith-Eintrag (ohne Item = Direct Action) landet ein Item sofort im Inventar des Spielers – kein zweiter Klick nötig. Perfekt für „Kiste durchsuchen", „Schublade öffnen" oder „Brief aufheben".

JSON-Beispiel: Werkzeugkiste
{
  "itemId": "werkzeugkiste",
  "canTake": false,
  "usableWith": [
    {
      "actionLabel": "🔧 Durchsuchen",
      "givesItemId": "schraubendreher",
      "message": "Du findest einen Schraubendreher!",
      "removeObject": true,
      "setFlag": "kiste_durchsucht"
    }
  ]
}

Das actionLabel erscheint als Button direkt am Objekt (kein Item im Inventar nötig). Nach dem Klick geht der Schraubendreher sofort ins Inventar, die Kiste verschwindet und der Flag kiste_durchsucht wird gesetzt.

Objekt-Aktion als Modal-Fenster (modal: true)

Standardmäßig erscheint die Erfolgsmeldung einer Objekt-Aktion als kurze Toast-Meldung. Mit modal: true wird sie als bleibendes Modal-Fenster angezeigt – ideal für Rezepte, Briefe oder Hinweisschilder.

JSON-Format
"usableWith": [
  {
    "actionLabel": "📜 Brief lesen",
    "message": "Liebe Anna, ...\n\nDein Papa",
    "modal": true,
    "title": "📜 Ein Brief"
  }
]

Was ist der Packager?

Der Packager ist ein separates Browser-Werkzeug (packager.html) das deine Spiele für andere zugänglich macht – ohne dass dein Publikum den Editor oder die Spielstruktur sehen muss. Er kombiniert Player + Spieldaten zu einer einzigen, sofort lauffähigen Datei, oder er erzeugt eine kompakte serie.json für die Online-Veröffentlichung.

ModusErgebnisIdeal für
🎮 Einzelspiel → StandaloneEine HTML-Datei, alles eingebettetOffline-Weitergabe, USB, E-Mail
📚 Serie → StandaloneEine HTML-Datei, alle Kapitel eingebettetOffline-Weitergabe einer kompletten Serie
📚 Serie → serie.jsonKompakte JSON-Datei, Thumbnails eingebettetWebserver-Veröffentlichung mit URL-Aufruf

Fall 1: Einzelspiel als Standalone

Der klassische Fall – ein Spiel, eine Datei, überall spielbar.

Packager öffnen → 🎮 Einzelspiel → Player laden → JSON laden → 🚀 Standalone erstellen
  1. Player laden: Aktuelle player.html per Drag & Drop oder Klick hochladen. Der Packager zeigt an welche Version erkannt wurde und welche Features die JSON enthält.
  2. JSON laden: Die exportierte Spiel-JSON hochladen (aus dem Editor: 💾 Als JSON speichern).
  3. Optional – Ladescreen-Bild: Ein Bild das während des Ladens gezeigt wird (empfohlen: 600×400px).
  4. 🚀 Standalone erstellen: Erzeugt spielname_standalone.html – diese Datei enthält alles und startet sofort im Browser.
// Was in der Standalone-HTML steckt:
✅ player.html (vollständiger Spielmotor)
✅ Spieldaten (JSON eingebettet)
✅ Ladescreen-Bild (als Base64, falls hochgeladen)
✅ Fortschritts-Animation beim Start
💡
Die Standalone-Datei funktioniert komplett offline – kein Internet, kein Server nötig. Einfach per E-Mail, USB oder Download-Link weitergeben.

Fall 2: Serie als Standalone

Alle Kapitel einer Serie in einer einzigen Offline-Datei.

Packager → 📚 Spielserie → Metadaten → Kapitel konfigurieren → Player laden → 🚀 Standalone erstellen
  1. Serientitel, Autor, Beschreibung eingeben.
  2. Optional: Hintergrundbild und Hintergrundmusik für das Hauptmenü hochladen.
  3. Kapitel hinzufügen: ➕-Button → Titel + dateiname.json eintragen.
  4. Pro Kapitel: 📂 JSON laden → Spiel-JSON hochladen (wird eingebettet) · 🖼️ Vorschau → Thumbnail hochladen (wird als Base64 eingebettet).
  5. Player laden und 🚀 Standalone erstellen.
ℹ️
Bei der Standalone-Serie werden die Kapitel-JSONs vollständig eingebettet – kein Server nötig. Die Thumbnails werden ebenfalls als Base64 eingebettet.

Fall 3: Serie online veröffentlichen

Der eleganteste Weg für adventure-builder.de oder einen eigenen Webserver: eine schlanke serie.json mit eingebetteten Thumbnails – die Kapitel werden beim Spielen per URL nachgeladen.

Packager → 📚 Spielserie → Kapitel konfigurieren (nur Dateinamen, kein JSON-Upload!) → 💾 serie.json speichern
  1. Serienstruktur aufbauen: Titel, Kapitel-Titel und Dateinamen eintragen (z.B. pizza-katastrophe.json).
  2. Kein JSON-Upload nötig! Die Kapitel-JSONs liegen später auf dem Server – der Player lädt sie beim Klick automatisch nach.
  3. Thumbnails hochladen: 🖼️ Vorschau pro Kapitel → Bild hochladen → wird als Base64 eingebettet und bleibt in der serie.json.
  4. 💾 serie.json speichern: Erzeugt eine schlanke JSON ohne Spieldaten – nur Struktur + Thumbnails.
  5. Auf den Server hochladen: Alle Dateien in denselben Ordner.

Serverstruktur:

📁 webserver/
   player.html
   sophie_schafft_das_serie.json    ← mit Thumbnails (Base64), kein gameData
   pizza-katastrophe.json           ← Kapitel 1
   zoo-verrueckt.json               ← Kapitel 2
   oma-geburtstag.json              ← Kapitel 3

Aufruf im Browser:

https://adventure-builder.de/player.html?serie=sophie_schafft_das_serie.json

// Kurzform funktioniert auch:
https://adventure-builder.de/player.html?game=sophie_schafft_das_serie.json
💡
Thumbnails als Base64 in der serie.json zu speichern ist der Trick: die Bilder sind überall verfügbar (kein separater Bildpfad nötig), aber die großen Spieldaten werden erst bei Bedarf nachgeladen. Perfekt für schnelle Ladezeiten.

Fall 4: Einzelspiel online via URL

Kein Packager nötig – der Player kann Spiele direkt per URL-Parameter laden.

https://adventure-builder.de/player.html?game=pizza-katastrophe.json

Serverstruktur:

📁 webserver/
   player.html
   pizza-katastrophe.json

Der Player erkennt automatisch ob es sich um ein Einzelspiel oder eine Serie handelt und zeigt entsprechend die Spieloberfläche oder das Serien-Hauptmenü.

URL-ParameterWirkung
?game=datei.jsonEinzelspiel oder Serie laden (universell)
?serie=datei.jsonExplizit als Serie laden
?JSON=datei.jsonEinzelspiel laden (Legacy)
?preview=1Vorschau-Modus (nur für Editor-Nutzung)

Welcher Weg für welchen Zweck?

SituationEmpfohlener Weg
Freunde/Familie (offline, kein Technik-Know-how)Standalone HTML (Fall 1 oder 2)
Schulprojekt, USB-VerteilungStandalone HTML
Eigene Website, adventure-builder.deserie.json + Kapitel-JSONs (Fall 3)
Schneller Test eines Einzelspiels onlineURL-Parameter (Fall 4)
Workshop – Teilnehmende spielen lokalStandalone HTML oder lokaler Webserver mit URL

Editor-Usability – neue Funktionen

🖌️ Editor-Themes

Unter ⚙️ Einstellungen → Editor-Theme stehen 5 Farbthemen zur Wahl: 🌈 Bunt, ⚫ Dark, 🔘 Schlicht, 🔵 Klassisch und 🎮 Minecraft. Jedes Theme ändert Hintergrundfarbe, Buttons, Header und Sidebar. Die Wahl wird im Browser gespeichert (nicht im Spiel-JSON).

⚙️ Einstellungen-Tab

Der neue Tab ⚙️ Einstellungen fasst Spiel-Informationen (Titel, Autor, Version, Sprache), Editor-Theme, TTS und Spielende an einem Ort zusammen. Kampf-System und Spielmodi sind im Tab Features bzw. Anzeige. Der Header-Button „⚙️ Einstellungen" öffnet direkt diesen Tab statt einem Modal.

↕ Akkordeon-Zyklus

Der ↕-Button rechts in der Titelleiste von ORTE, Features und Anzeige schaltet zwischen drei Zuständen durch: Alle aufAlle zuMerker (gespeicherter Zustand). Der Editor merkt sich welche Akkordeons offen waren und kehrt auf Wunsch dorthin zurück.

⏱ Zuletzt bearbeitet

Ab 3 Orten zeigt die Orts-Sidebar oben die 3 zuletzt bearbeiteten Orte als Schnellzugriff an. Spart Scrollen bei großen Spielen.

⧉ Objekt duplizieren

Jedes Objekt in einem Ort hat jetzt einen ⧉-Button (Duplizieren). Ein Klick erstellt eine identische Kopie direkt darunter – inklusive aller Verwendungen, Flags und Bedingungen.

🔍 Schnellsuche

In der Sidebar der Tabs NPCs, Flags und Sounds gibt es jetzt ein Suchfeld zum schnellen Filtern der Liste.

🎮 Spieltitel im Header

Nach dem Laden oder Anlegen eines Spiels erscheint der Spieltitel rechts neben dem „Adventure Builder Pro"-Logo im Header. Er aktualisiert sich automatisch wenn du den Titel im Tab ⚙️ Einstellungen → 📋 Spiel-Informationen änderst.

💾 Export-Dateiname = Spieltitel

Beim Export heißt die JSON-Datei jetzt automatisch nach dem Spieltitel – z.B. Mission_Zoo_verrueckt.json. Sonderzeichen werden entfernt, Leerzeichen durch _ ersetzt. Umlaute bleiben erhalten.

📋 Spiel-Informationen inline

Titel, Autor, Version und Startort sind jetzt direkt im Tab ⚙️ Einstellungen → 📋 Spiel-Informationen inline editierbar – kein Modal mehr nötig. Der Header-Button „⚙️ Einstellungen" öffnet direkt diesen Tab.

🚩 Flag setzen beim Nehmen (canTake)

Objekte mit canTake: true können jetzt ein setFlag erhalten. Sobald der Spieler das Objekt aufnimmt, wird dieser Flag automatisch auf true gesetzt. Im Editor erscheint dafür ein Dropdown „🚩 Flag setzen beim Nehmen" im Objekt-Modal (Hinzufügen + Bearbeiten). Dies ist z.B. nützlich um bedingte Ortsbeschreibungen auszulösen (Tasche nehmen → tasche_genommen → Beschreibung ändert sich).

🏁 Spielende – Verzögerung & Partikeldesigner

Unter ⚙️ Einstellungen → 🏁 Spielende kannst du die Ende-Meldung fein einstellen:

  • ⏱️ Verzögerung – Slider 0–5s (Standard: 2s). Wähle wie lange es dauert bis die Gewinn/Verlier-Meldung nach dem auslösenden Event erscheint.
  • 🎨 Partikel-Effekt – drei Modi: 🎉 Emojis (frei konfigurierbar), 🎊 Konfetti (geometrische Farbflächen), 🚫 Keiner
  • ✏️ Emojis konfigurieren – eigene Emojis eingeben oder aus 8 Schnellauswahl-Presets wählen (Party, Sterne, Sieg, Herzen, Natur, Space, Action, Games)
  • 🔢 Menge – Slider 10–200 Partikel
  • ⚡ Geschwindigkeit – 🐢 Langsam / ▶️ Normal / ⚡ Schnell

📝 forbidFlag in konditionalen Beschreibungen

Konditionale Ortsbeschreibungen unterstützen jetzt ein zweites Dropdown 🚫 Flag (darf NICHT gesetzt sein). Damit lassen sich Beschreibungen exakter steuern: z.B. „zeige diesen Text wenn Flag A gesetzt ist, aber nur solange Flag B noch nicht gesetzt ist". Außerdem gibt es einen ↑ Nach-oben-Button um die Reihenfolge der Einträge zu ändern – wichtig, da immer der erste passende Eintrag gewinnt (spezifischste Bedingungen müssen oben stehen).

🌐 Mehrsprachigkeit (DE / EN)

Ab v4.4 unterstützt Adventure Builder Pro zwei Sprachen: Deutsch und Englisch. Die Sprache wird pro Spiel in gameData.language gespeichert ("de" oder "en") und im Editor unter ⚙️ Einstellungen → 📋 Spiel-Informationen → 🌐 Sprache eingestellt.

Der Player erkennt beim Start die Sprache und lädt automatisch das passende Vokabular für Parser-Befehle, Richtungen und alle UI-Texte (Inventar, Ausgänge, Parser-Antworten, Sieg/Niederlage-Meldungen).

Mehrsprachige Spiele über die Kapitelauswahl

Der empfohlene Ansatz für mehrsprachige Spiele ist der Kapitel-Ansatz: Dasselbe Spiel wird als zwei separate JSON-Dateien (z.B. mission_de.json und mission_en.json) exportiert und in der Spielserie als separate Kapitel eingetragen. Der Spieler wählt beim Start seine Sprache über die Kapitelauswahl – keine spezielle Sprachauswahl-UI nötig.

Serie: "Mission Zoo verrückt"
├── Kapitel 1: 🇩🇪 Deutsch  → mission_zoo_de.json  (language: "de")
└── Kapitel 2: 🇬🇧 English  → mission_zoo_en.json  (language: "en")

Englisches Parser-Vokabular (Auswahl)

TAKE · PICK UP · GET · DROP · GO · NORTH/SOUTH/EAST/WEST/UP/DOWN · EXAMINE · LOOK AT · X · SEARCH · USE · USE WITH · COMBINE WITH · TALK TO · INVENTORY/INV/I · HELP/H/? · LOOK AROUND · OPEN · CLOSE · GIVE TO

Sound-Bibliothek für Hintergrundmusik

Hintergrundmusik eines Ortes wird jetzt über die 🔊 Sound-Bibliothek referenziert statt direkt als Base64 gespeichert. Im Ort-Editor erscheint ein Dropdown mit allen Bibliotheks-Sounds. Bestehende JSON-Spiele mit direkt eingebetteter Musik werden beim Laden automatisch migriert.

Vorteil: Dieselbe Musik kann mehreren Orten zugewiesen werden ohne den JSON-Export zu vergrößern. Unter Tab 🔊 Sounds sieht man bei jedem Sound wo er eingesetzt wird (z.B. „🎵 Hintergrundmusik: Küche").

📋
JSON-Schnellreferenz
Alle wichtigen Felder auf einen Blick

Vollständige Grundstruktur

{
 // === PFLICHT ===
 "title": "Spielname",
 "startLocation": "ort_id",

 // === OPTIONAL ===
 "author": "Dein Name",
 "version": "1.0",
 "defaultTheme": "modern",
 // Start-Inventar: pro Item "startInventory": true setzen (siehe Items)

 // === KERN-DATEN ===
 "locations": { /* Orte */ },
 "items": { /* Gegenstände */ },
 "npcs": { /* Charaktere */ },
 "recipes": [ /* Rezepte */ ],
 "quests": [ /* Aufgaben */ ],
 "flags": { /* Spielzustände */ },
 "sounds": { /* 🔊 Sound-Bibliothek */ },
 "cutscenes": { /* Story-Sequenzen */ },
 "gameEnds": { "win": [], "lose": [] },
 "displaySettings": { /* Layout */ }
}

usableWith – alle Felder

FeldTypBeschreibung
itemIdstringItem-ID (bevorzugt)
itemNamestringItem-Name (Legacy-Kompatibilität)
actionLabelstringButton-Text (leer = kein Item nötig)
successstringErfolgsmeldung
givesItemIdstringItem erscheint im Inventar
requireItemIdstringZusätzliches Item muss vorhanden sein
requireFlagNotstringGesperrt wenn diese Flag TRUE ist
changeObjectstringObjekt wird durch dieses ersetzt
spawnObjectstringNeues Objekt erscheint im Raum
spawnCanTakebooleanKann gespawntes Objekt aufgenommen werden?
removeObjectbooleanObjekt verschwindet
removeItembooleanVerwendetes Item wird verbraucht
setFlagstringDiese Flag wird gesetzt
clearFlagstringDiese Flag wird gelöscht
teleportTostringSpieler wird teleportiert
playCutscenestringCutscene wird danach abgespielt
playCutsceneOncebooleanCutscene nur einmal abspielen
quantitynumberWie oft nutzbar?
quantityMessagestringMeldung wenn aufgebraucht
damagenumberSchaden bei HP-Objekten
sfxstring🔊 Sound-ID aus der Bibliothek – spielt bei Erfolg
Checkliste
Ist dein Spiel fertig zum Testen?

Vor dem ersten Test

📁 Grundstruktur

  • startLocation ist gesetzt und der Ort existiert
  • Alle Orte haben Name und Beschreibung
  • Kein Ort verweist auf einen nicht-existierenden Ort (Exits)
  • Mindestens eine Sieg-Bedingung ist definiert

📦 Items & Inventar

  • Alle Items, die in Rezepten (Zutaten/Ergebnis), an Ausgängen (requiredItem) oder in usableWith (itemName) verwendet werden, sind in items definiert – im Editor ist das der Tab 📦 Objekte. Der Abgleich läuft über den Namen (exakte Schreibweise!). Nicht verwechseln: Gemeint sind Inventar-Items – nicht die Raum-Objekte, an denen usableWith hängt.
  • Wenn Inventar-Freischaltung: Freischalt-Item liegt als Raumobjekt vor, nicht als Tausch-Item

🗨️ NPCs & Dialog

  • Jeder NPC hat entweder einen statischen Dialog oder einen Dialog-Baum mit start-Knoten
  • receivesItems verweist auf Items die der Spieler auch wirklich finden kann
  • flagBranch-Ziel-Knoten existieren im Dialog-Baum

🏁 Spielende

  • Spielende-Bedingungen sind erreichbar (kein unlösbares Spiel)
  • Wenn teleportTo gesetzt: Ziel-Ort existiert
  • Wenn playCutscene gesetzt: Cutscene-ID existiert
  • message ist ausgefüllt (title + message + buttonText empfohlen)

🎬 Cutscenes

  • Alle referenzierten Cutscene-IDs existieren in cutscenes
  • game_intro vorhanden (optional, aber empfohlen)
  • playCutsceneOnce: true gesetzt wo nötig

🚩 Flags

  • Alle Flags die als Bedingung verwendet werden, sind in flags definiert
  • Flag-Namen sind konsistent (exakt gleich geschrieben)
💡
Best Practices
Tipps für besseres Game Design

Namenskonventionen

WasEmpfehlungBeispiel
Ort-IDsBeschreibend, klein, Unterstrichwald_eingang, schloss_thronsaal
Item-IDsBedeutungsträger, eindeutigrost_schluessel, heiltrank_gross
Flag-NamenZustand beschreibentuer_offen, boss_besiegt
Cutscene-IDsAuslöser erkennbargame_intro, boss_defeat

Story-Struktur

  • Tutorial-Ort: Der erste Ort sollte die Grundmechaniken erklären – am besten durch Handeln, nicht durch langen Text
  • Klare Ziele: Der Spieler sollte immer wissen was als nächstes zu tun ist – NPCs geben Hinweise
  • Belohnungen: Nach jedem Rätsel eine Belohnung – ein neues Item, eine Cutscene, eine neue Tür
  • Mehrere Wege: Dialog-Bäume und bedingte Ausgänge ermöglichen verschiedene Spielwege

Balance & Schwierigkeit

  • Kampfsystem: Feinde mit 100–200 HP, Waffen mit 20–40 Schaden gibt 3–8 Treffer pro Kampf
  • Rezepte: Nicht mehr als 2–3 Kombinationsschritte hintereinander – sonst wird's frustierend
  • Hinweise: Wenn Rätsel schwer sind, sollte mindestens ein NPC einen Tipp geben können
  • Sackgassen vermeiden: Teste jeden möglichen Weg – gibt es eine unbeabsichtigte Situation wo der Spieler feststeckt?

Atmosphäre & Stil

  • Themes konsequent einsetzen: Wechsle das Theme nur bei wichtigen Momenten – zu viele Wechsel wirken unruhig
  • Beschreibungen: Atmosphäre geht vor Fakten. "Es riecht modrig, ein Tropfen fällt in die Stille" ist besser als "Ein Keller, 3x4 Meter."
  • NPC-Persönlichkeit: Jeder NPC sollte eine eigene Sprache haben – Händler reden von Profit, Wachen von Pflicht
  • Cutscenes sparsam: Cutscenes sind emotionale Höhepunkte – zu viele davon verlieren ihre Wirkung

Typische Spielmuster als Vorlage

🔑 Schlüssel-Tür

Item finden → an Objekt verwenden → Flag setzen → Ausgang freischalten. Das klassischste Muster.

📜 Boten-Quest

Item A von NPC A erhalten → Item A zu NPC B bringen → Belohnung erhalten. Gut für strukturierte Quests.

⚗️ Mehrstufiges Crafting

Item A + Item B = Item C → Item C + Item D = Item E → Item E auf Objekt anwenden. Gut für Rätsel die Vorausdenken erfordern.

⚔️ Boss mit Belohnung

NPC mit maxHP → mit Waffe bekämpfen → onDefeat gibt Item und setzt Flag → Game End wird ausgelöst.

🎭 Geschichte mit mehreren Enden

Dialog-Baum mit setFlag → verschiedene Flags führen zu verschiedenen

📜
Quests – ein Hinweis
Warum der Tab entfernt wurde

Quests werden durch Flags ersetzt

Der Quest-Tab wurde aus dem Editor entfernt, weil das Quest-System im Player nie implementiert war – Quests wurden im JSON gespeichert, aber nie angezeigt oder ausgewertet. Für eine sichtbare, abhakbare Aufgabenliste gibt es stattdessen das 🎯 Aufgaben-System (Kapitel 10) – das ist im Player voll umgesetzt (Fortschrittsbalken, Durchstreichen erledigter Ziele, Geheimziele).

⚠️
Bestehende Spiele: Wenn dein JSON ein "quests": [...]-Feld enthält, schadet das nicht – der Player ignoriert es einfach. Du musst nichts ändern.

So baust du Quest-Mechaniken mit Flags

Alles was ein Quest-System leisten soll, lässt sich vollständig mit dem Flag-System abbilden:

Beispiel: Mehrstufige Quest "Brot backen"
// Schritt 1: Rezept – Mehl + Wasser = Teig
{ "item1": "mehl", "item2": "wasser", "result": "teig" }

// Schritt 2: NPC nimmt das Brot entgegen
"receivesItems": [{
 "itemId": "brot",
 "message": "Danke! Hier hast du deine Belohnung.",
 "givesItemId": "gold",
 "setFlag": "brot_abgegeben"
}]

// Schritt 3: Spielende wenn Quest abgeschlossen
"win": [{
 "type": "flag",
 "value": "brot_abgegeben",
 "message": "Du hast die Aufgabe erfüllt!"
}]
💡
Fortschrittsanzeige für den Spieler? Am einfachsten über das 🎯 Aufgaben-System (sichtbare Zielliste mit Balken). Alternativ über NPC-Dialoge mit flagBranch – der NPC sagt etwas anderes, je nachdem ob die Flag schon gesetzt ist.

Cutscene nach Objekt-Aktion

Nach einer erfolgreichen usableWith-Aktion kann automatisch eine Cutscene gestartet werden. Optional: nur einmal abspielen (playCutsceneOnce: true). Im Editor: Itemverwendung bearbeiten → „🎬 Cutscene nach Verwendung".

JSON-Format
"usableWith": [
  {
    "itemId": "zauberstab",
    "success": "Ein magisches Tor öffnet sich!",
    "playCutscene": "magie_cutscene",
    "playCutsceneOnce": true,
    "setFlag": "tor_offen"
  }
]

Konditionaler NPC-Dialog

Für einfache Fälle ohne Dialog-Baum: Der Gesprächstext eines NPCs wechselt automatisch je nach Flag-Zustand. Erste passende Bedingung gewinnt, Fallback auf den Standard-Dialog. Im Editor: NPC bearbeiten → Reiter „🔀 Konditional" beim Dialog-Feld.

JSON-Format
"npcs": {
  "papa": {
    "name": "Papa",
    "dialog": "Hast du den Schraubendreher?",
    "conditionalDialogs": [
      {
        "flag": "gegeben_schraubendreher",
        "dialog": "Danke! Ich repariere das gleich."
      },
      {
        "flag": "werkzeugkiste_leer",
        "dialog": "Die Werkzeugkiste ist jetzt leer..."
      }
    ]
  }
}

Für komplexere Gespräche mit Auswahloptionen → Dialog-Baum (dialogTree) verwenden.

Standard / Konditional – Tab-System im Editor

Alle konditionalen Inhalte sind im Editor über ein einheitliches Zwei-Reiter-System erreichbar. Der Reiter Standard zeigt den normalen Inhalt, Konditional die Flag-abhängigen Varianten. Hat ein Objekt bereits Einträge, öffnet sich der Konditional-Reiter automatisch mit Badge-Zähler.

WoWas
Objekte (Items)Bild · Beschreibung
OrteBild · Beschreibung
NPCsPortrait · Dialog
⚠️
Wichtig bei Raum-Objekten, die zugleich Items sind (z.B. ein Sicherungskasten, ein Mikrofon): Ein Raum-Objekt verweist nur auf ein Item. Seine Beschreibung – auch die bedingte – steht an der Item-Definition und wird dort bearbeitet (Tab 📦 Objekte → Item → Beschreibung → Reiter Konditional). Klickt man im Spiel das Objekt an, zeigt der Player immer die Item-Beschreibung. Eine bedingte Beschreibung, die direkt am Raum-Objekt hinterlegt wird, wird hingegen ignoriert. Im Tab 📍 Orte legst du nur fest, welches Item wo steht und ob man es nehmen kann.
🌐
QR-Modus & Geheimwörter
Das Abenteuer verlässt das Sofa: QR-Kärtchen an echten Orten · neu in v5.0

Das Prinzip: Anwesenheitsbeweis per QR

Der QR-Modus verbindet dein Adventure mit der echten Welt. Auf jedem gedruckten Kärtchen steht ein Geheimwort (z. B. TROPFENFANG-42) — als Text und im QR-Code daneben. Der QR ist bloß die schnelle Art, es zu lesen; abtippen geht immer.

Wo das Wort lebt: In der Spieldatei liegt nur ein Fingerabdruck (SHA-256) — wer die Datei öffnet, findet das Wort nicht. Es existiert allein auf dem Papier, am echten Ort.

Darum ist der Scan zweierlei: Er beweist die Anwesenheit — und löst im selben Moment die Handlung aus. Der Spieler hält die Gießkanne an den Wasserhahn, der Scanner geht auf, er scannt am echten Hahn — und die Kanne füllt sich. Technisch setzt das Wort ein 🚩 Flag, und Flags können alles: Türen öffnen, Aufgaben abhaken, Jagden verketten. Kein Server, kein Account, keine App.

💡
Alles ist optional. Ein Spiel ohne Geheimwörter verhält sich byte-genau wie bisher — offline, als Datei, im Packager-Standalone. Der 🗝️-Knopf erscheint nur, wenn das Spiel Geheimcodes enthält.
WerkzeugWer nutzt esZweck
qr-bogen.html🗝️ SpielleiterStationen anlegen, Geheimwörter würfeln, 🔒 verschlüsselt exportieren, druckfertige QR-Kärtchen
player.html📷 SpielerDer QR-Scanner ist fest eingebaut — keine Zusatzdatei, kein Nachladen. Der Player ist eine einzige Datei.
📦
Zum Verteilen brauchst du nur zwei Dateien: player.html und dein Spiel-JSON. Sonst nichts. (Und im Packager-Standalone wird sogar daraus eine Datei.)

Datenschutz: Es gibt nichts zu schützen — kein Server, keine Konten, keine Standortdaten. Die Kärtchen hängen an der Wand, das Spiel läuft auf dem Handy.

⚙️ Den QR-Modus einschalten

Tab 🎨 Anzeige → 📷 QR-Modus → „QR-Modus aktivieren" (technisch: displaySettings.qrModeEnabled).

Erst dann erscheinen im Editor die Felder „📷 QR-Scan verlangen" an Ausgängen und Objekt-Aktionen sowie das Akkordeon 🗝️ Geheimwörter. Für reine Solo-Spiele lässt du ihn aus — dann bleibt der Editor aufgeräumt.

↩️
Altbestand wird erkannt: Spiele, die schon Geheimwörter enthalten, gelten automatisch als QR-Spiele — der Schalter steht beim Laden von selbst auf „an“. Du musst nichts nachtragen.
⚠️
Kein Live-Umschalter im Player — anders als Parser und Nur-Text. Wer den QR-Modus mitten im Spiel abschalten könnte, würde alle Tore öffnen und vom Sofa aus gewinnen. Streikt die Kamera, tippt der Spieler das Wort — das er immer noch vom echten Ort braucht.

🗝️ Geheimwörter im QR-Modus

Geheimwörter verbinden das Spiel mit echten Orten: An der Station hängt ein QR-Kärtchen, das Team scannt oder tippt das Wort — im Spiel wird ein Flag gesetzt. Damit lassen sich Orte freischalten, Aufgaben abhaken, Jagden verketten. Das Datenformat im Spiel-JSON:

{
 "secretCodes": {
  "MONDSTEIN-47": {                       // Klartext-Variante
   "flag": "garten_gefunden",           // wird beim Eintippen gesetzt
   "reply": "🗝️ Der Gartenstein!",       // Antwort im Spiel (optional)
   "requireFlag": "keller_geloest",     // wirkt erst danach (optional)
   "lockedReply": "Noch nicht …"       // Antwort solange gesperrt (optional)
  },
  "#a3f19c…64 Hex…": { "flag": "…" }   // 🔒 verschlüsselte Variante (Standard)
 }
}

Workflow: Du schreibst das nicht von Hand — qr-bogen.html erledigt alles: Spiel laden, Stationen anlegen (Flags kommen als Vorschläge), exportieren. Beim Export entstehen zwei Dateien: die Spieldatei für den Server (Geheimwörter standardmäßig nur als 🔒 Fingerabdruck — neugierige Spieler können sie nicht herauslesen) und eine Planungsdatei mit dem Klartext, die bei dir bleibt und sich zum Weiterbearbeiten wieder laden lässt. Dazu der druckfertige Kärtchen-Bogen.

Im Spiel: Bei Spielen mit Geheimcodes erscheint automatisch der goldene 🗝️ Geheimwort-Knopf in der Kopfleiste (alle drei Spielmodi). Der Dialog bietet auf HTTPS-Seiten zusätzlich 📷 Scannen per Handykamera — der Scanner ist fest im Player eingebaut, es gibt nichts nachzuladen und nichts danebenzulegen. Er funktioniert deshalb auch im WLAN-Funkloch an der Station. Tippen geht immer, auch offline und im Standalone (dort ist der Kamera-Knopf mangels HTTPS ausgeblendet — der QR enthält das Wort ja als Text).

⚠️
Ehrliche Grenze der Verschlüsselung: Der Fingerabdruck verhindert das Ablesen aus der Datei, nicht beliebiges Durchprobieren. Ratbare Wörter („KELLER") bleiben knackbar — die gewürfelten Wörter (MONDSTEIN-47) oder eigene, unratbare verwenden. Mit requireFlag verkettete Jagden verhindern zusätzlich jedes Vorspringen.

🌐 Spiel verteilen

Zwei gleichwertige Wege, die QR-Fassung zu den Gruppen zu bringen:

WegWieWann sinnvoll
WebspaceSpiel-JSON neben player.html hochladen (mehr nicht — der Scanner steckt im Player) → Link player.html?JSON=dateiname weitergeben, gern als QR am StartpunktEin Link für alle; 📷 Kamera-Scan funktioniert (HTTPS)
Packager-StandalonePlayer + Spiel-JSON zu einer Datei bündeln, vorab aufs HandyGanz ohne Netz; Wörter werden getippt (der QR enthält das Wort als Text)

Der ?JSON=-Parameter akzeptiert auch absolute URLs — Spiel und Player dürfen auf verschiedenen Servern liegen.

📚 Weiterführende Dokumente

Für den kompletten Weg gibt es zwei eigene Anleitungen: SOLO-ZU-QR-ANLEITUNG (Schritt für Schritt an der Fittonie — dem kleinsten Spiel: zwei Kärtchen, ein Wasserhahn, eine Zimmerpflanze. Zeigt das qr_-Schema, mit dem jedes Solo-Spiel QR-fähig wird). Spielideen und Genre-Rezepte: SPIELIDEEN und SPIELARTEN-UEBERSICHT.

🚪 Physische Tore: So baust du eines — Schritt für Schritt

Der stärkste Baustein im QR-Modus ist ein Ausgang, der den Spieler wirklich an den echten Ort schickt — optional kombiniert mit einer Bedingung aus dem Spiel. Kopf und Füße.

Die Grundregel: Ein QR-Code kann genau eines — ein Flag setzen. Er legt nie Gegenstände ins Inventar. Die Immersion liefert die Antwort des Geheimworts („🚪 Klick! Ihr steht wirklich hier — die Tür ist entriegelt.“).

SchrittWoWas
1Editor, Tab 🚩 FlagsFlag anlegen: qr_backstage_offen (Startwert aus). Namensregel: Jedes Flag mit qr_ kommt aus der echten Welt.
2Editor, Tab 📍 Orte → Ausgang bearbeitenFeld 📷 QR-Scan verlangen (QR-Tor)qr_backstage_offen, dazu die Aufforderung („Nur autorisiertes Personal …“). Optional zusätzlich ☑️ Benötigt Item — dann gilt Kopf und Füße: Erst wird das Item geprüft, dann öffnet sich der Scanner.
3Editor, ⚙️ Features → 🗝️ GeheimwörterWort LICHTBLICK-42 → setzt qr_backstage_offen. Im Klartext — verschlüsselt wird erst beim Export.
4qr-bogenSpiel laden → Stationsort eintragen („Echte Backstage-Tür“) → 🔒 exportieren. Druckt die Kärtchen und verschlüsselt in einem Zug.
5Editor, Tab 🚩 Flags🔍 Kontrolle: Flag anklicken → „Wo wird dieses Flag benutzt?“ Unter 🔎 GEPRÜFT VON muss das QR-Tor stehen. Sonst läuft es ins Leere.
🚫
Der Verwehr-Text ist der wichtigste Satz. Er erscheint statt „Weg versperrt“ und entscheidet über Frust oder Aha-Moment. Er darf ruhig verraten, wo die fehlenden Dinge zu finden sind: „Die Tür ist zu — hier braucht ihr BEIDES: 🔦 die Taschenlampe (Requisitentisch im Backstage) UND den Türcode von der echten Technikraum-Tür.“
🛟
Rettungsweg-Regel: Jedes Item-Flag braucht einen zweiten Weg im Spiel (zum Beispiel: ein NPC vergibt per Rätsel dieselbe Taschenlampen-Flag) — sonst wird aus Vergesslichkeit ein Kilometer Rückweg. Beim Tür-Flag ist das anders und beabsichtigt: Da soll man hingehen müssen.
🔗
Zwei Schlösser, nicht verwechseln: Die Voraussetzung im qr-bogen steuert die Reihenfolge der Stationen. Das Benötigt-Flag am Ausgang steuert den Weg im Spiel. Ausführlich mit durchgespieltem Beispiel: SOLO-ZU-QR-ANLEITUNG.

🗝️ Geheimwörter im Editor anlegen (neu in v5.0)

Ein Geheimwort ist ein Wort (oder eine Zahl), das ein Flag setzt — der Spieler tippt es über den 🗝️-Knopf ein. Damit baust du Zahlenschlösser, Passwörter und Rätsel-Lösungen. Im QR-Modus wird genau daraus der QR-Code an einem echten Ort.

Anlegen: Tab ⚙️ Features → Akkordeon 🗝️ Geheimwörter → „➕ Geheimwort“.

FeldBedeutung
Wort/ZahlWird automatisch normalisiert (Großschrift, A–Z 0–9 und Bindestrich). Unratbar halten: MONDSTEIN-47, nicht KELLER.
setzt FlagWas das Wort bewirkt.
Antwort im SpielWas der Spieler liest: „🔓 KLACK! Das Schloss springt auf.“
VoraussetzungDas Wort wirkt erst, wenn ein früheres Flag gesetzt ist — so wird die Jagd sequenziell.
Antwort bei SperreDer Wegweiser: „Ihr steht am richtigen Ort — aber sprecht erst mit dem Zeugen!“
🔒
Klartext vs. verschlüsselt: Im Editor stehen die Wörter im Klartext — gut zum Bauen und Testen. Für den echten Einsatz exportierst du das Spiel einmal durch den 🗝️ QR-Bogen: Der verschlüsselt die Wörter (im Spiel steht dann nur ein Fingerabdruck) und druckt die Kärtchen. Bereits verschlüsselte Wörter erkennt der Editor und schützt sie.

📷 Das QR-Tor: Der Ort wird zur Spielmechanik — neu in v5.1

Ein Ausgang oder eine Objekt-Aktion kann verlangen, dass der QR-Code am echten Ort gescannt wird. Der Ausgang bleibt sichtbar (markiert mit 📷) — beim Klick öffnet sich sofort der Scanner, und nach dem richtigen Wort läuft die Handlung direkt weiter. Kein „erst scannen, dann nochmal klicken“.

Feld im EditorWoBedeutung
📷 QR-Scan verlangen (QR-Tor)Ausgang bearbeiten · Objekt-AktionFlag, das nur ein Geheimwort setzen kann
AufforderungdanebenDer Text im Scanner-Dialog („📷 Bist du wirklich dort?“)

Im JSON heißt das Feld qrGate (plus optional qrPrompt). Fehlt es, verhält sich alles exakt wie bisher — Solo-Abenteuer merken nichts davon.

🎯 Kopf und Füße: Rätsel UND Ort

Der stärkste Baustein entsteht, wenn du beides verlangst — im Spiel lösen und am echten Ort stehen. An einer Objekt-Aktion geht das direkt:

  1. Benötigt Flag = das Rätsel-Flag (z. B. lina_bereit) → der Kopf
  2. 📷 QR-Tor = das qr_-Flag → die Füße

Die Reihenfolge im Player ist bewusst gewählt: Erst werden die Spiel-Bedingungen geprüft, dann das QR-Tor. Wer das Rätsel noch nicht gelöst hat, bekommt die normale Absage — und wird nicht sinnlos zum Scannen geschickt. Erst wenn nur noch der Ort fehlt, geht die Kamera auf.

⚠️
Bei Aktionen: Tor-Flag ≠ Wirkungs-Flag. Eine Aktion tut etwas (Text, Bildwechsel, setFlag). Wären Tor-Flag und Wirkungs-Flag dasselbe, könnte jemand das Wort am 🗝️-Knopf eintippen: Das Flag wäre gesetzt, aber die Aktion liefe nie — Erfolgstext und Cutscene blieben aus. Darum: qr_strom_an öffnet das Tor, die Aktion setzt strom_an.
Bei Ausgängen entfällt das: Sie haben keine Nebenwirkung, ein Flag genügt.
🔍
Der Flag-Inspektor kontrolliert dich. Tab 🚩 Flags → Flag anklicken → „Wo wird dieses Flag benutzt?“ Er listet jede Stelle auf, die das Flag prüft, setzt oder löscht — und warnt: „⚠️ Dieses Flag läuft ins Leere!“, wenn ein qr_-Flag gesetzt, aber nirgends abgefragt wird. Genau dieser Fehler bleibt sonst bis zum Spieltag unsichtbar.
🧭
Die Design-Regel: Ein QR-Code gehört nur dorthin, wo es einen echten Grund gibt, Anwesenheit zu beweisen („Nur autorisiertes Personal“, „Schaltungen nur vor Ort quittieren“). Nicht jede Tür bekommt einen Scan — sonst wird aus dem Abenteuer eine Stempelkarte. Wechsle zwischen Kopf und Füßen.