Kapitel 6: Sprite Grafik

Einleitung

In den vorhergehenden Kapiteln haben wir gesehen, wie wir mit dem PRINT-Befehl den Bildschirm als Tabelle formatieren können und wie wir mit Hilfe des POKE-Befehls an beliebigen Stellen des Bildschirms Zeichen ausdrucken können.

Die Konstruktion von bewegten Darstellungen verursacht mit beiden Methoden einige Schwierigkeiten, da die Objekte aus vorgefertigten grafischen Symbolen zusammengesetzt werden müssen. Weiterhin bringt das Bewegen und Kontrollieren dieser Objekte einen großen Aufwand an Programmierbefehlen mit sich. Durch die begrenzte Zahl von Grafiksymbolen ist man schließlich in der Formgebung der Objekte stark eingeschränkt.

Durch die Verwendung von SPRITES fallen die meisten der aufgeführten Probleme weg. Ein SPRITE stellt ein frei programmiertes Objekt in hochauflösender Grafik dar, dem durch BASIC-Befehle jede beliebige Form gegeben werden kann. Durch einfache Angabe der Position kann das SPRITE auf dem Bildschirm verschoben werden. Die nötigen Berechnungen werden vom COMMODORE 64 automatisch intern erledigt. Aber die SPRITES haben noch mehr Vorteile.

Ihre Farbe kann geändert werden; der Zusammenstoß zweier SPRITES kann auf einfache Weise registriert werden; ein SPRITE kann sich vor oder hinter einem anderen vorbeibewegen und man kann mit einem Befehl seine Größe verändern.

All diesen Vorteilen stehen nur relativ geringe Schwierigkeiten beim Programmieren gegenüber. Zugegeben, Sie müssen noch einiges darüber lernen, wie der COMMODORE 64 arbeitet und wie er Zahlen intern verarbeitet. Aber schließlich ist das doch ganz interessant und auch gar nicht so schwierig; und wenn Sie alle Beispiele sorgfältig durcharbeiten, so werden Sie bald mit selbstkonstruierten SPRITES die verblüffendsten Kunststücke anstellen.

Die Konstruktion von Sprites

Die Sprites werden von einem speziellen Grafik-Baustein im COMMODORE 64, dem VIC (Video Interface Chip), unterstützt. Die Arbeit, die das Konstruieren der Sprites, das Kontrollieren ihrer Bewegungen und Positionen und die Farbgebung macht, wird zum größten Teil von diesem Chip übernommen.

Der Bereich, in dem die Sprites generiert werden, besteht aus 46 Speicherstellen von der Art, wie wir Sie schon bei der Behandlung des Bildschirm- und Farbspeichers kennengelernt haben. Diese Speicherstellen kann man sich in 8 Zellen, sogenannte Bits, unterteilt denken, die einzeln an- und ausgeschaltet werden können und auf diese Weise die Form der Sprites bestimmen. In welchem Zustand (an oder aus) die einzelnen Bits sind, wird durch die Zahl bestimmt, die in das betreffende Register geschrieben wird – doch davon später mehr.

Zusätzlich zu diesen speziellen Registern werden wir auch den Hauptspeicher des COMMODORE 64 benutzen, um Informationen über die Form der Sprites zu speichern. In 8 Speicherstellen (direkt hinter dem Bildschirmspeicher) werden Daten abgelegt, die den Computer darüber informieren, in welchem Speicherbereich die Daten für die Sprites gespeichert sind.

Wie sind die Sprites nun aufgebaut?

Wie Sie wissen, besteht der Bildschirm aus 25 Zeilen zu je 40 Zeichen. Jede der sich daraus ergebenden 1000 Bildschirmpositionen können Sie durch POKE mit einem Zeichen belegen. Diese Zeichen sind jedoch ihrerseits aus einer 8 x 8-Matrix zusammengesetzt. Beim Konstruieren eines Sprites können Sie nun jeden Punkt dieser Matrix einzeln ansprechen und erhalten dadurch eine Auflösung von 320 x 200 (horizontal x vertikal) Punkten für den gesamten Bildschirm. Ein Objekt, daß Sie auf diese Weise zusammensetzen, darf maximal 24 Punkte breit und 21 Punkte hoch sein.

