Ataquarium - Spieleentwicklung mit Highwire

Haben Sie die Sommerpause gut überstanden? Der Sommer war – zumindest im hohen Norden – ein sprichwörtlicher Schlag ins Wasser und gab somit eine gute Ausrede, sich auch während der Sommerpause einmal an den heimischen Computer zu setzen und den C-Compiler zu malträtieren. Wie üblich sind diese scheue Tiere, die sich allzu aufdringlichen Programmierversuchen mit hunderten Warnungen zu entziehen versuchen.

Von der Open-Source-Front gibt es wieder mal neues zu vermelden: so stellte Didier Méquignon den Source seines Aniplayer online. Jeder der Interesse hat, braucht bloß noch das Paßwort für das ZIP-Archiv (4,2 MB) und schon steht der Source, der mit den beiden Assemblern Devpac und Profimat (!) verfaßt wurde, offen. Kleine Geschichtsstunde: Profimat war 1987 ein bekannter Assembler für den ST und Amiga. Die Firma Data Becker hatte jedoch kein großes Glück mit ihren Programmiersprachen für den ST und so wurde aus dem Profimat ein eher kurzlebiges Produkt. Angehende Mit-Entwickler müssen sich also auf die Suche machen, aber über Google und eine Suche nach "Profimat Atari" ist der Assembler schnell gefunden.

Zum Glück haben sich die Highwire-Entwickler bei der Wahl ihrer C-Compiler nicht für Alcyon C, sondern für die aktuelleren GnuC, LatticeC und PureC entschieden. Nachdem das Thema "Applikationsentwicklung mit Highwire" in den vergangenen Ataquarien kurz angeschnitten wurde, gehen wir diesmal in die vollen: ein Quizspiel soll entstehen. Dabei wird schnell deutlich, welche Vorteile durch die Entwicklung eines Großteils des Spiels in HTML entstehen, aber auch die Nachteile in Form von Beschränkungen seitens Highwire.

Quizmaster

Als Grundlage diente die HighWire-Version 0.06A. Bei der Programmierung des Spiels habe ich darauf geachtet, möglichst wenig im HW-Sourcecode zu ändern, um bei Änderungen an Highwire möglichst schnell updaten zu können. Deshalb sind auch keine Optimierungen enthalten, obwohl diese möglich wären, denn das Quiz-Spiel benötigt nicht alle HTML-Tags.

Das Grundkonzept des Spiels ist ein Quiz mit Fragen im Multiple-Choice-Verfahren. Damit entfallen Tastatureingaben und es wird eine wesentliche Einschränkung umgangen: die fehlende Unterstützung von Eingabefeldern in Highwire. Zu jeder Frage gibt es ein Bild im GIF-Format und drei Auswahlmöglichkeiten. Ist die ausgewählte Antwort richtig, wird ein entsprechender Bildschirm angezeigt, bei einer falschen Antwort ebenfalls. Maximal werden sieben Fragen gestellt, die per Zufallsgenerator ausgewählt werden.

Das Thema des Quiz-Spiels ist, ebenso wie die Fragen, fest einprogrammiert, aber es könnte sicherlich schnell eine Version mit nachladbaren Fragen erstellt werden.

Dr. Who-Quiz

center
Bild 1

Vielleicht ist einigen das Dr. Who-Quiz bekannt, das auf [1] zum Download ausliegt. Von diesem stammen Grafiken und Fragen für das Quiz. Erstere sind dank des GIF-Formats in einer besseren Qualität als dies mit Farbicons nötig wäre.

Die Änderungen an Highwire finden zum Großteil in der Datei loader.c statt. Seit einiger Zeit unterstützt Highwire das about-Protokoll, mit dem Browser-interne Seiten angezeigt werden. Dieses Protokoll bietet eine relativ einfache Möglichkeit, eigene Seiten einzubauen, ohne gleich in die Link-Verwaltung einzugreifen. Im Browser selber ist nur eine interne Seite eingebaut, die Infos zur aktuellen Version gibt. Ein Link auf eine interne Seite sieht so aus:

<a href="about:test">Interne Seite</a>

