Das dritte Level - Kompatible Spieleprogrammierung, Teil 3: Spiele unter MultiTOS

Teil 1: Richtlinien und Blick auf andere Rechnersysteme
Teil 2: Grundregeln zur hardwarenahen Programmierung
Teil 3: Kompatible Spiele unter MultiTOS
Teil 4: Spiele auf Graflkkarten; alternative Treiberkonzepte

Brot und Spiele

Kompatible Spieleprogrammierung

Teil 3: Spiele unter MultiTOS

Hallo zum dritten Teil unserer Artikelserie. Diesmal geht es um Spiele unter MultiTOS. Zur Zeit läuft kein mir bekanntes, kommerziell vertriebenes Spiel unter MultiTOS, mit Ausnahme einiger recht einfach gehaltener Programme und dem Spiel, welches ich in [2] erkläre. Hier möchte ich zeigen, wie man Spiele programmiert, die nicht nur unter MultiTOS laufen, sondern es auch ermöglichen, immer noch zu anderen Programmen zu wechseln und neue zu starten.

Die wenigsten Spiele laufen in echten GEM-Fenstern, denn an sich liebt der Spieler den Fullscreen (je breiter, desto besser). Das ist auch verständlich, denn die Sprites sind größer, „und man fühlt sich fast wie im Kino". Nur scheint das unter MultiTOS nicht möglich zu sein, denn da soll ja alles in Fenstern laufen. Aber mit einem kleinen Trick geht es doch, und zwar mit folgenden AES Befehlen:

wind_update(BEG_UPDATE); wind update(BEG_MCTRL);.

...

wind_update(END UPDATE); wind_update(END_MCTRL);

Dabei gibt BEG UPDATE' an, daß man direkt auf den Bildschirm ausgeben möchte. Es ist dann keinem anderen Programm erlaubt, Ausgaben auf den Bildschirm zu machen, bis man mit END_UPDATE' die Kontrolle wieder freigegeben hat. Gleichermaßen reserviert BEG MCTRL' die Maus für das laufende Programm. Mit END_MCTRL' gibt man die Kontrolle an die AES oder das Programm, dem das oberste Fenster gehört, zurück. An sich sollte man, obwohl man gar nicht in ein Fenster ausgeben möchte, selbst Besitzer des obersten Fensters sein (einfach ein Dummy-Fenster öffnen), um die Tastaturereignisse gemeldet zu bekommen. Zudem sollte zuvor form_dial()' Modus FMD_START' den Bildschirm reservieren, um dann mit `FMD_FINISH' die anderen Programme (inklusive Bildschirmmanager) zu zwingen, ihre Fenster (auch das Fenster 0 des Bildschirmmanagers, aber nicht die Menüzeile!) zu restaurieren (siehe dazu auch [8]).

Auf jeden Fall sollte man dem Spieler die Möglichkeit geben, via Tastendruck oder Mausklick die GEM-Oberfläche restaurieren zu können, um bei Bedarf ein zusätzliches Programm starten oder zu einem noch laufenden wechseln zu können. Damit allerdings ein weiteres Programm gestartet werden kann, muß die ...

Speicherverwaltung ...

... stimmen. Nun ist das ganze gar nicht so schwer, solange man in „C" programmiert, da die meisten neueren C Compiler von vornherein einen Startup-Code einbinden, welcher den gesamten Speicher - bis auf Heap und Stack - beim Start des Programms an das Betriebssystem zurückgibt. Ansonsten bekommt das Programm, wenn MINT nicht mit der MAXMEM'Variable anders konfiguriert wurde, den ganzen Speicherplatz zugewiesen. Man kann in Ermangelung dessen dann auch keine andere Applikation mehr starten. Wie auch immer, man kann ja mit Mshrink()' den momentan nichtgebrauchten Speicher an das Betriebssystem zurückgeben und bei Bedarf mit `Malloc()' häppchenweise wieder holen. Aber Vorsicht („is cool man"), wenn man die Häppchen zu klein macht, wird unnötig Speicher verschenkt, weil MINT auf einem 68030-Prozessor wegen der MMU Page-Größe (das hat was mit dem Speicherschutz zu tun) immer minimal 4KB große Speicherblöcke alloziert. Selbst wenn das nicht der Fall ist, sollte man trotzdem versuchen, größere Speicherblöcke anzufordern (das „C" Malloc macht das sowieso) und diese dann selbst verwalten. Damit vermeidet man die Fragmentierung des Speichers, die durch häufiges Anfordern und Freigeben kleinerer Blöcke, gerade wenn mehrere Programme gleichzeitig laufen, entstehen kann. Fragmentierung, Zerstückelung des Hauptspeichers in viele unzusammenhängende freie Bereiche, führt immer dann zu Problemen, wenn vom Programm ein großer Speicherblock benötigt wird.