Als Beispiel haben wir aus diesem 24 x 21-Punkte-Feld einen Ballon konstruiert.

Am besten entwerfen Sie das Objekt auf fein gerastertem Papier, auf dem Sie ein 24 Kästchen breites und 21 Kästchen hohes Feld markieren. Zeichnen Sie zuerst die Form so ein, wie Sie Ihnen vorschwebt, und füllen Sie dann die Felder aus, die von den von Ihnen gezogenen Linien geschnitten werden. Nachdem Sie auf diese Weise die Form des Sprites festgelegt haben, müssen Sie diese noch in Daten umwandeln, die der Computer verarbeiten kann. Schreiben Sie zu diesem Zweck (wie in der Abbildung auf Seite 70) an den oberen Rand des 24 x 21-Punkte-Feldes 3 mal hintereinander die Zahlenreihe 128, 64, 32, 16, 8, 4, 2, 1. Die Zeilen des Feldes numerieren Sie von 1 bis 21 durch.

Legen Sie sich nun für jede Zeile drei Wertetabellen an, wie sie auf der Seite 71 dargestellt sind. Tabelle 1 entspricht den ersten 8 Positionen einer Zeile in Ihrer Sprite-Darstellung, und die Tabellen 2 und 3 entsprechen den Positionen 9-16 bzw. 17-24. Über die einzelnen Felder Ihrer Wertetabellen schreiben Sie nun wieder die oben angeführte Zahlenreihe von 128 bis 1 (Sie haben sicher schon gemerkt, daß es sich hier um Potenzen von 2 handelt). Wir ordnen nun in unserer SpriteZeichnung jedem ausgefüllten Feld die Zahl 1 und jedem leeren Feld die Zahl 0 zu. Dann legen wir für jede Zeile 3 Tabellen an und schreiben die entsprechenden Werte in die einzelnen Felder.

Nehmen wir als Beispiel die Zeile 1 des oben dargestellten Sprites. Die ersten 8 Felder sind leer, d. h. unsere Tabelle 1 enthält lauter Nullen. Um daraus eine Zahl zu errechnen, die der Computer verarbeiten kann, müssen wir den Inhalt jedes Feldes der Tabelle mit dem Wert multiplizieren, der über diesem Feld steht und die Produkte addieren. Da alle Felder 0 enthalten, erhalten wir als erstes Datum (Singular von Daten) als Summe eine 0.

Die dritte Tabelle der ersten Reihe enthält wieder lauter Nullen, die Summe ist also auch 0. Die 1. Reihe unseres Sprites wird also durch die Zahlen 0, 127, 0 beschrieben. Um sie leicht in einem Programm verwerten zu können, schreiben wir sie als sogenannte DATA-Zeile:

Plain Text

Als weiteres Beispiel die Daten der zweiten Reihe unseres Sprites:

Für die Reihe zwei erhalten wir also die DATA-Zeile:

Plain Text

Um mit der beschriebenen Methode vertraut zu werden, sollten Sie nun die restlichen 19 DATA-Zeilen selbst berechnen…

Nun haben wir die DATA-Zeilen, aber wie kann man sie einsetzen?

Tippen Sie das folgende Programm ein und starten Sie es:
(Wenn Sie näheres über den DATA- und den dazugehörigen READBefehl wissen wollen, schauen Sie bitte in Kapitel 8 nach.)

Plain Text

Wenn Sie alles richtig eingetippt haben, fliegt ein Ballon ruhig über den Himmel.

Um das Programm zu verstehen, müssen Sie wissen, welche Speicherstellen (auch Register genannt) welche Funktionen kontrollieren. Sie können das der folgenden Tabelle entnehmen:

RegisterBeschreibung
0X-Koordinate von Sprite 0
1Y-Koordinate von Sprite 0
2-15Bedeutung paarweise wie 0 und 1 für die Sprites 1 bis 7
16Höchstes Bit - X-Koordinate
211 = Sprite erscheint; 0 = Sprite verschwindet
29Sprite wird in X-Richtung vergrößert
23Sprite wird in Y-Richtung vergrößert
39-46Farben der Sprites 0-7

