Serious Games GODOT Umsetzung Chainguard

Umsetzung eines Serious Games

Konzeptfindung

Die Pre-Production ist in der Regel die Phase der Konzeptfindung. Diese Phase ist ein kreativer und kollaborativer Prozess, an dessen Ende im besten Falle ein Game Design Document steht. Für das Game Design Document wurde ein Template verwendet.
Game Design ist ein kreativer Prozess. Das gilt auch für Serious Games. Für ein gutes Spiel-Konzept sind also gute Ideen erforderlich. Verschiedene Methoden zur Ideenfindung bieten sich an.
  • Brain-Storming
  • Recherche von Games(nicht nur Serious Games)
  • Auseinandersetzung mit dem Problemfeld
  • Auseinandersetzung mit der Zielgruppe
  • Low-Fidelity Prototyping (kleine Skizzen oder Stickynotes)
Diese Ideen sollen nicht besonders detailliert oder ausgereift sein. Ein wesentlicher Teil der konzeptuellen Entwicklung ist die Iteration von Ideen. Es sollte kein großer Fokus auf einzelne Ideen gesetzt werden, stattdessen sollten viele verschiedene Konzepte und Blickpunkte besprochen werden. Abhängig vom Projekt können auch externe Bedingungen in den Designprozess eingreifen. Es ist möglich, dass die Lerninhalte oder Zielgruppe bereits vorgegeben sind. Solche Einschränkungen sollten aber nicht die Offenheit für Inspirationen aus sachfremden Spielen hemmen. Das Konzept von Chainguard zum Beispiel, ist fast gänzlich von einem Spiel inspiriert, das nichts mit IT-Sicherheit zu tun hat. Wenn eine bestimmte Zielgruppe bereits gegeben ist, bietet es sich auch an, diese Zielgruppe in den Designprozess einzubinden, etwa durch Interviews oder Teilhabe am Designprozess.

Konzeptfindung bei ChainGuard

"[ChainGuard] ist ein Serious Game mit Fokus auf dem Erlernen der Grundkenntnisse der Malware-Detection. Die Spieler treten hier, angelehnt an das Spiel Papers, Please! vom Solo-Entwickler Lucas Pope, in die Rolle eines "Richters" dessen Entscheidungen den mechanischen Kern des Spieles darstellen. Diese Entscheidungen beschränken sich auf die Bewertung von Software oder Softwareartefakten. Diese sollen nämlich entweder als harmlos oder als schädlich identifiziert werden. Folglich nimmt der Spieler die Rolle eine Anti-Malware Software ein, die die Verantwortung für die Sicherheit des Systems trägt. In dieser Rolle stehen dem Spieler verschiedene Werkzeuge zur Enttarnung von schädlicher Software zur Verfügung. Diese Werkzeuge dienen gleichzeitig als Lerngegenstand, da sie verbreitete Methoden der Malware-Detection auf eine simplifizierte Weise repräsentieren und folglich die Nutzung dieser ein Verständnis für diese Methoden liefert."
— Aus der Beschreibung der Umsetzung des Spieles im Kapitel "Production"
Die Entscheidung, das Spiel an "Papers, Please!" anzulehnen gab dem Team ein einfaches aber auch inspirierendes Blueprint. Die Spielmechanik als eine behaviouristich bewertbare ja/nein Entscheidung zu beschränken, hat uns den Aufwand genommen, komplexe Spielmechaniken in einer größtenteils fremden Engine zu implementieren. Gleichzeitig bot das Konzept "Papers, Please" durch seine eigene komplexe Spielwelt die Inspiration für ein Spiel, dass trotz einfach erscheinender Mechaniken eine komplexe Umgebung bieten kann. Die Spielerentscheidung durfte folglich nicht einfach sein und musste von verschiedenen Faktoren abhängen. Das Gebiet der IT-Sicherheit als Lerngegenstand hat sich aufgrund unserer zumindest oberflächlichen Vertrautheit und der sich bietenden Komplexität gut angeboten. Aus Einreisenden in "Papers, Please" wurden Softwarekandidaten. Aus der Grenze und dem Beamten(Spieler) wurde das Virenschutzprogramm ChainGuard. Die größte Hürde der Konzeptionsphase war es, Malware-Detection Methoden zu finden, zu abstrahieren und als glaubwürdige Spielelemente darzustellen. Nach einer kurzen Recherche konnten wir aber Signaturgenerierung, Sandboxing und reverse Engineering als einfach und verständlich darstellbare Werkzeuge eines Virenschutzprogramms herausarbeiten. Die restlichen Mechaniken, wie ein Zeitlimit, die Bestrafungen bei falscher Bewertung oder das Register haben sich natürlich aus der Grundidee des Spieles ergeben.

Motivation - ein Spiel das Spaß macht

Wie bereits im Kapitel "Vorab, was zeichnet ein Serious Game aus?" erwähnt, sollen Serious Games auch einen Unterhaltungswert bieten. Dieser dient nicht zuletzt der Motivation und folglich auch dem Lerneffekt und ist somit auch ein integraler Bestandteil der Entwicklung von Serious Games. Im folgenden Abschnitt sollen Game Design Prinzipien, die zur Motivation der Spielenden und dadurch auch zum gewünschten Lerneffekt führen, aufgeschlüsselt werden.

Feedback - Bewertung - Belohnung

"Eine Aufgabe des Game Designs ist es, gezielte Anreize für ein motivierendes Spiel zu schaffen. Klassische motivierende Merkmale eines Computerspiels sind die Rückmeldung, die Bewertung, die Belohnung und das Spielziel.""
— Wolfgang Becker Maren Metz Digitale Lernwelten – Serious Games und Gamification(link), Zugriff 05.April.2026
Spiele als Interaktive Medien bauen auf der Wechselwirkung zwischen Spieler und Spiel auf. Ein befriedigendes Spielerlebnis setzt also auch befriedigende Interaktion - und dazu gehört Feedback - vorraus. Feedback bezeichnet im Allgemeinen die Reaktion der Spielwelt auf das Handeln des Spielers. Dieser soll das Gefühl bekommen, er habe Einfluss auf diese Welt und seine Entscheidungen seien von Bedeutung. Sogleich dient positives Feedback der psychologischen Bedürfnisbefriedigung des Spielers. Das heißt, wenn ein Spieler merkt, dass er in einem Spiel besser wird, ist er motivierter weiterzuspielen.
Ein Beispiel aus ChainGuard: Genehmigt der Spieler eine Malware(also macht er einen Fehler), so treten die negativen Folgen seines Handels sofort in Erscheinung. UI-Elemente werden entfernt, der Bildschirm flackert oder wird rot. Wenn ein Spieler jedoch einen Nicht-Malware-Kandidaten genehmigt, wird dies mit einem Zuschlag auf die kostbare Zeit belohnt. So wird der Spieler angetrieben, das Spiel besser und aufmerksamer zu spielen, sich die Spielmechaniken - also auch den Lerngegenstand - zu verinnerlichen und über seine Entscheidungen nachzudenken.

Die Angemessene Herausforderung

Die Schwierigkeit eines Spieles sollte zwar zum einen fordernd genug sein, um die Spielenden bei Laune zu halten und ein Gefühl des wahren Triumphes bei Vollendung des Spieles zu bieten. Eine zu harte Schwierigkeit kann jedoch zu Resignation führen. Ein ausgewogenes Maß an Schwierigkeit zu finden ist komplex und wirkt nach der Realisation, dass das beste Maß an Schwierigkeit für jeden anders ist, nahezu unmöglich. Hier hilft es, sich seiner Zielgruppe bewusst zu sein:
  • Sind die Personen in der Zielgruppe vertraut mit Lernspielen?
  • Welches Alter hat die Zielgruppe(Kind/Erwachsen)?
  • Wie vertraut ist die Zielgruppe mit dem Lerngegenstand?
Die Herausforderung sollte überdies nicht statisch sein. Die Spieler mit einfachen Aufgaben an die Grundmechaniken heranzuführen, um dann stetig die Herausforderung zu erhöhen ist eine in Videospielen omnipräsente Praxis. (Vgl. Begriff "Scaffolding" VL "Digitales Lehr- und Lernmanagement")

Immersion