Interessant ist in loader.c die Funktion new_loader_job. Diese Funktion schaut sich das verwendete Protokoll in einer URL an und leitet dies an die nächste Funktion weiter. Neben dem about-Protokoll wird zwischen lokalen HTML-Dateien, Grafiken und Dateiformaten wie PDF unterschieden. Es gibt auch eine Unterstützung für den Online-Betrieb (STiK, MiNTNet), der in der PRJ-Datei über USE_INET aktiviert wird.
Das about-Protokoll wird gleich am Anfang behandelt:

	if (loader->Location->Proto == 1) { /* 'about:' request */

Dort steht eine Zuweisung in der Form

	loader->Data = strdup ("<html><head><title>About: HighWire</title>"
	                       "</head><body>\n" 

Da HighWire derzeit nur eine "about:"-Seite kennt, wird auch nicht weiter unterschieden, was nach dem Doppelpunkt kommt. Da die eingebaute Seite in einem Quiz-Spiel fehl am platze ist, wird diese komplett gelöscht, so das letztendlich nur zwei Zeilen übrig bleiben:

	loader->MimeType = MIME_TXT_HTML;
	sched_insert (parser_job, loader);

Diese zwei Zeilen schicken die interne HTML-Seite zur Weiterverarbeitung ab. Alles was wir einfügen, muß also vor den beiden Zeilen geschehen. Im Gegensatz zur internen Seite von HighWire muß die Seite mit den Fragen dynamisch zusammengebaut werden, deshalb bedarf es noch zwei Hilfsvariablen vom Typ char:

	char	*bastel[2048];
	char	*hilfstext[3];

Wie an der Größe unschwer zu erkennen ist, nimmt "bastel" den ganzen HTML-Quelltext auf. Zwei KB reichen für das Quizspiel völlig aus. "hilfstext" wird benutzt, um die Anzahl der richtigen Antworten anzuzeigen. Dies sind nicht die einzigen Variablen, die benötigt werden. So muß das Quiz wissen, wieviel Fragen richtig oder falsch beantwortet wurden. Damit nicht alle Fragen gespielt werden müssen, soll das Spiel die Anzahl der beantworteten Fragen ebenfalls mitzählen. Um das ganze übersichtlich zu halten, wird alles in einer Struktur "spielstand" zusammengefaßt:

struct
{
	int richtig;
	int falsch;
	int geschafft;
} spielstand;

In loader.c stehen alle Strukturen ab Zeile fünfzig. In der unveränderten Version sind dort die MIME-Typen notiert.
Damit kann schon einmal der erste Bildschirm programmiert werden. Wie jedes anständige Spiel hat auch "Dr. Who Quiz" einen Begrüßungsbildschirm. In new_loader_job wird an der Stelle der gelöschten internen Seite folgendes eingetragen:

strcpy(bastel, "<html><title>Dr. Who Quiz</title><body bgcolor=black 
text=white link=blue marginwidth=20 marginheight=20>\n");

center
Bild 2

Dies ist der "Kopf" für alle HTML-Seiten, die ausgegeben werden. HTML-Puristen werden vermutlich bemängeln, das keine Anführungszeichen gesetzt wurden, aber der HTML-Code ist ohnehin im Programm verankert und daher nicht einsehbar.
Der Titelbildschirm soll über "about:anfang" erreichbar sein. Die komplette Adresse speichert Highwire in "address". Dementsprechend wird eingefügt:

if (strstr (address, "anfang")>0) {
	spielstand.richtig = 0;
	spielstand.falsch = 0;
	spielstand.geschafft = 0;
	strcat(bastel, "<center><img src=\"/grafiken/whologo.gif\"><br>");
	strcat(bastel, "<font color=purple size=+2>Welcome to the Dr. Who-Quiz!</font><br>");
	strcat(bastel, "<font color=red size=+2>Version 1.0</font><br>");
	strcat(bastel, "<font color=lightblue size=+2>(C) 2002 Matthias Jaap</font><br>");
	strcat(bastel, "<a href=\"http://www.mypenguin.de/prg/\"><font 
size=+2>http://www.mypenguin.de/prg/</font></a><br>");
	strcat(bastel, "<a href=\"about:frage\"><font size=+2>Start game</font>
	</a><br></center>");
}

Zu Beginn wird überprüft, ob die Adresse überhaupt den Text "anfang" enthält. Ist dies der Fall, wird der Spielstand zunächst zurück gesetzt.
Der erste Bug in Highwire wird in der folgenden Zeile deutlich. Eigentlich sind die Grafiken eine Verzeichnisebene höher, aber wenn im <IMG>-Tag nur "grafiken/whologo.gif" stehen würde, sucht HW nach einer Grafik "anfagrafiken/whologo.gif". Es ist durchaus möglich, das dieser Bug bei Erscheinen des Heftes schon behoben wurde.
Mit dem ersten Link könnte die passende Internet-Seite für das Quiz aufgerufen werden. Theoretisch wäre es sogar möglich, automatisch Updates herunterzuladen.
Nach der If-Abfrage muß der zusammengebastelte String noch ergänzt und übergeben werden:

	strcat(bastel, "</body></html>");
	loader->Data = strdup (bastel);

Jetzt ist zwar die erste interne Seite fertig, aber HW sucht nach einer anderen Startseite. Es muß also die Default- Seite geändert werden. In der main.c in highwire.c wird def_adress[] auf "about:anfang" geändert. Bei der Gelegenheit können auch gleich die drei Zeilen nach char *address; gelöscht werden, um das Auswerten der Kommandozeile zu verhindern.
Nach einem Make und ein paar Warnungen liegt die erste Version vor, die noch nicht viel tut (Bild 1). Schon die erste Version könnte aber eine unangenehme Eigenschaft von Highwire zeigen: die Textanzeige funktioniert nur mit Speedo-Fonts. Tatsächlich benötigt HW feste Font-IDs – andere Programme wie der HomePage Penguin, der sich auch auf das Vorhandensein bestimmter Fonts verläßt, suchen nach Fontnamen, was dann auch mit den wesentlich beliebteren TrueType-Fonts funktioniert. Zum Glück soll sich dies schon bald ändern, denn TTF- Unterstützung ist angekündigt.

Fragen über Fragen

Was wäre ein Quiz ohne Fragen? Diese fehlen aber bisher völlig. Zurück in der loader.c soll dies geändert werden. Jede Frage besteht im Dr. Who-Quiz aus sieben Teilen: Frage, richtige Antwort, die drei Auswahlmöglichkeiten, der Grafik und einem Zähler. Der Zähler wird hochgesetzt, sobald die Frage einmal gestellt wurde.
Die Struktur für die Fragen wird an der bekannten Stelle in loader.c abgelegt.

Da das gesamte Spiel in englischer Sprache verfaßt ist, gibt es natürlich auch keine Probleme mit Umlauten. Bei einer deutschen Version müßten diese, wie in HTML üblich, markiert werden. Nach den drei Auswahlmöglichkeiten steht der Dateiname der Grafik ohne Endung. Da HW ohnehin nur GIF-Dateien verarbeitet, steht die Extension ohnehin fest.
Damit das Quiz weiß, wieviel Fragen es gibt, wird in der gleichen Datei nach den includes noch ein #define und eine weitere Hilfsvariable eingefügt:

#define FRAGENANZ	14
int zahl;

Jetzt kann endlich die Seite "about:frage" gebastelt werden. Der komplette Code wird nach der ersten Seite eingefügt und ist in Listing 1 zu sehen.
Über der Frage wird der aktuelle Spielstand eingeblendet. Die anfangs definierte Hilfsvariable "hilfstext" wird zur Konvertierung der Zahl in einen String benutzt.
Nun wird der Zufallsgenerator angeworfen. Wenn die Frage schon gestellt wurde, wird solange eine neue Zahl ermittelt, bis dies nicht mehr der Fall ist. Nachdem die Frage feststeht, wird die Grafik eingefügt. Dies wäre bei Frage 1 "ace.gif". "align=left" sorgt dafür, das der Text neben der Grafik dargestellt wird. Zwar wäre dies auch mit einer Tabelle möglich gewesen, aber die verwendete Version von Highwire hatte noch Probleme mit Grafiken innerhalb einer Tabellenzelle.
Schon beim Zusammenbasteln wird ein unterschiedlicher Verweis für eine falsche bzw. richtige Antwort angelegt. Da HW das Ziel des Verweises nicht anzeigt, ist Schummeln nicht möglich.

Die erste Frage kann damit angezeigt werden und es könnte wie in Bild 2 aussehen. Die Anzeige von GIF- Bildern funktioniert in der verwendeten Version nur in einer Auflösung mit 256 Farben zum großen Teil korrekt. Farbtiefen wie 16 Bit werden zwar unterstützt, aber die Farben sind stark verfremdet.

Richtig und falsch

Egal wie gut oder schlecht der Spieler ist – irgendwann endet jedes Quiz. In die Seiten für die falsche und richtige Antwort (Listing 2) ist deshalb eine Abfrage eingebaut, wieviel Fragen schon beantwortet wurden. Nach sechs Fragen ist Schluß. Wenn hier noch ein Verweis auf den Spielstart eingebaut werden soll, muß eine Schleife eingebaut werden, die den Zähler der einzelnen Fragen auf 0 setzt. Damit wäre das Quiz vollständig spielbar (Bild 3).

Schönheitskorrekturen

Jetzt können noch ein paar Spuren verwischt werden. Unter N.AES, XaAES und MultiTOS erscheint das Quiz im Anwendungsmenü immer noch als "Highwire". Eine Änderung von menu_register in highwire.c behebt dies:

menu_register(gl_apid, "  Dr.Who-Quiz");

Ebenso sollte der Text der Info-Alertbox abgeändert werden. Diese steht in do_info_dialog in der gleichen Datei. Die Infozeile des Fensters wird derzeit u.a. zur Anzeige der zuletzt geladenen Grafik benutzt. Um dies abzustellen müssen nur die Aufrufe von set_info() in aei.c gelöscht werden. Ebenfalls in aei.c sind die GEMScript-Routinen. HW unterstützt drei Kommandos: Open, Quit und Appgetlongname. "Open" kann bei einem Quiz entfallen, der Rückgabewert von Appgetlongname muß von "Highwire" auf "Dr. Who Quiz" geändert werden.

center
Bild 3

Updates

Neben den offziellen Updates gibt es alle paar Tage Patches von Baldrick (Dan Ackerman), AltF4 (Ralph Lowinski) und Rainer Seitel. Ein Blick in die Änderungen zeigt, das ein Großteil der Änderungen nicht in den hier behandelten Dateien aei.c, highwire.c und loader.c stattfindet. In dem Fall ist ein Update sehr leicht möglich. Von Baldrick folgt wenig später oft eine Version, die vorangegangene Patches zusammenfaßt. In dieser Version sind dann auch alle Dateien enthalten, daher ist etwas Vorsicht angebracht, um nicht das eigene Projekt zu überschreiben.

Möglichkeiten, das Quiz schöner zu machen, gibt es genug. So wäre Sound durch das <BGSOUND>-Tag sehr einfach möglich. Das Ändern der Info-Zeile ist auch ganz ohne C möglich:

<IOD4 SHOUT="Neuer Inhalt der Statuszeile">

Dieses Tag wird seit HW0.07A unterstützt und stammt aus dem (weitgehend unbekannten) Browser I/O/D/4.

Fazit

Soweit der erste Ausflug in die Programmierung mit C und HTML. Je leistungsfähiger der Browser ist, desto mehr kann im HTML-Bereich gemacht werden. So wäre dieses Quiz mit etwas Aufwand auch in JavaScript unter Light of Adamas realisierbar und im Open Source-Browser Mozilla ist (fast) alles mit Web-Sprachen möglich. Der Vorteil der hier vorgestellten Methode ist, das am Ende eine eigenständige Anwendung herauskommt.
In der Anleitung sollte aber erwähnt werden, das die Anwendung auf den Sourcen von Highwire basiert.

Listings

[1] http://www.jaapan.de/software/html-spiele-fuer-den-st/


Mia Jaap
Aus: ST-Computer 09 / 2002, Seite 37

Links

Copyright-Bestimmungen: siehe Über diese Seite