Sie müssen außerdem wissen, in welchem 64er Block die Daten eines bestimmten Sprites abgespeichert sind. Diese Daten stehen in den 8 Registern direkt hinter dem Bildschirmspeicher.

Nun wollen wir Schritt für Schritt durchgehen, wie wir unsere Sprites auf den Bildschirm bringen und verschieben können.

  1. Poken Sie in den Speicherstelle 21 den “richtigen Wert” damit das von Ihnen gewählte Sprite auf dem Bildschirm erscheint.
  2. Lassen Sie den Sprite-Pointer (auch „Zeiger“) auf die Speicherstelle zeigen, von der ab die Daten des Sprites gelesen werden sollen.
  3. Schreiben Sie mit POKE die Daten in die Speicherstellen.
  4. Konstruieren Sie mit einer Schleife die X- und Y-Koordinaten für die Bewegung der Sprites.
  5. Sie können zusätzlich die Farben des Sprites oder seine Größe (in X- oder/und Y-Richtung) ändern. Die Parameter für die Größenänderung stehen in den Speicherstellen 29 und 23.

Einige Punkte des Programms könnten trotz der vorangegangenen Erläuterungen noch unklar sein.

Zeile 10:
V = 53248

Die erste Speicheradresse des Video-Chips wird unter V abgespeichert. Zu diesem Wert braucht nur noch die Nummer des Registers addiert zu werden, um die absolute Speicheradresse zu erreichen.

Zeile 11:
POKE V+21,4

Dieser Befehl läßt Sprite Nr. 2 auf dem Bildschirm erscheinen. Der Grund dafür ist, daß im Feld 2 der zugehörigen Tabelle eine 1 steht, wenn in das zugehörige Register eine 4 geschrieben wird.

Jedes Sprite ist im Register 21 repräsentiert, und der Wert 4 im Register entspricht dem Sprite 2. Sprite 3 würde einer 8 entsprechen, beide Sprites zusammen dem Registerinhalt 12 (= 8 + 4). Wenn Sie also die Sprites 2 und 3 „einschalten“ wollten, müßten Sie den Befehl POKE V + 21, 12 in Ihr Programm aufnehmen.

Zeile 12:
POKE 2042,13

Der Computer wird angewiesen, die Daten für Sprite Nr. 2 (entspricht Speicherstelle 2042) aus Block 13 des Speichers auszulesen. Ein Sprite „verbraucht“ den Inhalt von 63 Speicherstellen oder 63 Bytes. Der Inhalt einer Tabelle, wie wir sie zur Ermittlung der DATA-Zeilen zusammengestellt haben, entspricht einem Byte. Da wir 63 solcher Einheiten brauchen (in jeder der 21 Zeilen 3 Tabellen) müssen wir zur Konstruktion eines Sprites 63 Speicherstellen auslesen. Dies geschieht auf folgende Weise:

Plain Text

Durch diese Schleife werden 63 Bytes Daten in den 13. Block (1 Block = 64 Bytes) des Speichers eingelesen, der bei der Adresse 832 (= 13*64) beginnt.

Plain Text

Da die Register 4 und 5 die X- und Y-Koordinaten des Sprites 2 enthalten, bewirkt dieser Programmteil (natürlich nur zusammen mit einem NEXT), daß sich das Sprite 2 diagonal über den Bildschirm bewegt. Da der Koordinatenursprung in der linken oberen Ecke liegt, verläuft die Bewegung von links oben nach rechts unten. Der Computer liest die Daten schnell genug, um die Bewegung kontinuierlich erscheinen zu lassen. Näheres zu diesem Thema steht im Anhang 0.

Wenn sich mehrere Sprites über den Bildschirm bewegen sollen, wird jedem Objekt ein eigener Speicherbereich zugeordnet.

Die Zeile 70 bewirkt einen Rücksprung nach 30, wodurch der ganze Vorgang wiederholt wird. Der Rest des Programms besteht aus DATA-Zeilen, die die Information über die Form des Ballons enthalten.