...beschreibt den Zustand des vollkommenen Sichhineinversetzens. In einem Videospiel beschreibt dieser Zustand das Gefühl, Teil der Spielwelt zu sein. Die Folge dieses Zustandes ist, dass das Lernen nicht mehr als Aufgabe, sondern als natürliche Aktivität einer immersiven Umgebung angesehen wird. Dieser Zustand ist also für Serious Games nicht weniger von Bedeutung als für herkömmliche Videospiele. Es gibt verschiedene Wege, ein immersives Spielgefühl zu erzeugen. Sie lassen sich jedoch alle auf das Prinzip einer glaubhaften, lebhaften Spielwelt zurückführen. Eine glaubwürdige Welt wird im Wesentlichen durch Ihre Charaktere verkörpert. Ferner befriedigt die Interaktion mit glaubwürdigen Charakteren das psychologische Grundbedürfnis der sozialen Integration und trägt so zu einer motivierten Spielerfahrung bei. Die Charaktere einer immersiven Welt sollte man immer als Abbild der Welt als Ganzes verstehen. Das heißt, sich zu fragen: In was für einer Welt würde dieser Charakter leben? Oder was für Charaktere würden in dieser Welt leben? Eine immersive Spielwelt muss diese Fragen für den Spieler beantworten können.

Ein Beispiel aus ChainGuard:

Die Charaktere in dem Spiel sind die Kandidaten. Sie stellen sich dem Spieler durch ihre Beschreibungen vor und "wollen" alle (mehr oder weniger) vom Spieler als Nicht-Schadsoftware genehmigt werden. Da der Spieler aber weiß, dass er Schadsoftware entlarven muss, realisiert er schnell, dass ein großer Teil der Charaktere dieser Welt ihn anlügt. Dieser Eindruck wird mit dem eintönigen alten Windows User Interface kombiniert, um ein Gefühl einer dystopischen Spielwelt zu erzeugen, die aber durch ihr konsistentes Auftreten zur Immersion beitragen und zum Spielen anregen soll.

Wie strukturiere ich Lerninhalte für ein Serious Game?

Spiele als interaktive Medien bieten einzigartige Möglichkeiten und Herausforderungen. Die strukturelle Integration von Lerninhalten in eine Spielumgebung ist eine dieser Probleme.
Das, was gelernt werden soll, muss im Spiel real vorkommen, beispielsweise strategisches Denken, das Führen von Teams, Kooperation oder das Lösen von kombinatorischen Problemen und jede Menge mehr.
— Helmut Niegemann, Armin Weinberger Handbuch Bildungstechnologie(link), Zugriff 05.April.2026
Niegemann und Weinberger sprechen sich hier für eine aktive Umsetzung des Lerngegenstandes als Teil des Spieles aus. Was dieser Lerngegenstand ist - ob reines Faktenwissen oder Verständnis für ein komplexes System - beeinflusst die lerntheoretische Perspektive, die eingenommen werden muss.

Die behaviouristische Perspektive

...sieht Lernen als die Etablierung von Reiz-Reaktions-Mustern. Wichtig für das Design von Spielmechaniken: Eine Aufgabe hat immer die gleiche Lösung.
Dieser Ansatz bietet sich am meisten für die Vermittlung von Faktenwissen an. Als Beispiel für diese Praxis bietet sich die gamifizierte Sprachlern-App Duolingo an.
Genre die sich für behaviouristische Lernspiele eignen:
  • Quizspiele
  • Drill- & Practice-Spiele(zum Beispiel ein Piano-Lernspiel)
  • Denkspiele wie Sudoku

Die kognitivistische Perspektive

...sieht Lernen als einen aktiven Prozess des Lernenden(des Spielers). Es geht darum, das Problemlösen zu erlernen und eigene Vorgehensweisen zu entwickeln. Der Lerneffekt entsteht hier in erster Linie durch Testen und Ausprobieren. Das Spiel sollte dem Spieler nicht die Lösung, sondern Tipps geben.
Wichtig für das Design von Spielmechaniken: Eine Umgebung schaffen, in der eigene Strategien und Denkansätze ausprobiert werden können.
ChainGuard zum Beispiel versucht den Spieler dazu zu bringen, verschiedene Methoden der Malware-Detection auszuprobieren und seine eigene Strategie zum Abarbeiten der Kandidaten in begrenzter Zeit zu finden. Es ist nicht - so wie beim Behaviorismus - eine richtige Strategie vorgegeben.
Genre die sich für Kognitivistische Lernspiele eignen:
  • Offene Rätselspiele mit vielen verschiedenen Mechaniken(zB: Portal 2)
  • Detektiv- und Rätselspiele
  • Explorationsspiele

Die konstruktivistische Perspektive

...sieht Lernen als aktiven Konstruktionsprozess von Wissen durch den Lernenden(Spieler). Der Lerngegenstand wird durch eine tiefgreifendes Verständnis einer komplexen und realistischen Spielumgebung vermittelt. Daraus folgt, dass das Spiel selbst diesen komplexen Prozess ermöglichen und unterstützen muss.
Wichtig für das Design von Spielmechaniken: Eine Welt schaffen, deren Regeln und Mechaniken auf dem Lerngegenstand aufbauen.
So wie beim Kognitivismus, nimmt hier das Spiel selbst nur eine beratende Rolle ein.
  • Sandbox/Open-World-Spiele
  • Konstruktions- und Bau-Spiele (zum Beispiel Poly Bridge )
  • Rollenspiele (zum Beispiel um Geschichtswissen zu vermitteln)
Diese drei Perspektiven schließen sich Gegenseitig nicht aus- sie bauen aufeinander auf. Viele Serious Games bieten Lernerfahrungen aus verschiedenen Perspektiven. Ohne eine eindeutig behaviouristische Bewertung kann das Spielziel unklar erscheinen und ohne tiefgreifende und komplexe Mechaniken kann Immersion und Engagement leiden. Es gilt, eine Balance zu finden.
Zu einer tieferen Behandlung der Lerntheorien, Game-Design(MDA-Ansatz, ...), bieten sich die Lehrmaterialien des Moduls "Digitales Lehr- und Lernmanagement" an.

Proof of Fun

In zeitlich begrenzten Projekten gehört ein minimum viable Product (MVP) zu den größten Projekt-Meilensteinen. Ein MVP wird oft als ein Prototyp des geplanten Produktes verstanden - die simplifizierteste Version des Spieles.
Hier bietet es sich an, mit der Zielgruppe in Kontakt zu treten und sie in den Entscheidungsprozess zu involvieren, um elementare Funktionen herauszustellen. Die Konzeption eines MVP ist die Auflistung aller Features, die für die wichtigsten Spielmechaniken gebraucht werden. Diese Features sollten im Entwicklungsprozess priorisert werden.

Hollstrand Supporting Pre-Production in Game Development (Link), Zugriff 06. April 2026
Becker, Metz Digitale Lernwelten – Serious Games und Gamification (Link), Zugriff 06.April 2026
Przybylski, Rigby A Motivational Model of Video Game Engagement (Link), Zugriff 06. April 2026
Hyrynsalmi et al. What is a Minimum Viable (Video) Game? (Link), Zugriff 06. April 2026

ChainGuard

...ist ein Serious Game mit Fokus auf dem Erlernen der Grundkenntnisse der Malware-Detection. Die Spieler treten hier, angelehnt an das Spiel Papers, Please! vom Solo-Entwickler Lucas Pope, in die Rolle eines Richters dessen Entscheidungen den mechanischen Kern des Spielerlebnisses darstellen. Diese Entscheidungen beschränken sich auf die Bewertung von Software oder Softwareartefakten. Diese sollen nämlich entweder als harmlos oder als schädlich identifiziert werden. Folglich nimmt der Spieler die Rolle eine Anti-Malware Software ein, die die Verantwortung für die Sicherheit des Systems trägt. In dieser Rolle stehen dem Spieler verschiedene Werkzeuge zur Enttarnung von schädlicher Software zur Verfügung. Diese Werkzeuge dienen gleichzeitig als Lerngegenstand, da sie verbreitete Methoden der Malware-Detection auf eine simplifizierte Weise repräsentieren und folglich die Nutzung dieser ein Verständnis für diese Methoden liefert.
Screenshot von Chainguard

Kandidaten

