Skip to content

Interaktionstypen-Referenz

Interaktionen sind der einheitliche Aktionsbaukasten von IfRPG. Dieselben Typen werden in Entity-States, Level-Triggern, Questfolgen, Achievement-Folgen und globalen Triggern verwendet. Wer diese Seite beherrscht, versteht damit den größten Teil der Laufzeitlogik des Spiels.

Wo Interaktionen verwendet werden

Interaktionen können an allen Stellen eingesetzt werden, an denen das Spiel auf ein Ereignis reagieren soll:

  • onInteract und onTouch von Entities
  • onEnter und onFirstLoad eines Levels
  • onFinish und onFail von Quests
  • onFinish von Erfolgen
  • globale Trigger in den Global Settings

Je nach Kontext wird entweder eine einzelne Interaktion oder eine Liste von Interaktionen gespeichert. Mehrere Interaktionen werden immer in der angegebenen Reihenfolge ausgeführt.

Allgemeine Struktur

Ein minimaler Interaktionsblock sieht so aus:

{
  "type": "text",
  "text": "Willkommen im Labor."
}

Mehrere Schritte hintereinander werden als Array gespeichert:

[
  {
    "type": "play_sfx",
    "sfx": "ui/quest-unlock.mp3"
  },
  {
    "type": "quest",
    "questId": "beispiele/quest_mermaid_drohne"
  }
]

Wichtige Grundregeln

  • Medienpfade wie mediaId, sfx oder voice sind immer relative Projektpfade innerhalb der registrierten Medienlisten.
  • Positionsfelder wie targetX und targetY arbeiten auf Tile-Basis.
  • Bedingungen in branch und while-loop verwenden dieselbe Bedingungssprache wie States und andere Logikbereiche.
  • Verschachtelung ist erlaubt. Besonders häufig sind branch, while-loop und Interaktionslisten in ifInteraction und elseInteraction.

Ausgabe und UI

text

Zeigt einen Text direkt im Spiel an, meist als Sprechblase oder kurzes Ingame-Feedback.

Wichtige Felder:

  • text
  • optional entityId
  • optional voice

Minimalbeispiel:

{
  "type": "text",
  "text": "Die Tür ist verschlossen."
}

Typische Stolperstelle: Wenn entityId gesetzt wird, sollte diese Entity im aktuellen Kontext auch wirklich vorhanden sein. Sonst erscheint der Text nicht dort, wo erwartet.

text_dialog

Öffnet einen modalen Textdialog mit Bestätigung. Dieser Typ ist sinnvoll für längere Hinweise, Einführungen oder kleine Zwischensequenzen.

Wichtige Felder:

  • title
  • text
  • optional confirmText
  • optional voice

Minimalbeispiel:

{
  "type": "text_dialog",
  "title": "Hinweis",
  "text": "Du brauchst zuerst den Werkstattschlüssel.",
  "confirmText": "Verstanden"
}

Typische Stolperstelle: text_dialog ist bewusst modal. Wenn eine Szene parallel weiterlaufen soll, ist text meist die bessere Wahl.

journal

Schaltet einen Journaleintrag frei und öffnet das Journal.

Wichtige Felder:

  • journalId

Minimalbeispiel:

{
  "type": "journal",
  "journalId": "grundlagen/variablen"
}

Typische Stolperstelle: Der Eintrag muss in der aktuellen Welt oder global vorhanden sein. Ein falscher journalId-Wert erzeugt keine sinnvolle Rückmeldung.

journal-popup

Schaltet einen Journaleintrag frei und zeigt ihn sofort als Popup an. Das ist der richtige Typ für neue Hilfeseiten oder Storytexte, die direkt im Moment der Freischaltung sichtbar sein sollen.

Wichtige Felder:

  • journalId

Minimalbeispiel:

{
  "type": "journal-popup",
  "journalId": "hilfe/if_else"
}

Typische Stolperstelle: journal-popup ist stärker eingreifend als journal. Für stille Freischaltungen ohne Unterbrechung ist journal besser geeignet.

show_image

Zeigt ein Bild im Spiel an.

Wichtige Felder:

  • mediaId
  • optional fullscreen

Minimalbeispiel:

{
  "type": "show_image",
  "mediaId": "images/story/karte.png",
  "fullscreen": true
}