Fügen Sie nun folgende Zeile zu dem Programm hinzu und starten Sie es erneut:

Plain Text

Der Ballon ist jetzt in X- und Y-Richtung doppelt so groß wie vorher. Der Grund dafür ist, daß die Zahl 4 (für Sprite Nr. 2) in die Register 23 und 29 geschrieben wurde. Es ist wichtig zu berücksichtigen, daß die linke obere Ecke des Sprites beim Vergrößerungsvorgang an ihrem Platz bleibt. Um unser Programm noch interessanter zu machen, fügen wir folgende Zeilen hinzu:

Plain Text

Ein weiteres Sprite (Nummer 3) ist auf dem Bildschirm erschienen, da wir in das Register 21 eine 12 gepoked haben. Die 12 schaltet die 2 und die 3 ein, da 12 = 000011002 ist.

Durch die Zeilen 45 und 55 wird Sprite 3 auf dem Bildschirm bewegt. Die Speicherstellen V+6 und V+7 enthalten die X- und Y-Koordinaten des Objekts.

Wenn Sie wollen, daß am Himmel noch ein bißchen mehr los ist, dann bringen Sie an Ihrem Programm die folgenden Ergänzungen an.

Plain Text

Durch den POKE-Befehl in Zeile 11 wurde ein weiteres Sprite auf den Bildschirm gebracht, da in die Position 4 des Registers 21 eine 1 geschrieben wurde. Dieser Position entspricht die Dezimalzahl 16, zusammen mit der 12, die schon im Register stand, ergibt das 28. Nun sind Sprite 2-4 eingeschaltet (000111002 = 28).

In Zeile 12 wird festgelegt, daß alle drei Sprites ihre Daten dem 13. Speicherblock entnehmen.

In Zeile 25 werden die Sprites 2 und 3 (daraus ergibt sich die Zahl 12) in X- (V+29) und Y-Richtung (V+23) auf das Doppelte vergrößert. Zeile 48 bewirkt, daß sich Sprite 3 in Richtung der X-Achse bewegt. Da in Zeile 58 für die Y-Koordinate der konstante Wert 100 vorgegeben wird, bewegt sich Sprite 3 nur horizontal.

Noch einige Bemerkungen zu Sprites

Mit Hilfe derselben Kodierungen (0-15) wie bei den Zeichenfarben (siehe Kapitel 5 oder Anhang G) können Sie die Sprites in 16 verschiedenen Farben darstellen.

Wenn Sie z. B. dem Sprite Nr. 1 die Farbe grün geben wollen, so müssen Sie folgenden Befehl eintippen: POKE V+40,13 (mit V = 53248).

Sie werden vielleicht beim Ausprobieren des Beispielprogramms bemerkt haben, daß die Sprites nie den rechten Bildschirmrand erreichen. Der Grund dafür ist, daß die Bildschirmbreite 320 Punkten entspricht, das X-Register jedoch nur Werte zwischen 0 und 255 enthalten kann. Wie kann man nun ein Objekt dazu bringen, sich über den gesamten Bildschirm zu bewegen?

Man benutzt zu diesem Zweck das Register Nr. 16, über dessen Funktion Sie der Tabelle im Anhang N entnehmen können, daß darin das „höchste Bit“, auch MSB = Most Significant Bit genannt, gespeichert ist. Das ist folgendermaßen zu verstehen: Ist das n-te Bit in diesem Register gesetzt, so befindet sich das n-te Sprite in einer Bildschirmposition, die einem X-Wert > 255 entspricht. Der aktuelle X-Wert ergibt sich dann, wenn man zu dem Wert, der im X-Register steht, 256 hinzuzählt.

Soll z. B. das Sprite Nr. 2 eine X-Position zwischen 256 und 320 einnehmen, so muß im Register Nr. 16 das zweite Bit gesetzt werden. Da 2↑2=4, müssen wir in dieses Register eine 4 poken:

Plain Text