Die Kandidaten sind Spielobjekte, die Software(-artefakte) repräsentieren. Sie sind ein Teil der Nutzeroberfläche im Spiel und lassen sich per Drag&Drop verschieben. Zum Anfang des Spieles befinden sich alle Kandidaten in einer scrollbaren Warteschlange am linken Rand des Fensters. Ein Icon gibt einen ersten Hinweis über die Natur des Kandidaten. Die Kandidaten können per Drag&Drop in verschiedene Komponenten des Spieles eingefügt werden: die Sandbox, Reverse-Engineering-Box, Signatur-Box und das Kontrollpanel. Die Boxen repräsentieren die oben erwähnten Werkzeuge, mit denen ein Kandidat analysiert werden kann.

Das Register

Das Register bietet dem Spieler einen Katalog an Informationen, die er in seiner Bewertung der Kandidaten nutzen soll. Neben einer Tabelle mit bereits als schädlich identifizierten Signaturen bietet das Register eine Liste an System-Calls, die von bestimmten Arten von Software genutzt werden. So kann der Spieler(sobald er die genutzten Systemaufrufe einer Software herausgefunden hat) einschätzen, ob ein Kandidat auf Resourcen zugreift die er eigentlich nicht brauchen sollte und kann so Schlüsse auf die Integrität des Kandidaten ziehen.

Die Signatur-Box

In diesem Gadget kann, wie bereits oben erwähnt, ein Kandidat eingesetzt werden. Nach einer Wartezeit von 20 Sekunden wird dann per Click auf die Signatur-Box eben diese Signatur im Informationsfeld angezeigt. Diese kann mit der Liste im Register abgeglichen werden um schädliche Signaturen zu identifizieren.

Die Sandbox

Die Sandbox bietet eine abstrahierte Darstellung der dynamischen Codeanalyse für Malwarekandidaten. Der Spieler kann einen Kandidaten in diese Sandbox einfügen und mit einer gewissen Wahrscheinlichkeit, und wenn der Kandidat eine Malware ist, wird sich diese Sandbox rot färben und somit dem Spieler die böswillige Natur des Kanidaten zeigen.

Die Reverse-Engineering-Box

Die Reverse-Engineering-Box besitzt eine identische Funktionsweise zur Signatur-Box. Der Unterschied ist, dass statt der Signatur ein Teil des Quellcodes und eine Liste der vom Kandidaten genutzten Systemsaufrufe ausgegeben werden. Der (pseudo-)Quellcode kann vom Spieler selbst bewertet werden; die Liste der herausgegebenen Systemaurufe können im Register mit für den Typ der Anwendung erwarteten Systemaufrufen verglichen werden. Wenn eine Software bestimmte Systemaufrufe Nutzt, die sie nicht brauchen sollte, ist das im Allgemeinen ein Zeichen für Malware.
Beispiel: ein Musik-Player versendet TCP-Pakete im Hintergrund.

Kontrollpanel

Hier wird die Entscheidung getroffen, ob ein Kandidat schädlich ist oder nicht. Der Kandidat wird in die Mitte des Panel eingesetzt und durch einen Knopfdruck bewertet: "Genehmigen" oder "Ablehnen". Die Folgen dieser Entscheidung werden im Abschnitt “Feedback” erklärt.

Informationsfeld

Hier werden Informationen über Kandidaten, das Register und den Output der Signatur- und Reverse-Engineering Box bei einem Klick auf das jeweilige Element angezeigt.

Zeitstrahl

Die Hauptressource, um die die Spielenden kämpfen, ist Zeit. Er muss alle Kandidaten vor Ablauf der Zeit bewerten. Ist man zu langsam, oder wird zu viel Malware genehmigt, verliert man das Spiel. Die Bewertung von Kandidaten kann die verbleibende Zeit erhöhen oder reduzieren. Mehr dazu im nächsten Abschnitt.

Feedback

Abhängig von Kandidat gibt existiert ein Feedback für jede Bewertung:
Kandidat ist\ Spielerentscheidung Ablehnen Genehmigen
Malware Nichts
  • Man verliert Zeit
  • Bildschirmflackern
  • Bildschirm verzieht sich
  • Spielelemente werden ausgeblendet
  • Nach 5 genehmigten Malware-Kandidaten ist das Spiel verloren.
keine Malware Man verliert Zeit Man gewinnt Zeit zurück

Bezug auf Lernegegenstand

Die Malware-Detection Methoden sind in ihrer Gesamtheit abstrahierte Abbildungen der im Paper "A Comprehensive Review on Malware Detection Approaches" vorgestellten Methoden. Die Generierung und der Abgleich einer Signatur, sowie die Analyse der von einer Software genutzten System-Calls sind etablierte und effektive Methoden zur Identifizierung von Schadsoftware. Durch die gamifizierte Nutzung dieser Methoden wird ein Verständnis für sie entwickelt - lernen findet statt.

Leitfaden zu Godot

Szenen-Hierarchie

Analog zum Branching-System von Git lohnt es sich bei kollaborativen Projekten sehr, die Arbeit logisch und praktisch zu trennen, um Konflikte bei - von mehreren Devs gleichzeitig bearbeiteten - Assets zu vermeiden. Bei Godot bietet sich für die parallele Arbeit die Nutzung von verschiedenen Szenenbäumen an. Ein Beispiel aus dem Entwicklungsprozess von ChainGuard: Zu Beginn wurden 3 Basisfunktionen herausgearbeitet, die unser MVP haben musste. Erstens, eine Drag&Drop Funktion für Spielelemente; Zweitens, die Übertragung eines UI-Mockups in Godot; und Drittens, das Laden von Kandidaten-Datensätzen aus einer JSON-File. Diese drei Features sind bewusst so gewählt, dass sie nicht aufeinander aufbauen. So konnte sich jeder eine eigene Szene erstellen und dort seine Aufgabe umsetzen. Folglich wurden die drei Szenen - und das ist die Besonderheit von Godot - als Unterszenen in einer umfassenden Hauptszene aggregiert.
Alle Nodes mit dem Filmklappen-Symbol sind Unterszenen.
Erstellen einer neuen Szene:
Speichern der neuen Szene als Asset:
Einfügen einer Unterszene:
Die lose_screen Szene wird als Unterszene in die Hauptszene eingefügt

Skripte in Godot

Die Implementierung eigener Funktionalitäten durch eigens geschriebene Skripte ist ein grundlegender Baustein der meisten Spiele Engines - so auch in Godot.

Die Sprachen

Godot unterstützt hauptsächlich 2 Skriptsprachen. Godot-Skript ist eine an Python angelehnte Sprache. Die gleiche Schwache Typisierung, die gleichen Syntaxregeln. Sie wird von der Dokumentation und dem Großteil der Community bevorzugt. Die zweite unterstützte Sprache ist das dem Unity-Dev bereits bekannte C#. Die Nutzung von C# in Godot hat jedoch einige Plattform-Kompatibilitäts-Einschränkungen: zum Beispiel ist der Export auf Web momentan nicht unterstützt. Godot-Doku zu C#
Ein Skript pro Node und Vererbung
Anders als in Unity kann man in Godot nur ein Skript pro Node anfügen. Das hat den Grund, dass die vom Nutzer erstellten Skripte in Godot Unterklassen der Nodes sind. Folglich kann ein Skript für einen Button automatisch alle Klasseneigenschaften und Methoden der Button-Klasse(und aller ihrer Oberklassen, bis zur Object-Klasse) nutzen und überschreiben. Überdies stellt dieses Skript eine neue Art von Node dar und kann auch so im Editor erstellt werden. Beispiel aus der Entwicklung: In Chainguard exisitert eine Klasse “TimeBar”, die von der UI-Basisklasse “Control” erbt. Beim Hinzufügen einer neuen Node kann man nun “TimeBar” als neuen Node-Typen finden.
Das Schriftrollen-Symbol notiert eine durch den Nutzer erstellte Klasse
Wichtig: Ein Skript wird erst zu einer vollwertigen Unterklasse, wenn im Skript mittels der “class_name XXXX” Notation ein Name vergeben wird.
extends Control
class_name TimeBar
Variablen im Editor setzen
Unity bietet die praktische Funktion, dass öffentliche Felder im Editor geändert werden können. In Godot ist diese Funktionalität hinter der “@export”-Notation versteckt.
Export-Beispiel aus dem Sandbox-Skript
@export
var chance_of_trigger := 0.8
Durch die Nutzung der "@export"-Notation werden nun Felder im Editor/Inspektor sichtbar:

Gruppen

...vereinen die Funktionalitäten von Unitys Tags und Layers in einem. Nodes können Gruppen im rechten Editorpanel hinzugefügt werden:
und per
Drop-Target Objekte durch die Gruppe finden
var containers = get_tree().get_nodes_in_group("drop_container")

Globale Objekte

Objekte wie klassisch betitelte Game-Manager die szenenübergreifend exisiteren sollen sind von Godot unterstützt. Wo bei Unity die "DontDestroyOnLoad"-Methode genutzt wird um Objekte in jeder Szene zu verfügbar zu machen, muss man bei Godot für diese Funktion in die Projekteinstellungen:
Projekt > Projekteinstellungen > Globals
Hier können per Referenz auf ein Skript Globale Objekte definiert werden. Und direkt von Skripten angesprochen werden.

Signale

"Das sind Nachrichten, die Nodes aussenden, wenn etwas Bestimmtes mit ihnen passiert, z.B. wenn ein Button gedrückt wird. Andere Nodes können sich mit diesem Signal verbinden und eine Funktion aufrufen, wenn das Ereignis eintritt. Signale sind ein in Godot integrierter Delegierungsmechanismus, der es einem Spielobjekt ermöglicht, auf eine Änderung in einem anderen zu reagieren, ohne dass sie sich gegenseitig referenzieren. Die Verwendung von Signalen führt zu weniger Kopplung und hält Ihren Code flexibel." (Quelle)
Signale sind also eine Möglichkeit Funktionen global aufzurufen ohne eine Referenz auf diese. Dieses Feature ist auch besonders bei kooperativen Workflows praktisch, da man, statt via einer Referenz auf eine noch nicht vorhandenes Objekt, ein Signal auslösen kann dass einfach von später hinzukommenden Komponenten aufgenommen werden kann ohne etwas am Code des Auslösers ändern zu müssen. Es gibt 2 Wege, wie man einen Funktionsaufruf mit einem Signal verbinden kann: über Skript oder über den Editor.
Editor
Schaue dir zunächst die verfügbaren Signale einer Node im Inspektor an.
Liste der Signale einer Node anzeigen
Wähle ein Signal aus und weise ihm die Node mit dem Skript deiner Ziel-Funktion zu.
Signal zu einer Zielfunktion zuordnen
Per Skript
signal mein_signal(wert)

func _ready():

    print("Sender bereit")

    emit_signal("mein_signal", "test")

Sender
extends Node func _ready():

    var sender = get_node("../Sender")

    sender.mein_signal.connect(_on_mein_signal)

func _on_mein_signal(wert):

    print("Empfangen:", wert)

Empfänger

Definition of Done(DoD):

JSON oder YAML Datei für Speichern von Kandidaten-Attributen anlegen.
In der Datei sollte ein Array von Objekten sein, die alle die folgenden Attribute haben(Datentypen erstmal alle String außer explizit anders beschrieben):
Name,
Publisher,
Description,
IsMalware (bool),
Signature(4-stelliger Zahlencode zB "0239"),
SourceCode (string, kann erstmal Leer bleiben)
System Calls (Array mit Strings, die einen oder mehrere System Calls beinhalten, erstmal kombination aus diesen Mocks nehmen: "KILL_PROCESS, SEND_PACKET, INSTALL_KERNEL_RUNTIME" )
Punishment(Zahlencode, der dann intern in nem Switch benutzt wird um die Folgen der Malware zu mappen, Zahl von 1- 10)
davon erstmal 10 generieren lassen(ich denke KI ist da der schnellste weg um erstmal 10 mockups zu erstellen) 5 sind malware 5 nicht. Die anderen Felder müssen sich noch nicht stark unterscheiden zwischen Malware und nicht Malware.
Bonus/Follow-Up: Datei in Godot auslesen und als Text ausgeben(Konsole oder Textfeld).

Entwicklertagebuch

Um in Chainguard, wie in PapersPlease, über einzelne Kandidaten entscheiden zu können braucht es erst einmal ebend diese Kandidaten. Das heißt, es benötigt eine Candidate Klasse, um eine Datenstruktur für einzelne Kandidaten festzulegen. Wichtig hierbei ist, dass jedes Skript (jede .gd Datei) eine Klasse ist. Das heißt, dass man in der Regel nicht über "Class:" eine neue Klasse in dem Dokument definiert, sondern über "class_name Candidate" der Klasse nur mitteilt, wie sie heißt. "Class:" existiert trotzdessen, die so definierte Klasse kann aber nicht ohne weiteres von außen aufgerufen werden.

Um Kandidaten speichern und laden zu können braucht es einen CandidatesManager, dieser schreibt die Kandidaten als Liste, in eine JSON oder lädt sie aus dieser wieder.

In GODOT können einzelne Scenes singulär gestartet werden. Zum Testen der neuen Funktionalität wird also kein Dummy in die main-Scene gepackt, sondern eine separate Test-Scene für die Funktionalität erstellt. In dieser braucht es dann nur ein Node an das wir unser Skript hängen, welches die neue Funktionalität mit Mockup Daten testet. Dafür ist das datenstruktur_und_anzeige_der_kandidaten_daten.gd Skript verantwortlich.

Wenn man die 3 Skripte betrachtet, fällt auf, dass candidate.gd und candidates_manager.gd "extends RefCounted" und datenstruktur_und_anzeige_der_kandidaten_daten.gd "extends Node" in der 1. Zeile stehen haben. Dies liegt daran, dass datenstruktur_und_anzeige_der_kandidaten_daten.gd an einem Node hängt und die anderen Beiden nicht, sondern über ihren Klassennamen referenziert werden.

Mehr zu Klassen in der Doku.

Definition of Done(DoD):

Wir müssen die Kanidaten als Spiel-Elemente Darstellen.
Zunächst brauchen wir die Möglichkeit, UI-Elemente per Drag & Drop über das Spiel zu bewegen.
Die Verwendeten Objekte sollten UI-Objekte(erbt von Control in Godot) und KEINE Node2D sein.
Tutorial https://godot.snoeyz.com/drag-and-drop/

Entwicklertagebuch

Für den Drag-and-Drop-Mechanismus wurde eine Demoszene angelegt, welche aus einem Control-Node besteht, welches als Kindelemente mehrere Container und ein Item besitzt. Das Item ist das ziehbare Element, die Container sind die Elemente, auf die das Objekt gezogen werden. Diesen Containern wurde die "drop_container"-Gruppe zugeordnet. Dem Item wurde das Skript draggable_item.gd zugeordnet bekommen. In diesem Skript werden alle Container initialisiert. Wenn es zu einem InputEventMouseButton kommt, wird das Dragging durchgeführt. Wenn das Item wieder mit der Maus losgelassen wird, wird mit der check_drop-Funktion festgestellt, ob das sich Item über der Position eines Drop-Containers befindet. Falls nicht, wird der letzte Container und die letzte Position für das Item ausgewählt. Falls das Element über einem Drop-Container ist, wird der letzte Container gespeichert, damit das Item notfalls wieder auf die letzte Position kann, wenn der nächste Drop nicht erfolgreich ist. Außerdem wird die aktuelle Position und der aktuelle Container geändert. Mit der clamp-Funktion von Godot wird sichergestellt, dass sich das Item genau innerhalb der Grenzen des Containers liegt. Auch wenn es mit der Maus etwas über die Grenze gezogen wurde.

Nachdem die Grundfunktion implementiert wurde, wurde der Code noch einmal angepasst, um ihn die Funktionalität zu erweitern, dass der jeweilige Container wissen muss, welches Item sich in ihm befindet. Dazu wurde der Szene ein DragLayer hinzugefügt. Im Skript draggable_item.gd wird das Item bei dem Mausklick mit dem DragLayer gereparentet. Dadurch ist das Item für den Übergang das Child dieses DragLayers. Sobald das Item gedroppt wird, wird es mit dem an dieser Postion liegenden Container gereparentet. Dadurch ist dann eine klarere Struktur gegeben, sodass das Item dem Container zugeordnet werden kann, in welchem es liegt. Der DragLayer verhindert, dass ein Item beim Übergang einem Container zugeordnet wird, da es sich grade frei bewegt. Befindet sich das Item nicht auf der Position eines Containers, wird das Item analog zu der bisherigen Lösung mit dem letzten Container gereparentet.