Typische Stolperstelle: mediaId muss auf einen registrierten Bildpfad zeigen. Reine Dateinamen ohne korrekten Ordnerpfad reichen nicht.

show_video

Zeigt ein Video im Spiel an.

Wichtige Felder:

  • mediaId
  • optional fullscreen
  • optional autoplay

Minimalbeispiel:

{
  "type": "show_video",
  "mediaId": "videos/intro.mp4",
  "fullscreen": true,
  "autoplay": true
}

Typische Stolperstelle: Für kurze Zwischensequenzen ist autoplay sinnvoll. Für Lernvideos oder erklärende Clips kann es besser sein, die Wiedergabe bewusst vom Benutzer starten zu lassen.

Audio und Medien

play_music

Setzt oder wechselt die Hintergrundmusik.

Wichtige Felder:

  • mediaId

Minimalbeispiel:

{
  "type": "play_music",
  "mediaId": "music/village-theme.mp3"
}

Typische Stolperstelle: Musikwechsel wirken global. Wer einen nur kurzen Effekt möchte, sollte eher play_sfx verwenden.

stop_music

Stoppt die aktuell laufende Hintergrundmusik.

Minimalbeispiel:

{
  "type": "stop_music"
}

Typische Stolperstelle: stop_music setzt keine neue Stille-Definition für spätere Level. Beim nächsten Musikwechsel oder Levelwechsel kann wieder andere Musik starten.

play_sfx

Spielt einen Soundeffekt ab.

Wichtige Felder:

  • sfx

Minimalbeispiel:

{
  "type": "play_sfx",
  "sfx": "ui/success.mp3"
}

Typische Stolperstelle: Soundeffekte eignen sich für unmittelbares Feedback. Für Sprache oder längere Audioausgabe sind play_voice oder Musikwechsel meist passender.

play_voice

Spielt eine Sprach- oder Kommentarspur ab.

Wichtige Felder:

  • voice

Minimalbeispiel:

{
  "type": "play_voice",
  "voice": "tutorial/welcome.mp3"
}

Typische Stolperstelle: Sprache und text oder text_dialog sollten inhaltlich zusammenpassen. Audio ohne sichtbaren Text ist im Unterricht oft schwerer nachvollziehbar.

Variablen, Switches und Logik

script

Steuert einen Switch. Der Typname ist historisch gewachsen; fachlich handelt es sich um eine Switch-Aktion.

Wichtige Felder:

  • switchId
  • optional switchValue

Minimalbeispiel:

{
  "type": "script",
  "switchId": "labor_tuer_offen",
  "switchValue": true
}

Typische Stolperstelle: Wenn switchValue fehlt, wird der Switch umgeschaltet. Das ist praktisch, aber in komplexen Szenen schwerer zu lesen als ein explizites true oder false.

variable

Verändert eine Variable. Unterstützt werden direktes Setzen, mathematische Formeln und String-Ersetzungen per regulärem Ausdruck.

Wichtige Felder:

  • variableInteraction.targetId
  • variableInteraction.operation
  • je nach Operation: value, formula, regex, replacement

Minimalbeispiel für direktes Setzen:

{
  "type": "variable",
  "variableInteraction": {
    "targetId": "gold",
    "operation": "set",
    "value": 25
  }
}

Minimalbeispiel für Mathematik:

{
  "type": "variable",
  "variableInteraction": {
    "targetId": "xp",
    "operation": "math",
    "formula": "xp + 10"
  }
}

Typische Stolperstelle: Die Formel arbeitet mit dem bestehenden Variablennamen. Ein Tippfehler in targetId oder in der Formel führt zu unerwarteten Ergebnissen.

branch

Führt abhängig von einer Bedingung unterschiedliche Interaktionen aus.

Wichtige Felder:

  • condition
  • ifInteraction
  • optional elseInteraction

Minimalbeispiel:

{
  "type": "branch",
  "condition": "gold >= 10",
  "ifInteraction": {
    "type": "text",
    "text": "Du kannst den Schlüssel kaufen."
  },
  "elseInteraction": {
    "type": "text",
    "text": "Dir fehlt noch Geld."
  }
}

Typische Stolperstelle: Die Interaktionen in ifInteraction und elseInteraction sind einzelne Blöcke. Für längere Folgen sollte dort jeweils eine Interaktionsliste verwendet werden.

while-loop

