Ein benutzerdefiniertes Bildbetrachtungsspiel für ein autistisches Kind
Einleitung
Mein Sohn Nat ist autistisch. Er schaut sich gerne Bilder von vertrauten Orten, Dingen und Menschen an. Wir kauften eine Digitalkamera, damit wir so viele Bilder von alltäglichen Dingen machen konnten, wie wir wollten, ohne uns um die Kosten und den Aufwand für Film und Entwicklung kümmern zu müssen. Nats Geschmäcker sind schwer vorherzusagen, daher haben wir vielleicht Bilder von einem Motiv gemacht, das ihn sicher erfreuen würde, nur um festzustellen, dass er überhaupt kein Interesse daran hat. Wir wollten beim Fotografieren einen weiten Bogen spannen, um sicherzustellen, dass wir die Bilder einfangen, die ihn interessieren würden.
Sobald wir die Kamera hatten, machten wir Hunderte von Bildern und zeigten Nat, wie er sie sich auf dem Computer mit einem handelsüblichen Bildbetrachter namens ThumbsPlus ansehen konnte. Als ich Nat beim Durchklicken der Bilder beobachtete, bemerkte ich etwas: Sobald er sich mit der Reihenfolge der Bilder vertraut gemacht hatte, klickte er auf die Bilder, als ob es darauf ankäme, wohin er klickt. Der Bildbetrachter kümmerte sich nicht darum: Jeder Klick auf das Bild zeigte das nächste Bild. Aber wenn Nat wusste, dass das nächste Bild etwas war, das sich links vom aktuellen Bild befand, klickte er auf die linke Seite des Bildes. Wenn er wusste, dass das nächste Bild durch eine Tür rechts vom Bild ging, klickte er auf die Tür. Er hat eine Reihe von Abenteuerspielen für Kinder gespielt, wie zum Beispiel Pajama Sam, und kannte diesen Navigationsstil. Selbst in einem Programm, das diesen Navigationsstil nicht verwendete, hatte er begonnen, ihn zu nutzen, als ob er es täte.
Daher dachte ich mir: Warum nicht einen Bildbetrachter machen, der auf seine Art funktioniert? Warum nicht ein Programm schreiben, mit dem ich Bildumgebungen aus unserem Leben erstellen kann und Nat darin auf die Art und Weise navigieren kann, wie er es wollte?
Eines von über 1500 Bildern in Natsworld. Die Benutzeroberfläche besteht einfach aus einer Reihe von Richtungspfeilen (in der Mitte) Vergrößern
Die Wahl von Python
Ich hatte Python zuvor für kleine Skriptprojekte verwendet und mochte sein schnelles Startgefühl. Es würde mir eine formbare Umgebung bieten, in der ich mit Funktionen experimentieren konnte, um zu sehen, was Nat interessant finden würde. Obwohl dies ein Projekt zu Hause war, das nur von meinem Sohn genutzt werden sollte, teilte es Probleme mit größeren, angeblich ernsteren Projekten: unklare Anforderungen, unvorhersehbare Kunden und begrenzte Entwicklerressourcen. Das wichtigste Anliegen bei der Auswahl der Entwicklungswerkzeuge war meine Produktivität. Da dies eine Arbeit "nach Feierabend" war, wären meine Zeit und meine Aufmerksamkeit stark beansprucht, und ich wollte mich auf das Benutzererlebnis konzentrieren können, anstatt Umgebungen, Speicherverwaltung und Ähnliches aufzubauen.
Ich suchte nach bestehender Software und fand viele interessante Beispiele bei pygame (www.pygame.org). Pygame bot alle Funktionen, die ich für Bildbearbeitung und Anzeigemanagement benötigte, und es gab dort einige bestehende Projekte, die nützliche Beispiele lieferten. Pyzzle bot fast das, was ich brauchte, war aber intern nicht so gut organisiert, wie ich es mir gewünscht hätte, um schnell mit neuen Funktionen experimentieren zu können.
Implementierung
Mit Hilfe der vorhandenen Beispiele, die meine pygame-Nutzung leiteten, erstellte ich ein neues Framework für mein Programm. Mein Programm, das ich einfach "Nat's World" nannte, würde eine virtuelle Welt zur Erkundung bieten. Es würde so funktionieren, wie Nat es erwartete, und eine einfache Erkundungsumgebung ähnlich wie bei Spielen wie Myst bieten; ein Klick auf die linke Seite des Bildschirms würde Sie nach links drehen, ein Klick in der Mitte würde Sie vorwärts bewegen und so weiter.
Im einfachsten Fall bestand die gesamte Umgebung nur aus einer Reihe von Knoten, von denen jeder ein Bild zum Anzeigen und eine Liste anderer verbundener Knoten zum Navigieren hatte. Ein physischer Ort in der Welt wird durch eine Reihe von Knoten dargestellt, einen für jede Blickrichtung. Diese Knoten zusammen werden als "Spot" bezeichnet. Im Laufe der Zeit wurde dieses Modell erweitert, um dem Umfeld Funktionen hinzuzufügen, aber dieses einfache Modell hat mir den Start erleichtert. Python gab mir eine saubere objektorientierte Grundlage für den Aufbau meiner Node-Klasse, und pygame lieferte die Primitive für die Anzeige von Bildern, die Erstellung von Cursors und die Sammlung von Eingaben.
Eine der größten Herausforderungen war die Entscheidung zwischen verschiedenen Möglichkeiten, die Beschreibung der Welt zu organisieren. Einerseits hätte ich eine beschreibende Sprache für die Struktur der Welt erstellen und einen Interpreter schreiben können, der die Beschreibung liest und die In-Memory-Strukturen aufbaut, auf denen das Spiel laufen würde. Dies wäre eine ziemlich große Anstrengung gewesen und hätte von mir verlangt, alle möglichen Strukturen zu formalisieren. Es hätte auch eine längere Verzögerung bedeutet, bevor ich etwas hatte, das Nat tatsächlich nutzen konnte. Andererseits hätte ich einfach Python-Anweisungen verwenden können, um die Strukturen direkt zu konstruieren. Das wäre mühsam und fehleranfällig gewesen.
Als praktischer Mittelweg habe ich Python-Anweisungen verwendet, um die Welt aufzubauen, aber stark auf Hilfsfunktionen und -klassen zurückgegriffen, um Verknüpfungen für gängige Strukturen bereitzustellen. Zum Beispiel sind meine Bilder alle in Verzeichnissen gespeichert, die nach Datum benannt sind, und ich hätte für jeden Knoten einen Bildnamen eingeben müssen. Die Klasse ImgShortcut machte dies einfach. Die Definition der__call__Methode erlaubte es mir, mit der Syntax von Python zu spielen, um den gewünschten Effekt zu erzielen
class ImgShortcut:
def __init__(self, fmt):
self.fmt = fmt
def __call__(self, arg):
return self.fmt % (arg)
nov4 = ImgShortcut(r'C:\img\vol3\20011104\dscf%04d.jpg')
nov10 = ImgShortcut(r'C:\img\vol3\20011110\dscf%04d.jpg')
>>> print nov4(17)
c:\img\vol3\20011104\dscf0017.jpg
Als weiteres Beispiel teilten viele Spots in der Welt dieselbe Vier-Knoten-Struktur: eine für die Nordansicht, eine für die Westansicht und so weiter. Mit der Schlüsselwort-Argument-Syntax von Python konnte ich eine Funktion schreiben, um diesen gängigen Spot-Typ zu erstellen
def nesw(name, **data):
"""
Make four nodes for n, e, w, s from a location.
Keys:
images: ni, ei, wi, si.
destinations: n, e, w, s.
"""
# (code omitted)
Das erste Argument ist der Basisname für die neuen Knoten (die Knotennamen werden durch Anhängen von ":n", ":w" usw. gebildet). Die verbleibenden Argumente werden über Schlüsselwörter angegeben: ni ist der Bildname für den Nordknoten, n ist der Knoten im Norden; wi ist das Bild für den Westknoten, w ist der Knoten im Westen und so weiter. Jetzt kann ich einen Spot mit einer einfachen Kurzschreibweise erstellen
nesw('front43',
ni = nov4(17),
ei = nov4(18), e = 'allerton_hawthorne:e',
si = nov10(381), s = 'hall:s',
wi = nov4(16), w = 'markliesl:w'
)
Aufgrund der Schlüsselwort-Syntax kann ich Argumente weglassen, die für den jeweiligen Spot nicht zutreffen. Jetzt habe ich eine nahezu deklarative Syntax, die sich zum Erstellen gängiger Strukturen eignet, aber ohne einen Interpreter für eine neue Minisprache schreiben zu müssen. Und wenn ich einen ungewöhnlichen Fall habe, der volles Python benötigt, steht mir das zur Verfügung.
Die Welt und das Programm zur Unterstützung wuchsen parallel. Als mir neue Ideen für Strukturen für Spots einfielen, schrieb ich neue Hilfsfunktionen wie nesw(), um sie einfach zu erstellen. Ich konnte Nat beim Spielen des Spiels beobachten, sehen, was er wollte, und schnell Funktionen hinzufügen. Viele der Funktionen von Python (interpretierter Code, Objektorientierung, Garbage Collection, Listen und Wörterbücher) unterstützten diese schnelle Wende.
Die Node-Klasse wurde erweitert und unterklassifiziert, um neue Knotentypen zu erstellen. Zum Beispiel fügte ich eine MenuNode-Unterklasse hinzu, um Bildschirmmenüs von Zielen zu verarbeiten. Dies ermöglichte das Klicken auf das Auto und die Auswahl des gewünschten Ziels. Übergänge zwischen Knoten wurden hinzugefügt, um den Effekt angenehmer zu gestalten. Das Klicken auf das Stereo erzeugte ein Menü mit Liedern zum Abspielen (natürlich über pygame).
Ergebnisse
Zu diesem Zeitpunkt beträgt die Gesamtgröße des Quellcodes etwa 1400 Zeilen Code, zuzüglich 1300 Zeilen, die die Welt beschreiben, die derzeit über 1500 Knoten umfasst.
Wenn ich Nat's World Freunden zeige, sagen sie immer, wie toll es wäre, wenn ich etwas Ähnliches für andere Leute ermöglichen könnte. Ich habe darüber nachgedacht, eine WorldBuilder-Anwendung zu schreiben. Sie würde es einer nicht-technischen Person ermöglichen, über eine GUI Bilder zu durchsuchen und sie zu einer Welt von Knoten zu verbinden. Es wäre ein schönes Projekt zum Erstellen und noch schöner, es zu haben, da ich es selbst nutzen könnte, um Nat's World zu erweitern. Ich weiß nicht, ob ich jemals die Zeit und den Fokus haben werde, so etwas in meiner Freizeit zu bauen, aber wenn ich es hätte, wüsste ich, dass Python das Werkzeug für die Aufgabe wäre.
Über den Autor
Ned Batchelder ist ein Softwareingenieur aus Brookline, MA. Seine Frau und seine drei Jungen spielen alle gerne Nat's World. Seine Website ist https://www.nedbatchelder.com.