Definition of Done(DoD):

Buttons sind als solche markiert, Bezeichnungen die mit Drag&Drop zu tun haben, können erstmal ignoriert werden.
Liste der Signale einer Node anzeigen

Entwicklertagebuch

Die Umsetzung erfolge in der GUI-Szene umgesetzt. Zur Implementierung wurde eine Komposition aus 2DSprites und Control-UI-Elementen genutzt.

Entwicklertagebuch

Dieses Issues bestand aus der Erstellung aller Issues die für das aktuelle MVP umgesetzt wurden. Also: alle Issues in dieser Liste.

Definition of Done(DoD):

Die im UI - Mockup als "Drag & Drop" Zeile Markierten Rechtecke zu nur neuen
drop_containers" hinzufügen.
Kandidaten Drag & Dropable machen.

Entwicklertagebuch

Die Drag&Drop Szene wurde als Unterszene der UI-Szene instanziiert und die Drop Targets den verschiedenen Plätzen in der UI(Sandbox, Signatur-Box, Reverse-Engineering-Box und Controlpanel) eingefügt.

Definition of Done(DoD):

Vorraussetzung: Reverse Engineering Box, Register, Signatur-Box Implementiert
Die große Textbox in der Mitte soll abhängig vom ausgewähltem Element Kontext-Infos anzeigen.
Schritte:
Ein Script für die Textbox erstellen
Einen Singleton im Skript haben der das ausgewähle Element anzeigt. Der Singleton wird gesetzt wenn auf ein Element gecklickt wird, das Kontext-Infos hat(siehe Mockup: Kandidat, Reverse-Engineering-Box, Register, Signtatur-Box)
Beim Setzen soll eine Funktion "get_context_info" oder ein Signal auf einem Skript des angeklickten Objektes aufgerufen werden, welches einen String zurück gibt. Dieser soll in der Box angezeigt werden.

Entwicklertagebuch

Statt eines Globalen Singletons wurde eine Game-Manager-Node in einer Gruppe definiert, da es zu Problemen in anderen Szenen kam. Für Elemente die Kontext Infos geben wurde die Klasse Focusable erstellt, die bei einem click eine Methode des Game-Manager aufruft. Dieses Methode übergiebt einen String der dann mit BBCOde auf der Kontext-Tafel angezeigt wird. (In Hindsight hätte man die Verbindung zwischen Button und Game Manager einfacher mit einem Signal lösen können.) Teil dieser Aufgabe war auch, das Drag&Drop Skript anzupassen, sodas bei einem CLick auf das Objekt auch die wichtigen Daten zu den Kandidaten angezeigt werden.

Definition of Done(DoD):

Erstellen von StartScreen-Szene
Erstellen von Hauptszene(Mit UI-Mockup als Sub-Szene)
Button-Navigation Hauptszene <-> Startscreen
Lose-Szene mit Button zum Start-Screen und Hauptszene("Neu Versuchen")
Wenn Todes-Timer schon implementiert ist: Bei 0 oder weniger Zeit die Lose-Szene öffnen.

Entwicklertagebuch

Für die Menüs wurden der Text der Buttons aus dem Mockup, welche mit Adobe Illustrator erstellt wurden, angepasst und neu mit den jeweiligen Grafiken für die Buttons exportiert. Die Szenen main_menu.tscn, lose_screen.tscn und win_screen.tscn wurden mit den jeweiligen Buttons angelegt, wobei sich der Win- und der Lose-Screen nur vom Anzeigetext unterscheiden. Für spätere Anpassungen der Screens wurden aber dennoch separate Szenen angelegt. Den Menüs wurde jeweils mithilfe eines Control-Nodes das menu.gd-Skript zugewiesen, in welchem den Buttons der jeweilige change_scene_to_file-Aufruf zugeordnet wird. Ein solcher Aufruf wurde auch dem Zeitstrahl hinzugefügt, damit nach Ablauf der Zeit der Lose-Screen angezeigt wird.

Definition of Done(DoD):

Nachschlageregisterdaten in JSON schreiben und auslesbar machen
Inhalt:
Liste an Schadsoftware mit Namen, Herausgebern und Signaturen
Liste an System Calls und welche Arten von Anwendungen sie benutzen
Register signal/methode schreiben, die einen formattierten String dieses Inhaltes zurück gibt, nachdem die JSON-Datei ausgelesen wurde

Entwicklertagebuch

In diesem Issue wurde nichts anderes gemacht als in "MP-SeriousGames#01 - Datenstruktur und Anzeige der Kandidaten-Daten" und ein Großteil des Codes aus dem Issue wurde in diesem wiederverwendet. SysCall und Malware werden dabei getrennt, je analog zu Candidate, behandelt und implementiert. Genaueres kann im anhängigen Merge-Request nachgelesen werden.

Definition of Done(DoD):

Script für das Drop-Target Sandbox schreiben
Funktion oder Signal Input: candidate.gd Wenn Malware == true
starte mit wahrscheinlichkeit von 0.8 einen Timer von 10 sek, nachdem das Rechteck Rot wird

Entwicklertagebuch

Exakte implementierung wie im Issue beschrieben. Skript Zusätzlich wurde eine Methode für das entfernen des Kandidaten aus dem Input-Slot implementiert, die den Zustand der VM zurücksetzt. Skript erbt von DropBox-Klasse, die lediglich die Kanidatenvariable und die receive-Funktion beinhaltet.

Definition of Done(DoD):