Wiederholt Interaktionen, solange eine Bedingung wahr ist. Dieser Typ ist vor allem für kleine Cutscenes, visuelle Folgen oder wiederholte Variablenänderungen gedacht.

Wichtige Felder:

  • condition
  • interactions

Minimalbeispiel:

{
  "type": "while-loop",
  "condition": "akku < 100",
  "interactions": [
    {
      "type": "variable",
      "variableInteraction": {
        "targetId": "akku",
        "operation": "math",
        "formula": "akku + 10"
      }
    }
  ]
}

Typische Stolperstelle: Die Bedingung muss sich innerhalb der Schleife irgendwann ändern. Sonst entsteht eine Endlosschleife.

timer

Verzögert die weitere Ausführung um eine bestimmte Zeitspanne.

Wichtige Felder:

  • duration

Minimalbeispiel:

{
  "type": "timer",
  "duration": 1.5
}

Typische Stolperstelle: duration wird in Sekunden angegeben. Sehr kleine Werte können visuell kaum erkennbar sein, sehr große Werte lassen Szenen schnell träge wirken.

Quests, Erfolge und Freischaltungen

quest

Schaltet eine Quest frei oder öffnet sie.

Wichtige Felder:

  • questId
  • optional optional

Minimalbeispiel:

{
  "type": "quest",
  "questId": "beispiele/quest_nsd_akkupruefer",
  "optional": false
}

Typische Stolperstelle: optional steuert die Einordnung im Questbereich. Für Pflichtquests sollte dieser Wert bewusst gesetzt bleiben oder weggelassen werden.

achievement

Vergibt oder entzieht ein Achievement.

Wichtige Felder:

  • achievementId
  • optional achievementOperation

Minimalbeispiel:

{
  "type": "achievement",
  "achievementId": "erste_klasse",
  "achievementOperation": "unlock"
}

Typische Stolperstelle: revoke ist für Spezialfälle gedacht, etwa Debug- oder Resetpfade. In normalen Fortschrittssystemen ist unlock fast immer die richtige Operation.

changeSkin

Wechselt den aktiven Spielerskin. Dieser Typ wird eher über globale Trigger, Belohnungen oder spezielle Systempfade genutzt als über gewöhnliche Dialogaktionen.

Wichtige Felder:

  • targetSkinId

Minimalbeispiel:

{
  "type": "changeSkin",
  "targetSkinId": "zauberlehrling"
}

Typische Stolperstelle: Der Zielskin muss in den Settings definiert und freigeschaltet sein. Sonst hat die Aktion keine sinnvolle Wirkung.

changePet

Aktiviert oder wechselt einen Begleiter.

Wichtige Felder:

  • targetPetId

Minimalbeispiel:

{
  "type": "changePet",
  "targetPetId": "katze"
}

Typische Stolperstelle: Bei Welten ohne Pets wirkt der Typ wie ein stiller No-Op. Deshalb sollte er nur eingesetzt werden, wenn Begleiter im Projekt tatsächlich vorgesehen sind.

Eingaben

input_text

Öffnet einen Texteingabedialog und schreibt das Ergebnis in eine Variable.

Wichtige Felder:

  • title
  • text
  • variableInteraction.targetId
  • optional defaultValue

Minimalbeispiel:

{
  "type": "input_text",
  "title": "Name",
  "text": "Wie soll deine Drohne heißen?",
  "variableInteraction": {
    "targetId": "drohnen_name",
    "operation": "set"
  }
}

Typische Stolperstelle: Der Dialog speichert nur sinnvoll, wenn variableInteraction.targetId korrekt gesetzt ist.

input_number

Wie input_text, aber für numerische Eingaben.

Wichtige Felder:

  • title
  • text
  • variableInteraction.targetId

Minimalbeispiel:

{
  "type": "input_number",
  "title": "Energie",
  "text": "Wie hoch ist der Akkustand?",
  "variableInteraction": {
    "targetId": "akku",
    "operation": "set"
  }
}

Typische Stolperstelle: Die Zielvariable sollte inhaltlich und vom Datentyp her wirklich zu einer Zahl passen.

choice

Zeigt einen Ja-/Nein-Dialog und speichert die Auswahl in einem Switch.

Wichtige Felder:

  • title
  • text
  • switchId
  • optional trueLabel
  • optional falseLabel