Auch Speicher für zusätzliche Bildschirmseiten muß vom Betriebssystem angefordert werden und darf (auch im „normalen" TOS) nicht einfach unterhalb der vom Betriebssystem angelegten Bildschirmseite plaziert werden.

Animation und Sprites in Fenstern

Auflösungen mit bis zu 256 Farben sind bei dem On-Board-Video-Subsystem der ATARI-Rechner planeweise organisiert, wobei n Planes zu jeweils n Wörtern hintereinander angeordnet sind. Hierbei repräsentiert n die Farbtiefe in Bits. Beispielsweise liegen bei 256 Farben acht Wörter hintereinander im Speicher und bestimmen die Farben der ersten 16 Pixel. Die Planes sind also interleaved angeordnet. Benutzt man einen Rasterkopierbefehl und kopiert ein mehrfarbiges Raster vom Speicher auf den Bildschirm, kann man verfolgen, wie das Betriebssystem Plane für Plane auf den Bildschirm kopiert, was zu seltsamen Verfärbungen der Pixel führt. Wenn man statt der Betriebssystemrasterkopierroutine eine eigene schreibt, kann man diese natürlich so anlegen, daß immer erst alle Planes einer Zeile kopiert werden, was in den meisten Fällen das Flackern vermeidet. Allerdings wirkt der Blitter wenig effektiv, wenn er in gleicher Weise vorgehen soll. Mir ist allerdings aufgefallen, daß z.B. TOS 3.06 (seltsamerweise nicht TOS 2.06) und NVDI bei abgeschaltetem Blitter - die Raster tatsächlich schon zeilenweise kopieren und damit das Flackern vermeiden. Leider kann man dem Falcon-VDI nicht verbieten, den Blitter zu benutzen, da die Funktion `Blitmode()' von dessen TOS nicht unterstützt wird, auch weiß man nicht, mit welcher Technik das VDI - wenn entsprechende Routinen implementiert wären - in diesem Fall Raster kopieren würde.

Warum ich das Problem mit dem Kopieren von rechteckigen Blöcken angesprochen habe, ist leicht zu verstehen, wenn man weiß, daß man, um effektiv Spiele im Fenster laufen lassen zu können, die Sprites mit Maske (ebenfalls rechteckige Blöcke) mit dem Hintergrund verknüpfen (siehe Bild) und - je nach Technik - komplett oder nur ausschnittweise den so im Speicher erzeugten Screen in das Fenster kopieren muß. Um das Flackern zu vermeiden, kann man entweder das VDI benutzen, wobei man - da man immer nur kleine Teile des Gesamtbildes kopieren darf-möglicherweise eine langsame Bildausgabe in Kauf nehmen muß, oder man beschreibt inkompatiblerweise den Bildschirmspeicher direkt. Wenn man dabei das Fenster immer auf Wortbreite, also 16 Pixel, ausrichtet, und die Fensterbreite und das Verschieben des Inhalts auch in 16-Pixel-Schritten erfolgt, benötigt man keine Rasterkopierroutine mehr, sondern kann entsprechende Teile des Speichers komplett ins Fenster kopieren. Das geht allerdings nur, solange das Fenster nicht verdeckt ist. Aber man kann das Spiel ja anhalten, wenn das eigene Fenster nicht mehr das oberste ist.

Es ist gefährlich, nicht via VDI zu kopieren, da so etwas auf vielen Grafikkarten Probleme bereitet. Auf jeden Fall sollte man VDI-Routinen benutzen und die anderen Möglichkeiten, Blöcke ins Fenster zu kopieren, alternativ dazu anbieten.

Off-Screen-Bitmaps

In bestimmten Situationen ist es recht angenehm, wenn die Zeichenfunktionen nicht auf den Schirm, sondern in einen Speicherbereich ausgegeben werden können. Früher hat man einfach mit Setscreen()' die logische Bildschirmadresse auf einen Speicherbereich gerichtet, und schon konnte man auf diesem Bereich die Zeichenfunktion genauso wie auf dem Bildschirm einsetzen. Das macht Probleme im Multitasking, weil ein Programm die Logbase' des anderen verstellt. Zudem funktioniert das Verfahren mit den wenigsten Grafikkarten. Heute benutzt man Off-ScreenBitmaps, wobei die heute gebräuchlichen dahingehenden Betriebssystemerweiterungen nur folgende Gemeinsamkeit haben: Sie bieten die Möglichkeit, einen nur durch den Speicher begrenzten virtuellen Bildschirm zu öffnen, auf den die Zeichenfunktionen umgelenkt werden. Ich selbst kenne zwei Definitionen für Off-Screen-Bitmaps. Zum einen die des Treibers meiner Grafikkarte [9], welcher zu der oben beschriebenen Funktion noch die Möglichkeit bietet, auch Bitmaps mit einer anderen (1, 8, 24, 32 Bit) als der aktuellen Farbtiefe zu verwalten. Zum anderen die von [10] & [11], welche zusätzlich zur eingestellten nur 1 Bit Farbtiefe verwalten. Wobei [11] frei kopierbar ist und das ATARI-VDI um die Off-Screen-Funktionen von [ 101 erweitert.

Solange sich die Hersteller solcher Betriebssystemerweiterungen nicht über Syntax und Parameter neuer Funktionen einigen können, ist es für den Programmierer schwer, Applikationen zu schreiben, welche diese Funktionen nutzen. Allerdings ist es von Vorteil, daß es [11] gibt, weil so jeder die Möglichkeit bekommt, mit OffScreen-Bitmaps zu arbeiten - auch wenn [11] nicht den vollen Funktionsumfang von [9] hat.

Auflösungsunabhängig?

Laut ATARI (siehe Teil 1, [B] und [H] der Game/Entertainment-Software-Guidelines) sollte man Spiele so schreiben, daß man sie in jeder Grafikauflösung starten kann. Nun, das muß nicht unbedingt bedeuten, daß man das Spiel in jeder Auflösung spielen kann; eine simple Alert-Box, welche angibt, welche Auflösung man einstellen muß, um das Spiel auch spielen zu können, würde [B] genügen. Naja, laut [H] soll man die vr_trnfm()' (TRANSFORM FORM)-Funktion nutzen, um die Grafikdaten vom Standard- ins geräteabhängige Format, nämlich der eingestellten Auflösung, zu wandeln. Nun kann die vr= trnfm()'-Funktion ja eine ganze Menge, nur anständig Grafikdaten in ein geräteabhängiges Format mit weniger Bitplanes wandeln kann sie noch nicht. Dazu müßte die Funktion durch „Dithern" die Farben andeuten. So etwas oder andere Techniken, um die Anzahl der Farben zu reduzieren, beherrscht das VDI leider noch nicht. Da im Standardformat die Grafikdaten in einzelnen Planes vorliegen, ist es auch gar nicht so leicht, selbst etwas zu schreiben, was die Grafikdaten zu Daten mit geringerer Farbtiefe konvertiert. Einfacher wird das ganze, wenn Grafik im Packed-Pixel-Format vorliegt, denn bei Auflösungen mit gleicher und höherer Farbtiefe kann man vrt_cpyfm()' benutzen (COPY RASTER, TRANSPARENT), setzt die Palette und überträgt Pixel-Guppe für PixelGruppe gleicher Farbe, indem man die Funktion auf ein leeres Stück Speicher richtet und den color-index' des Hintergrunds auf die Farbe der Pixel Gruppe setzt und kopiert. Beim Konvertieren in niedrigere Farbtiefen benutzt man wieder `vrt_cpyfm', muß aber darauf achten, daß man die Farben erst durch einen Algorithmus zur Reduktion der Farbtiefe umrechnen muß. Darüber gibt es aber entsprechende Literatur in [14] und [15] (siehe dazu auch die ATARI-Listings zum PD-Raytracer „POV-Ray"). Es hat in diesem Zusammenhang keinen Sinn, eine Farbreduktion vorzunehmen, wenn man (z.B. in Monochrom) die Sprites vom Hintergrund nicht mehr unterscheiden kann.

Zur Auflösungsunabhängigkeit gehört allerdings nicht nur, daß die Farbtiefe, sondern daß auch die Größenverhältnisse angepaßt werden. So sollte man zumindest eine Stauchung bzw. Streckung der Grafik um den Faktor zwei ermöglichen, um z.B. 320200-(ST niedrig)-Spiele auch unter 640480 (TT Mittel) „ohne Lupe" spielen oder um Seitenverhältnisse z.B. 320480 (TT niedrig) ausgleichen und umgekehrt z.B. Spiele, welche ursprünglich eine Auflösung von 640480 benötigen, auch unter 320*200 spielen zu können.

Geschwindigkeitsprobleme

Es wäre sehr unökonomisch, Programme für ein Multitasking-System zu schreiben und dann die Rechenzeit in Leerschleifen zu „verbraten". Daher empfiehlt der „versierte GEM-Programmierer", die `EVENT_TIMER'-Funktion zu nutzen, in welcher man eine Wartezeit in Millisekunden angeben kann. In der Zwischenzeit bekommt dann ein anderes Programm Rechenzeit zugewiesen. Besser ist es natürlich auch hier (wie oben schon erwähnt), den Inhalt von Bildschirm bzw. Fenster häufiger zu erneuern und/oder für flüssigere Animationen etc. zu sorgen.

Klaus-Dieter Pollack

Literatur:

[1] Thomas Binder, Gamefix, Falcon030 wird ST(E)-kompatibel, ST-Computer 11/93
[2] Klaus-Dieter Pollack, Spiele selbst programmieren, erschienen zu CeBIT 1993 im Heim Verlag, ISBN 3928480-13-8
[3] Falcon030 Developer Documentation, ATARI Oktober 1992
[4] Jorgo Schimanski, Spieleprogrammierung in Assembler auf dem Amiga, erschienen 1991 im Heim Verlag, ISBN 3-928480-01-4
[5] RISC OS, Programmers Reference Manual Acorn Computer Limited 1989, ISBN 1-86250-060-3
[6] Archimedes (Sonderheft der 64er), erschienen im Markt und Technik Verlag
[7] Two Tribes, ein schachähnliches Action-/Strategiespiel, welches voraussichtlich irgendwann 1995 erhältlich sein wird und auf allen TOS-kompatiblen Rechnern laufen wird
[8] Jankowski,Rabich,Reschke, ATARI ST-STE-TT Profibuch, erschienen 1991 im Sybex Verlag, ISBN 3-88745888-5
[9] Martin Huber, Nova Treiber ab Vers. 2.0
[10] Sven und Wilfried Behne, NVDI ab Vers. 2.5
[11] Sven und Wilfried Behne, Enhancer ver. 1.0
[12] Steve Williams, 68030 Assembly Language Reference, erschienen 1989 im Adisson Wesley Verlag, ISBN 0201-08876-2
[13] MC 68040 User's Manual, Motorola 1989
[14] James F. Foley, van Dem, Feiner, Huges, Computer grafics: principles und practice, Adisson Wesley ISBN 0201-12110-7
[15] Gerd Respondek, Farblose Darstellung, CT 11/91
Nachdem Sprite und Hintergrund verknüpft wurden, kann man je nach Aufwand entweder den veränderten Teil oder den kompletten Fensterinhalt erneuern.



Aus: ST-Computer 01 / 1995, Seite 80

Links

Copyright-Bestimmungen: siehe Über diese Seite