Script für das Drop-Target Reverse Engineering Box.
Script soll das "drop_box" erweitern und an Objekt "Drop_Target_RE" ersetzen
Variable on_focus_output: string (Standard-Wert sowas wie "Platziere Software hier um sie zu Analysieren)
"func receive_candidate(new_candidate):" erweitern, sodass Variable "on_focus_output" nach 20 Sekunden auf eine formatierte Ausgabe von _SourceCode: String, _System_Calls: Array[String] gesetzt wird.
Funktion get_context_info: soll on_focus_output zurückgeben

Entwicklertagebuch

Problemfreie Implementierung i re_box.gd Skript erbt von DropBox-Klasse, die lediglich die Kanidatenvariable und die receive-Funktion beinhaltet.

Definition of Done(DoD):

Script für das Drop-Target Signatur-Box.
Variable on_focus_output: string (Standard-Wert sowas wie "Platziere Software hier um sie zu Analysieren)
Funktion/Signal die eine instanz der Candidaten-Klasse nimmt Soll die Variable "on_focus_output" nach 20 Sekunden auf eine formatierte Ausgabe von _Signatur setzen. mit dem Namen: "receive_candidate"
Funktion get_context_info: soll on_focus_output zurückgeben

Entwicklertagebuch

Implementierung fast exakt zu Issue #11. Skript: box_signatur.gd

Definition of Done(DoD):

Vorraussetzung: zeitstrahl Implementiert
Singleton-Klasse erstellen die auf einer Node sitzt und global angesprochen wird, wenn ein Kandidat bewertet wurde.
globale Funktion die eine Zahl(punishment_index) und einen boolean(ob richtig bewertet wurde) bekommt
abhängig von boolean soll eine von 2 Funktionen augerufen werden
right_answer(punishment_index)switch mit dem index: 0 : mehr zeit default : nichts
wrong_answer(punishment_index) 0,1 : weniger Zeit 2 : ein zufälliges UI Element wird für 10 Sekunden disabled
Mögliche Konsequenzen:
Screen verfärben
Elemente disable
Mouse Sensitivity
Timer nicht mehr sehen
Screen Rotieren

Entwicklertagebuch

Statt einer Singleton Klasse, wurden die Konsequenzen im game_manager.gd-Srkipt implementiert. Die Methode "invoke_consequence" dient als Startpunkt. Diese wird von den Bewertungsbuttons aufgerufen und erhält 3 Parameter: Falsch/Richtig "geraten", Malware ja/nein, punishment Index des Kandidaten.
Die Methode enthält sowohl den Mechanismus der im GDD in der Tabelle benannt wird als auch einen Zähler für genehmigte Malware. Wenn der Zähler 5 erreicht, ist das Spiel verloren. Konsequenzen beinhalten:
  • Verlieren/Dazugewinnen von Zeit
  • Rotes Noise-Overlay für das Spiel
  • zufälliges UI-Element aus definierter Liste für 20 Sekunden Disablen
  • Spieloberfläche für 20 Sekunden verzerren

Definition of Done(DoD):

Oben in der Mitte des UIs soll ein Zeitrahl über eine Minute runterticken und wenn die Zeit <= 0 ist dann eine Nachricht printen

Entwicklertagebuch

Für die Implementierung des Zeitstrahls wurde eine Demoszene und ein Skript angelegt. Die Szene enthält ein Control-Element, dessen Kind eine ProgressBar ist. Das Control-Element enthält das Skript für den Zeitstrahl. Mit der _process-Methode von Godot wird der Wert der ProgressBar beim Ablaufen angepasst, sodass die Animation entsteht. Sobald 60 Sekunden abgelaufen sind, wird die Nachricht "Minute ist vorbei!" ausgegeben.

Definition of Done(DoD):

Vorraussetzung: UI - Mockup umgesetzt, Datenstruktur für Kandidaten fertig
Jedes UI-Element der Kandidaten soll zu beginn des Spieles einen nicht bereits verwendeten Kandidaten als Script oder Objekt im Script zugeordnet bekommen.

Entwicklertagebuch

Der Ansatz, die Kandidaten als Teil der UI- oder Drag&Drop Szene statisch hineinzuladen wurde verworfen.
Stattdessen wurde eine szene mit einem Kandidaten erstellt. Dieser Besteht aus der Textur selbst, dem Label und einem Skript,
welches sowohl die Kandidaten-Daten als auch die Funktionalitäten eines Drag&Drop Items vereint.

Definition of Done(DoD):

Einmal das Projekt im jetzigen Zustand bauen und in Web anzeigen lassen.
Probleme/Auffälligkeiten dokumentieren.

Entwicklertagebuch

Die Ergebnisse dieser Aufgabe sind im Teil zum Export des Spieles dokumentiert.

Definition of Done(DoD):

Der grüne und der rote Button sollten ein Skript bekommen, in dem eine Referenz zu dem Kandidatenslot besteht.
Bei einem Button Press soll der Kandidat aus dem Kandidatenslot gelesen werden.
Es wird ermittelt, ob die richtige Entscheidung getroffen wird, mit einem Vergleich des isMalware Attribut mit der Art des Buttons Name der function "receive_candidate"
(die unterscheidung des Button kann in Metadaten/Properties getroffen werden, damit kein eigenes Skript geschrieben werden muss)

Entwicklertagebuch

Buttons bekommen beide das evaluation_button.gd-Skript. Die Unterscheidung zwischen "Genehmigen" und "Ablehnen" Button wird über das im Editor setzbare attribut "is_green" dargestellt.
Buttons erhalten eine Referenz, wenn ein Kandidat in das Controlpanel eingefügt wird.
Wenn der Button betätigt wird, wird die Bewertung mit den Kandidatendaten abgeglichen und mitsamt der punishmentId an den GameManager geschickt.
Zusätzlich wird in diesem Skript die Anzahl der verbleibendenden Kandidaten getrackt, sodass die Siegbedingung ausgelöst werden kann.

Definition of Done(DoD):

Alle Lilanen Boxen sollten als Drag & Drop Ziele fungieren und ein Skript mit einer Referenz auf den in ihnen liegenden Kandidaten besitzen.

Entwicklertagebuch

Funktionalität wurde bereits in Issue #6, #10, #11 und #12 umgesetzt.

Definition of Done(DoD):

momentan kann man mehrere draggable items anclicken und gleichzeitig bewegen.
Implementierungsvorschlag: Schranke/Lockable Resource die global trackt ob gerade ein Item gedraggt wird

Entwicklertagebuch

Dieses Problem wurde dadurch gelöst, dass bei jedem Drag eine Abfrage hinzugefügt wurde, ob sich bereits ein anderes Child-Element auf dem DragLayer befindet. Falls der Wert größer als 0 ist, findet ein return statt. Dadurch hat sich allerdings auch die Anzeige des Infotextes in der Mitte geändert, wobei dort dann falsche Texte angezeigt wurden, da die dazugehörige Funktion auch mit dem ersten Mausklick des Ziehvorganges gestartet wird. Dies wurde behoben, indem die Abfrage der Child-Elemente an dieser Stelle eben falls implementiert wurde.

Definition of Done(DoD):

Drop Target soll nur einen Kandidaten nehmen können

Entwicklertagebuch

Das Problem wurde innerhalb von candidate_node.gd in der snap_to_container-Methode behoben. Indem hier abgefragt wird, ob die Anzahl der Child-Elemente in diesem Container größer als 0 ist, also ob sich hier bereits ein Item in diesem Container befindet. Falls das der Fall ist, wird das Item wieder mit dem Warteschlangen-Container gereparentet. Damit das Element auch visuell zurück in die Warteschlange gesetzt wird, geschieht danach ein Aufruf von queue_container.move_child(self, queue_container.get_child_count() - 1). Damit wird das Item an die unterste Position geschoben.

Definition of Done(DoD):

Gewonnen: es existieren keine Kandidaten mehr
implementierungshinweis: alle kandidaten beim erstellen in eine Gruppe tun und dann immer wenn der Bewertungsbutton(eval) nach dem "free_queue" aufruf schauen, ob noch nodes in der Gruppe sind
Lose: Timer Abgelaufen, zu oft(fürs erste 5 x) falsch geraten(lässt sich als teil der "invoke_consquences"- methode im game manager gut tracken)

Entwicklertagebuch

Damit die Win-Condition funktioniert, werden alle Kandidaten bei der Erstellung im Skript candidate_creation.gd der Gruppe "candidate_nodes" hinzugefügt. Die Größe dieser Gruppe wird dann in der _button_pressed-Methode des evaluation_button.gd-Skriptes geprüft. Wenn diese kleiner als oder gleich eins ist, befinden sich keine Kandidaten mehr in der Warteschlange und der Win-Screen wird über einen change_scene_to_file-Aufruf geladen. Die erste Lose-Condition mit zu vielen falschen Antworten wurde mit einer failCount-Variable im game-manager.gd-Skript realisiert. Diese wird global deklariert und in der _ready-Methode mit dem Ausgangswert 0 initialisiert. Mit einer if-Abfrage, ob die bereits vorhandene right_guess-Variable False ist, wird der Wert der failCount-Variable erhöht. Liegt dieser bei fünf Fehlversuchen, wird der Lose-Screen geladen. Die zweite Lose-Condition mit dem abgelaufenen Timer wurde bereits beim Anlegen der Szenenstruktur implementiert.

Definition of Done(DoD):

Mock-Kandidaten-Daten erweitern & verbessern

Entwicklertagebuch

Die candidates.json-Datei wurde um mehr Kandidaten ersetzt. Zusätzlich haben die Kandidaten andere Beschreibungen erhalten. Die erweiterte Datei wurde neu abgespeichert.

Überblick

Das Deployment eines Godot-basierten Serious Games für das Web umfasst mehrere Schritte: den HTML5-Export aus der Engine, den Transfer auf einen Server und die korrekte Konfiguration des Webservers. Dabei spielen moderne Web-Sicherheitsstandards wie Secure Context und Cross-Origin Isolation eine zentrale Rolle, die häufig zu unerwarteten Problemen führen.

Die Bereitstellung von Spielen über den Browser hat in der Serious-Games-Forschung besondere Bedeutung: Web-basierte Distribution senkt die Einstiegshürde für Lernende erheblich, da keine Installation erforderlich ist (Prensky, 2001). Gleichzeitig stellt die Browser-Plattform spezifische technische Anforderungen, die im Folgenden erläutert werden.

Schritt 1: Godot HTML5-Export

Godot kompiliert das Projekt mithilfe von WebAssembly (WASM) in ein browserlauffähiges Format. WebAssembly ist ein von Mozilla, Google, Microsoft und Apple gemeinsam entwickelter Standard (W3C, 2019), der es ermöglicht, kompilierten Code nahezu nativ im Browser auszuführen.

  1. In Godot: Projekt → Export → Hinzufügen → Web
  2. Export-Template herunterladen (falls nicht vorhanden)
  3. Export-Pfad festlegen (z.B. B:\Projekt_Godo\export)
  4. „Projekt exportieren" klicken

Der Export erzeugt folgende Dateien, die alle benötigt werden:

Datei Funktion Pflicht?
index.html Einstiegspunkt, lädt Engine und Assets Ja
*.js JavaScript-Laufzeit der Godot-Engine Ja
*.wasm WebAssembly-Modul (kompilierte Engine) Ja
*.pck Gepackte Assets, Szenen und Skripte Ja
*.png Splash-Screen / Boot-Bild Optional
Icons Für Touch-Geräte (Progressive Web App) Optional
ⓘ Wichtig: Fehlende Dateien führen zu Fehlern wie „Fail to fetch" oder einem weißen Bildschirm. Immer den gesamten Export-Ordner hochladen.

Godot Engine Documentation (2024). Exporting for the Web. docs.godotengine.org
W3C (2019). WebAssembly Core Specification. w3.org

Schritt 2: Zugriff auf den Server (SSH)

Für das Deployment wird ein Linux-Server mit SSH-Zugang benötigt (in unserem Fall eine Ubuntu 24.04 VM der HTWK Leipzig). Der Zugriff erfolgt über PuTTY (SSH-Client für Windows).

  1. VPN aktivieren (bei Hochschulnetz zwingend erforderlich)
  2. PuTTY starten → Host Name: Server-IP eingeben, Port: 22, Typ: SSH
  3. Verbindung öffnen → Benutzername und Passwort eingeben
ⓘ Hinweis: Immer die IP-Adresse verwenden, nicht den Hostnamen – dieser kann auf einen Proxy verweisen und ist für SSH nicht geeignet.

Schritt 3: Dateien auf den Server übertragen

Für den Dateitransfer gibt es zwei bewährte Methoden:

Methode Tool Vorteile
Kommandozeile PSCP (Teil der PuTTY-Suite) Schnell, skriptbar, kein Extra-Tool
Grafisch WinSCP Drag-and-Drop, übersichtlich

Upload mit PSCP (PowerShell auf dem lokalen PC)

  1. Zielordner auf dem Server erstellen (in PuTTY/SSH):
    mkdir -p /home/stud/chainguard
  2. Upload starten (in PowerShell, nicht in PuTTY!):
    pscp.exe -r "B:\Projekt_Godo\export" stud@[SERVER-IP]:/home/stud/chainguard
  3. Auf dem Server prüfen:
    ls -la /home/stud/chainguard/export
ⓘ Typische Fehler:
• unable to open: failure → Zielordner existiert nicht → erst mkdir -p
• No such file or directory → Falsches Arbeitsverzeichnis → einen Ordner höher wechseln
• command not found → PSCP auf dem Server statt auf dem PC ausgeführt

Schritt 4: Webserver einrichten (Apache)

Für den permanenten Betrieb wird ein vollwertiger Webserver empfohlen. Apache HTTP Server ist der am weitesten verbreitete Webserver weltweit (Netcraft, 2024) und eignet sich besonders für statische Inhalte wie Godot-HTML5-Exporte.

Installation und Konfiguration

# Apache installieren
sudo apt update
sudo apt install apache2 -y

# Aktivieren und starten
sudo systemctl enable --now apache2

# Projekt ins Web-Verzeichnis kopieren
sudo mkdir -p /var/www/html/chainguard
sudo cp -r /home/stud/chainguard/export/* /var/www/html/chainguard/
sudo chown -R www-data:www-data /var/www/html/chainguard

# Apache neustarten
sudo systemctl restart apache2

Das Spiel ist nun unter http://[SERVER-IP]/chainguard erreichbar.

Schnelltest ohne Apache (Python)

Für schnelle Tests ohne Installation eignet sich Pythons eingebauter HTTP-Server:

cd /home/stud/chainguard/export
python3 -m http.server 8080 --bind 0.0.0.0

Erreichbar unter http://[SERVER-IP]:8080 (VPN muss aktiv sein).

Schritt 5: Secure Context und HTTPS

Ein häufiges Problem bei Godot-Web-Exports ist die Fehlermeldung:

⚠ Error: „The following features required to run Godot projects on the Web are missing: Secure Context – Check web server configuration (use HTTPS)"

Moderne Browser erzwingen für bestimmte APIs (insbesondere SharedArrayBuffer, das Godot für Multi-Threading nutzt) einen Secure Context. Laut W3C-Spezifikation gilt ein Kontext als „sicher", wenn er über HTTPS oder von localhost ausgeliefert wird (W3C, 2021).

Zusätzlich erfordern moderne Browser Cross-Origin Isolation durch zwei HTTP-Header, damit SharedArrayBuffer verfügbar ist (Mozilla MDN, 2024):

  • Cross-Origin-Opener-Policy: same-origin
  • Cross-Origin-Embedder-Policy: require-corp

Lösung A: Threads deaktivieren (einfachste Lösung)

In Godot: Projekt → Export → Web → Threads: Off (Single-Threaded). Dadurch wird SharedArrayBuffer nicht mehr benötigt und das Spiel funktioniert auch ohne HTTPS. Performanceeinbußen sind je nach Projekt minimal.

Lösung B: Cross-Origin-Header setzen (Apache)

# In /etc/apache2/sites-available/000-default.conf
# Innerhalb des <VirtualHost *:80> Blocks:
Header always set Cross-Origin-Opener-Policy "same-origin"
Header always set Cross-Origin-Embedder-Policy "require-corp"

# Headers-Modul aktivieren:
sudo a2enmod headers
sudo systemctl restart apache2

Lösung C: HTTPS mit Self-Signed Certificate (empfohlen für Produktion)

Für einen vollständig konformen Secure Context wird HTTPS benötigt. Auf einer VM ohne öffentliche Domain eignet sich ein selbstsigniertes Zertifikat:

# 1. SSL-Zertifikat erstellen
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/ssl/private/apache-selfsigned.key \
  -out /etc/ssl/certs/apache-selfsigned.crt \
  -subj "/C=DE/ST=Sachsen/L=Leipzig/O=HTWK/CN=[SERVER-IP]"

# 2. SSL in Apache aktivieren
sudo a2enmod ssl
sudo a2ensite default-ssl
sudo systemctl restart apache2

# 3. In /etc/apache2/sites-available/default-ssl.conf:
# Im <VirtualHost *:443> Block nach DocumentRoot:
SSLEngine on
SSLCertificateFile /etc/ssl/certs/apache-selfsigned.crt
SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned.key

# 4. Neustart
sudo systemctl restart apache2

Das Spiel ist dann unter https://[SERVER-IP]/chainguard erreichbar. Der Browser zeigt eine Zertifikatswarnung (da selbstsigniert) – über „Erweitert → Fortfahren" kann diese akzeptiert werden.

W3C (2021). Secure Contexts. w3.org
Mozilla MDN (2024). SharedArrayBuffer: Security requirements. developer.mozilla.org
DigitalOcean (2024). How To Create a Self-Signed SSL Certificate for Apache in Ubuntu. digitalocean.com

Schritt 6: Updates deployen

Beim Aktualisieren des Spiels sollte der alte Inhalt vollständig ersetzt werden, um veraltete Dateien zu vermeiden:

# 1. Alten Inhalt auf dem Server löschen
sudo rm -rf /var/www/html/chainguard/*

# 2. Neuen Export hochladen (PowerShell auf dem PC)
pscp.exe -r "B:\Projekt_Godo\export\*" stud@[SERVER-IP]:/home/stud/chainguard/

# 3. Ins Webverzeichnis kopieren (SSH auf dem Server)
sudo cp -r /home/stud/chainguard/* /var/www/html/chainguard/
sudo chown -R www-data:www-data /var/www/html/chainguard
sudo chmod -R 755 /var/www/html/chainguard
sudo systemctl reload apache2

# 4. Im Browser: Strg+F5 (harter Reload, Cache umgehen)

Schritt 7: Begleitende Website deployen

Neben dem Spiel selbst kann auch eine begleitende Website (z.B. dieses Tutorial) auf demselben Server bereitgestellt werden. Beide Projekte liegen in separaten Ordnern im Apache-Webroot und sind unabhängig voneinander erreichbar. Dieses Vorgehen entspricht dem Prinzip der Separation of Concerns (Martin, 2003): Das Spiel und die Dokumentation sind getrennte Artefakte mit eigenem Deployment-Zyklus.

Verzeichnisstruktur auf dem Server

Server-Pfad URL Inhalt
/var/www/html/chainguard/ https://[IP]/chainguard Godot-Spiel (HTML5-Export)
/var/www/html/tutorial/ https://[IP]/tutorial/main.html Tutorial-Website

Upload und Einrichtung

# 1. Website hochladen (PowerShell auf dem PC)
pscp.exe -r "B:\Projekt_Godo\Website\src" stud@[SERVER-IP]:/home/stud/tutorial

# 2. Ins Webroot kopieren (SSH auf dem Server)
sudo mkdir -p /var/www/html/tutorial
sudo cp -r /home/stud/tutorial/src/* /var/www/html/tutorial/
sudo chown -R www-data:www-data /var/www/html/tutorial
sudo chmod -R 755 /var/www/html/tutorial
sudo systemctl reload apache2

Updates der Website

# PowerShell (PC):
pscp.exe -r "B:\Projekt_Godo\Website\src" stud@[SERVER-IP]:/home/stud/tutorial

# SSH (Server):
sudo rm -rf /var/www/html/tutorial/*
sudo cp -r /home/stud/tutorial/src/* /var/www/html/tutorial/
sudo chown -R www-data:www-data /var/www/html/tutorial
sudo systemctl reload apache2
ⓘ Hinweis: Beide Projekte (Spiel und Website) sind vollständig unabhängig voneinander. Das Aktualisieren des eines hat keinen Einfluss auf das andere. Man kann aus der Website direkt auf das Spiel verlinken mit <a href="/chainguard/index.html">Spiel starten</a>.

Zusammenfassung: Deployment-Pipeline

Phase Tool / Ort Aktion
1. Export Godot (lokal) Projekt → Export → Web
2. Transfer PSCP / WinSCP (lokal) Dateien per SSH auf den Server laden
3. Deploy SSH (Server) Dateien ins Apache-Webroot kopieren
4. HTTPS Apache (Server) SSL-Zertifikat + Secure Context konfigurieren
5. Website PSCP + SSH (Server) Tutorial-Website in separaten Ordner deployen
6. Test Browser (lokal) https://[IP]/chainguard + /tutorial aufrufen

Weiterführende Literatur

Godot Engine Docs (2024). Exporting for the Web (Link), Zugriff 01. April 2026
W3C (2019). WebAssembly Core Specification (Link), Zugriff 29. März 2026
W3C (2021). Secure Contexts (Link), Zugriff 06. April 2026
Mozilla MDN (2024). SharedArrayBuffer (Link), Zugriff 03. April 2026
Haas, A. et al. (2017). Bringing the Web up to Speed with WebAssembly. Proc. ACM SIGPLAN Conference on Programming Language Design and Implementation.
Prensky, M. (2001). Digital Game-Based Learning. McGraw-Hill.
DigitalOcean (2024). Self-Signed SSL Certificate for Apache in Ubuntu (Link), Zugriff 07. April 2026

Einige Aspekte der Postproduction sind für Spiele im Kontext einer Abschlussarbeit oder für sonstige Projekte im Hochschulkontext meist nicht von hoher Wichtigkeit, da es in diesen Kontexten zum Beispiel oft keine Vermarktung braucht, welche im Normalfall ein Teil der Postproduction ist. Allerdings gibt es einen Postproduction-Aspekt der besonders bei Serious Games sehr wichtig ist: Das Play-Testing. Erst durch das Play-Testing kann festgestellt werden, ob ein Serious Game wirklich seinen Zweck erfüllt. Im nachfolgenden Kapitel finden sich einige Hinweise zum Play-Testing bei Serious Games. Außerdem wird kurz erklärt, wie Updates und Patches über Godot ausgerollt werden, falls das Projekt irgendwann erweitert oder aktualisiert werden soll.

Play-Testing und Feedback

Anders als bei Spielen, die nicht den Serious Games zuegordnet werden können, ist bei Serious Games das Feststellen des Lernfortschrittes neben den gewöhnlichen Aspekten des Play-Testing ein sehr wichtiger Punkt, da ein Serious Game erst seinen Zweck erfüllt, wenn eine Lernentwicklung erreicht werden kann. Der Fokus in diesem Unterkapitel liegt deswegen nicht auf den klassischen Gesichtspunkten des Play-Testing, sondern lediglich auf das Testen des Lernfortschrittes.

Bei dem Play-Testing von Serious Games sollte es nach Symborski, et al. 4 verschiedene Phasen geben. Die ersten drei davon finden direkt hintereinander statt: Einen Pre-Test, bei dem der aktuelle Wissensstand vor dem Spielen geprüft wird, das Spiel an sich, sowie ein Post-Test, bei dem der Wissenstand direkt nach dem Spiel geprüft wird. Durch das Vergleichen des Pre-Tests und des Post-Tests wird der direkte Unterschied des Lernfortschrittes vor und nach dem Spiel erkenntlich. Für die Feststellung von Langzeiteffekten gibt es die vierte Phase: Den Follow-Up-Test, der einige Wochen nach den ersten drei Phasen durchgeführt werden soll. In der Veröffentlichung von Symborski, et al. wird die letzte Phase noch in zwei Tests unterteilt: Einer nach 8 Wochen, der andere nach 12. Für Projekte im Kontext des Studiums können hier durchaus kürzere Abstände gewählt werden, da in solchen Projekten oft Zeitmangel besteht.

Die zwei Teile der letzten Phase haben nach Symborski, et al. unterschiedliche Aspekte, die gestestet werden sollen. Im der folgenden Aufzählung befinden sich diese Aspekte unterteilt in den zwei Teilen:

  • Erster Teil (Nach 8 Wochen)
    • Confirmation Bias: Nur Infos suchen, die eigene Meinung bestätigen
    • Fundamental Attribution Error: Verhalten anderer wird auf deren Persönlichkeit zurückgeführt
    • Bias Blindspot: Man erkennt Bias bei anderen, aber nicht bei sich selbst
  • Zweiter Teil (Nach 12 Wochen)
    • Anchoring Bias: Erste Information beeinflusst Entscheidung stark
    • Representativeness Heuristic: Entscheidungen, weil etwas typisch wirkt
    • Projection Bias: Projektion eigener Einschätzung auf andere

Hierbei ist zu beachten, dass nicht bei jedem Projekt jeder Bias wichtig ist und getestet werden muss. Die Tests von den verschiedenen Biases wurden von Barton, et al. genauer beschriebenen, wobei die Grundstruktur immer der Vergleich der eigenen Antwort mit den korrekten Antworten ist. Die Abweichung zur richtigen Antwort stellt den Messwert dar.

Wartung und Updates

Updates und sonstige Patches, die neuen Content oder Bugfixes enthalten, werden in Godot über sogenannte Rescourcepacks ausgeliefert, welche in Godot entweder als PCK- oder ZIP- Dateien exportiert werden. Darin können sich alle möglichen Dateitypen, wie beispielsweise Skripte, Szenen und Texturen befinden. Es ist auch möglich weitere Godot-Projekte in den Rescourcepacks zu speichern, welche dann während der Laufzeit des ursprünglichen Projektes geladen werden.

Der Unterschied zwischen den PCK- und ZIP-Files besteht darin, dass die PCK-Files nicht komprimiert sind, die ZIP-Files allerdings schon. Dadurch sind die PCK-Files größer als die ZIP-Files. Allerdings ist ein PCK-File gegenüber eines ZIP-Files schneller lesbar, da hier der Inhalt ohne Komprimierung vorliegt. Es ist also abhängig von Faktoren, wie Größe der Inhalte und gewünschte Performance, welcher Dateityp für das Rescourcepack sinnvoller ist.

Das Exportieren der Rescourcepacks in Godot erfolgt über Projekt > Exportieren... > PCK/ZIP exportiern... oder über die Commandline. Die Rescourepacks können dann später im Code manuell mit einem Aufruf von ProjectSettings.load_rescource_pack geladen werden.

Projekt > Exportieren...

Durch das Nutzen von Rescourcepacks können nicht nur Updates und Patches, sondern auch Mods ausgerollt werden.

Symborski et al. The Design and Development of Serious Games Using Iterative Evaluation (Link), Zugriff 03. April 2026
Barton et al. The Use of Theory in Designing a Serious Game for the Reduction of Cognitive Biases (Link), Zugriff 05. April 2026
Godot Engine 4.6 documentation in English Exporting packs, patches, and mods (Link), Zugriff 03. April 2026
Godot Engine 4.6 documentation in English Exporting projects (Link), Zugriff 03. April 2026