Minimalbeispiel:

{
  "type": "choice",
  "title": "Abgabe",
  "text": "Willst du die Aufgabe jetzt abgeben?",
  "switchId": "aufgabe_abgegeben",
  "trueLabel": "Ja",
  "falseLabel": "Nein"
}

Typische Stolperstelle: choice speichert in einen Switch, nicht in eine Variable. Für freie Texte oder mehrere Optionen sind die anderen Eingabetypen besser geeignet.

input_choice

Zeigt mehrere auswählbare Optionen und speichert den gewählten Index in einer Variable.

Wichtige Felder:

  • title
  • text
  • choices
  • variableInteraction.targetId

Minimalbeispiel:

{
  "type": "input_choice",
  "title": "Werkzeug",
  "text": "Wähle dein Werkzeug:",
  "choices": ["Hammer", "Schraubenzieher", "Multimeter"],
  "variableInteraction": {
    "targetId": "werkzeug_index",
    "operation": "set"
  }
}

Typische Stolperstelle: Gespeichert wird der Index der Auswahl. Wer den eigentlichen Textwert braucht, muss ihn später über die Logik abbilden.

teleport

Wechselt in ein anderes Level derselben Welt und setzt den Spieler auf die Zielkoordinaten.

Wichtige Felder:

  • targetLevel
  • targetX
  • targetY

Minimalbeispiel:

{
  "type": "teleport",
  "targetLevel": "labor_2",
  "targetX": 8,
  "targetY": 14
}

Typische Stolperstelle: Wenn targetLevel stimmt, aber die Koordinaten ungünstig sind, wirkt der Teleport wie ein Spawn-Fehler. Deshalb Zielpunkte immer im Level testen.

switch_world

Wechselt in eine andere Welt.

Wichtige Felder:

  • targetWorld
  • optional targetLevel
  • optional targetX
  • optional targetY

Minimalbeispiel:

{
  "type": "switch_world",
  "targetWorld": "beispiele",
  "targetLevel": "campus_1",
  "targetX": 3,
  "targetY": 9
}

Typische Stolperstelle: Wenn targetLevel oder Koordinaten fehlen, greift der Fallback auf das konfigurierte Startlevel oder dessen Spawn. Das sollte bewusst genutzt und nicht dem Zufall überlassen werden.

move_player

Bewegt den Spieler automatisch.

Wichtige Felder:

  • targetX
  • targetY
  • optional moveSpeed
  • optional waitForCompletion
  • optional lookAt
  • optional lockControls

Minimalbeispiel:

{
  "type": "move_player",
  "targetX": 12,
  "targetY": 6,
  "moveSpeed": "walk",
  "waitForCompletion": true
}

Typische Stolperstelle: Ohne waitForCompletion laufen nachfolgende Aktionen sofort weiter. Für kleine Cutscenes ist der Wert oft wichtig.

move_npc

Bewegt eine bestimmte Entity automatisch.

Wichtige Felder:

  • entityId
  • targetX
  • targetY
  • optional moveSpeed
  • optional waitForCompletion
  • optional resumePath

Minimalbeispiel:

{
  "type": "move_npc",
  "entityId": "waechter_1",
  "targetX": 10,
  "targetY": 4,
  "moveSpeed": "run",
  "waitForCompletion": true,
  "resumePath": true
}

Typische Stolperstelle: entityId muss auf die konkrete Instanz verweisen, nicht auf ein Template.

attach

Hängt den Spieler oder eine Szene an eine Entity an. Dieser Typ wird vor allem für geführte Sequenzen, Begleitbewegungen oder Kamera-nahe Kopplungen genutzt.

Wichtige Felder:

  • entityId

Minimalbeispiel:

{
  "type": "attach",
  "entityId": "vogel_1"
}

Typische Stolperstelle: attach ist ein Spezialwerkzeug. Wer nur eine einmalige Bewegung auslösen möchte, fährt mit move_player oder move_npc meist einfacher.

unattach

Löst eine vorherige Kopplung wieder.

Wichtige Felder:

  • optional unattachDirection

Minimalbeispiel:

{
  "type": "unattach",
  "unattachDirection": "automatic"
}

Typische Stolperstelle: Wer attach nutzt, sollte unattach immer bewusst mitdenken. Sonst bleibt die Szene in einem gebundenen Zustand hängen.