Nun zählen wir den Inhalt des X-Registers, das zum Sprite Nr. 2 gehört (das ist Register Nr. 4) von 0 bis 63 hoch. Auf diese Weise erreichen Sie die restlichen X-Werte von 256-319.

Sie begreifen das ganze Konzept am besten, wenn Sie das folgende Programm analysieren, das eine leicht abgeänderte Version unseres bisherigen Sprite-Programms darstellt:

Plain Text

In Zeile 60 wird das MSB für Sprite Nr. 2 gesetzt. In Zeile 70 beginnt die Schleife, die das Sprite zum rechten Bildschirmrand wandern läßt. Die Zeile 100 ist ebenfalls wichtig, da hier das MSB wieder „abgeschaltet“ wird, so daß die Bewegung wieder am linken Bildrand starten kann.

Binärarithmetik

Eine detaillierte Einführung in die Methode, wie der Computer Zahlen verarbeitet, würde über den Rahmen dieser Einführung hinausgehen; im folgenden sollen jedoch einige Begriffe erläutert werden, die für den Umgang mit Zahlen in Binärdarstellung wichtig sind.

BITDies ist die kleinste Informationseinheit, die ein Computer verarbeitet. Ein BIT kann anschaulich als die Information darüber verstanden werden, ob ein Schalter auf „EIN“ (entspricht dem Wert 1) oder auf „AUS“ (entspricht dem Wert 0) steht. Man sagt auch, ein BIT ist gesetzt (= 1) oder nicht gesetzt (= 0).

Die nächstgrößere „Informationseinheit“ ist das BYTE.

BYTEEine Zusammenstellung von 8 BITS. Je nachdem, ob bestimmte BITS „gesetzt“ oder „nicht gesetzt“ sind, erhält man 256 verschiedene Kombinationen. Man kann also durch ein BYTE die Zahlen von 0 bis 255 darstellen. Sind in einem BYTE alle BITS nicht gesetzt, so kann es auf folgende Weise dargestellt werden:

Dieses BYTE hat den Wert 0. Sind alle BITS gesetzt, so erhält man:

Dieses BYTE hat den Wert 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 255.

REGISTEREin REGISTER entspricht einer speziellen Adresse im Computer; in ihr kann ein BYTE, d. h. maximal der Wert 255 abgespeichert werden. Durch Änderung der Registerinhalte können Computerfunktionen gesteuert werden. Im Zusammenhang mit den Sprites haben wir z. B. Register kennengelernt, deren Änderung dazu führt, daß Objekte auf dem Bildschirm erscheinen oder ihre Größe in x- bzw. y-Richtung ändern.

Die Umwandlung von der Binärdarstellung in die Dezimal-Darstellung

In der folgenden Tabelle sind die ersten 8 Zweierpotenzen als Binärzahlen dargestellt:

Wie bereits erwähnt, können Sie durch ein BYTE alle Zahlen von 0 bis 255 darstellen; da die Speicher unseres Computers ein BYTE enthalten, müssen deswegen die Zahlen, die wir hinein-poken auch zwischen 0 und 255 liegen. Wenn Sie wissen wollen, welcher Dezimalzahl eine bestimmte Binärzahl entspricht, so müssen Sie nur die Zweierpotenzen addieren, an deren Stelle im Bitmuster eine 1 steht. So kommt man zum Wert 255, wenn alle Bits gesetzt sind und erhält z. B. für die Binärzahl „00000011“ den Wert 3.

HILFSPROGRAMM: Umwandlung von Binärzahlen in Dezimalzahlen

Das folgende Programm wandelt von Ihnen eingegebene Binärzahlen in Dezimalzahlen um:

Plain Text

Die eingegebene Binärzahl wird als String A$ abgespeichert; dieser String wird von rechts nach links mit Hilfe der MID$-Funktion gelesen. Mit der VAL-Funktion wird ermittelt, wie groß der Wert des gelesenen Stringbestandteils ist (0 oder 1) und dieser Wert wird dann mit der entsprechenden Zweierpotenz multipliziert. Die Werte werden aufaddiert und Zeile 50 bewirkt, daß Binär- und Dezimalzahl am Ende des Programms zusammen ausgegeben werden.