Animation, Kontrolle und Effekte

play_animation

Spielt eine benannte Animation auf einer Entity oder im Interaktionskontext ab.

Wichtige Felder:

  • animationName
  • optional entityId
  • optional repeatCount

Minimalbeispiel:

{
  "type": "play_animation",
  "entityId": "portal_1",
  "animationName": "activate",
  "repeatCount": 1
}

Typische Stolperstelle: Der Animationsname muss zur Definition des States passen. Ein falscher Name führt nicht automatisch zu einer hilfreichen Fehlermeldung.

block_player_movement

Sperrt oder entsperrt die Spielersteuerung.

Wichtige Felder:

  • lockControls

Minimalbeispiel:

{
  "type": "block_player_movement",
  "lockControls": true
}

Typische Stolperstelle: Für jede Sperrung sollte auch ein klarer Entsperrpfad existieren. Sonst wirkt das Spiel „kaputt“, obwohl nur die Steuerung noch blockiert ist.

effects

Steuert Licht-, Wetter-, Atmosphären- und Transformations-Effekte.

Wichtige Felder:

  • effectMode
  • effectWeather
  • effectAtmosphere
  • effectTransformation
  • optional das Spielerlicht in night- und cave-Modi
  • optionale Intensitäten
  • optional isTemporary
  • optional duration

Verfügbare Werte:

  • effectMode: none, night, cave, alert, underwater
  • effectWeather: none, rain, snow, thunderstorm, fireworks, explosions
  • effectAtmosphere: none, fog, toxic, smoke, demonic
  • effectTransformation: none, earthquake, underwater, drunk, muffled

Die Intensitäten werden jeweils über Werte zwischen 0 und 1 gesteuert:

  • effectModeIntensity
  • effectWeatherIntensity
  • effectAtmosphereIntensity
  • effectTransformationIntensity
  • effectPlayerLightIntensity

Für das Spielerlicht stehen zusätzlich diese Felder zur Verfügung:

  • effectPlayerLightEnabled
  • effectPlayerLightRadius
  • effectPlayerLightColor
  • effectPlayerLightIntensity
  • effectPlayerLightFlicker
  • effectPlayerLightBlink
  • effectPlayerLightBlinkFrequency
  • effectPlayerLightBlinkPattern

Minimalbeispiel:

{
  "type": "effects",
  "effectMode": "night",
  "effectPlayerLightEnabled": false,
  "effectWeather": "rain",
  "effectWeatherIntensity": 0.6,
  "isTemporary": true,
  "duration": 5
}

Beispiel mit eigener Spielerbeleuchtung:

{
  "type": "effects",
  "effectMode": "cave",
  "effectPlayerLightEnabled": true,
  "effectPlayerLightRadius": 2.4,
  "effectPlayerLightIntensity": 0.9,
  "effectPlayerLightFlicker": true
}

Typische Stolperstelle: Temporäre Effekte brauchen eine sinnvolle Dauer. Nicht-temporäre Effekte bleiben aktiv, bis sie gezielt überschrieben oder beendet werden.

Typischer Workflow

Ein guter Ablauf beim Bauen komplexerer Interaktionen ist:

  1. Zuerst den eigentlichen Spielzweck klären: Text, Belohnung, Teleport, Variable oder Cutscene.
  2. Die Folge in kleine Schritte zerlegen statt sofort eine große verschachtelte Interaktion zu bauen.
  3. Zuerst lineare Folgen testen, dann branch oder while-loop ergänzen.
  4. Bewegungen, Timer und Effekte immer direkt im Spiel gegenprüfen.
  5. IDs für Quests, Journal, Erfolge, Entities und Medien konsequent aus den vorhandenen Definitionen wählen.

Häufige Fehler

  • Interaktionen verweisen auf falsche IDs für Quests, Journal, Erfolge oder Entities.
  • Bedingungen in branch oder while-loop werden nicht gegen echte Laufzeitdaten getestet.
  • Eine Schleife verändert ihre Abbruchbedingung nie und läuft deshalb endlos.
  • Bewegungsaktionen ohne waitForCompletion werden wie synchrone Sequenzen behandelt, obwohl sie parallel weiterlaufen.
  • Audio-, Medien- und Effektaktionen werden isoliert gepflegt, aber nie im Zusammenspiel mit Dialogen und Triggern getestet.