Dieses Kapitel können Sie überspringen, falls Sie nur die Programmierprinzipien lernen wollen und zu den weiteren Teilen dieser Einführung streben. Falls Sie jedoch schon ganz eifrig mit QBASIC programmieren und bedauern, bisher keine Zeichnungen, Kurven, grafischen Spiele oder ähnliches erstellen zu können, dann bekommen Sie hier eine kleine Einführung in die Programmierung der "hochauflösenden" Grafik unter DOS.
Es wird Ihnen allerdings auch bei grundsätzlich gedämpften Interesse an Grafikprogrammierung empfohlen, mal hier reinzuschnuppern, da im Kapitel "Sprites" einige Beispielprogramme kommen, an denen Sie den "neuen" Programmierstil und die Möglichkeiten sehen können, die Ihnen eine modernere Programmiersprache als das C16-BASIC bietet.
Zur Orientierung in Bezug auf "Grafikprogrammierung auf PCs":
Genereller Hinweis: Sie können durch Alt-Enter das DOS-Fenster auf den s.g. Vollbildmodus schalten. In der Regel wird das der PC aber automatisch machen, wenn Sie unter Windows in deinem DOS-Fenster den Grafikmodus verwenden. Also nicht erschrecken. Mit Alt-Enter kommen Sie wieder zurück in den Fenster-Modus!
Wie beim C16 muss man den Bildschirm unter DOS für die Grafikprogrammierung erstmal vom Textmodus auf den Grafikmodus umschalten. Der Vorteil gegenüber dem C16 ist, dass der herkömmliche PRINT-Befehl auch in den Grafikmodi funktioniert.
Die verfügbaren Grafikmodi in QBASIC spiegeln die Urgeschichte der Grafikkarten wieder. Die beiden Uralt-Grafikkartenstandards CGA und EGA lassen wir hier beiseite. Der VGA-Standard von ca. 1990 hingegen hat noch eine kleine Bedeutung darin, dass auch heutige Linux- und Windows-XP-Systeme in einem VGA-Grafikmodus starten. Es seien hier nur die beiden wichtigsten Grafikmodi aufgezählt:
Zwischen Text- und Grafikmodi schaltet man mit dem SCREEN-Befehl um. Für ein grafikorientiertes Programm wird man dies nur einmal und am Anfang machen, da die Grafikmodi gegenüber den Textmodi bei der Darstellung von Text keine Nachteile bieten (sieht man von der geringeren Auflösung des 13h-Modus ab).
SCREEN 0 | Textmodus |
SCREEN 12 | 640x480x16-Modus |
SCREEN 13 | 320x200x256-Modus |
Kleines Schmunzeln am Rande: Schauen Sie mal in der Hilfe unter Screen-Anweisung-> Bildschirmmodi nach. Ganz unten steht ein kleines Beispielprogramm und der Hinweis "Nur für Systeme mit Farbgrafikadapter". "Grafikadapter" ist der alte Name für "Grafikkarte". Und der Hinweis soll heissen: Wenn Ihr PC nur eine Textmodus- Karte und keine Grafikkarte hat, funktioniert das Beispiel nicht...
Die Lösung des Problems, eine Figur gleiten zu lassen, heisst: Mehrere Bildschirmseiten. Das heisst, wir stellen zusätzlichen Speicherplatz bereit, um den Bildschirm zweimal abzuspeichern. Das nennen wir die beiden "Bildschirmseiten". (Wenn Sie jetzt über das Thema "Grafik und Speicherplatz" stolpern, dann schauen Sie nochmal unter C16: Hochauflösende Grafik im unteren Teil des Kapitels "Grafik und Speicher" nach.) Einstweilen begnügen wir uns mit "Stehgrafiken" oder "Hüpf-Figuren" und brauchen nur 1 Bildschirmseite.
Befehl | Syntax | Gebrauch/Bedeutung |
---|---|---|
CLS | CLS | "Clear Screen". Löscht den Bildschirm, egal in welchem Screen-Modus. |
PSET | Einfach: PSET (x,y) |
Zeichnet einen Bildschirmpunkt an der Koordinate x,y. Beispielprogramm:
'Sternenhimmel SCREEN 13 FOR i = 1 TO 1000 x = RND * 320 y = RND * 200 PSET (x, y) NEXT i Ausführliche Syntax: PSET STEP (x,y),Farbe Das Schlüsselwort "STEP" kann weggelassen werden. Wenn es dabei ist, werden x und y als Schrittweite relativ zur letzten gezeichneten PSET- Position gewertet. PSET (50,50) PSET STEP (0,20) PSET STEP (-20,0) PSET STEP (0,-20) PSET STEP (20,0) zeichnet also ein Viereck von der Ecke mit den Absolutkoordinaten (50,50) aus. |
LINE | LINE (x1,y1)-(x2,y2) | Zeichnet eine Linie vom Punkt (x1,y1) bis zum Punkt (x2,y2). Funktioniert wie DRAW 1,X1,Y1 TO X2,Y2 beim C16. |
Rechtecke und gemusterte Linien mit LINE zeichnen |
LINE (x1,y1)-(x2,y2),farbe,B LINE (x1,y1)-(x2,y2),farbe,BF LINE (x1,y1)-(x2,y2),farbe,B,musterwert
|
LINE (x1,y1)-(x2,y2),farbe,B zeichnet Rechteck von der linken oberen Ecke
(x1,y1) bis zur unteren Ecke (x2,y2). LINE (x1,y1)-(x2,y2),farbe,BF Rechteck ist ausgefüllt. Kleines Beispielprogramm
'Modern Art in Vierecken SCREEN 12 xscreensize = 640 yscreensize = 480 FOR i = 1 TO 100 farbe = RND * 16 x1 = (RND - .1) * xscreensize y1 = (RND - .1) * yscreensize xsize = RND * xscreensize / 2 ysize = RND * yscreensize / 2 x2 = x1 + xsize y2 = y1 + ysize LINE (x1, y1)-(x2, y2), farbe, B,&hFF00 'Verzoegerungsschleife. Wert fuer 500 MHz-PIII. 'Bei schnellerem PC anpassen. FOR j = 1 TO 10000: NEXT j 'Auskommentiert: Nach jedem Viereck auf Tastendruck warten. 'WHILE INKEY$ = l>"": WEND NEXT iWie Sie sehen, füllt sich der Bildschirm mit gestrichelten farbigen Vierecken. Die Strichelungen kommt durch die Angabe des letzten Werts zustande. Die Linie wird Abschnitte mit jeweils 16 Pixel eingeteilt und die 16-Bit-Zahl sagt, welche Pixel gesetzt sein sollen: Ist ein Bit auf 1, wird das Pixel gesetzt. Im Beispiel sind also immer die ersten 8 Pixel gesetzt und die zweiten 8 Pixel nicht. Eine Angabe von &HF0F0 würde die Strichlänge auf 4 Pixel verkürzen, &HCCCC auf 2 Pixel und &HAAAA auf ein Pixel. (Gelt, das ist jetzt ein bisserl Denksport???) |
CIRCLE (Kreise, Ellipsen) | Einfach: CIRCLE (x,y),rad,farbe | Einfache Syntax: Zeichnet eine Kreis mit rad Radius um den Punkt x,y. Zum Zeichnen von Ellipsen und Kreissegmenten gibt es eine ähnlich längliche Syntax wie beim C16. Das kann man aber gut in der Online-Hilfe nachschlagen. |
Farben, Farbpalette | PALETTE USING - Befehl |
Wahrscheinlich haben Ihnen die 16, bzw. 256 Farben, die Sie mit dem
Color-Befehl (siehe Kap. 26)
hervorrufen können, noch nicht so ganz gefallen. Die Vorbelegung der
256 Farben ist eigentlich zu nichts zu gebrauchen.
Die 16, bzw. 256 auf dem Bildschirm gleichzeitig verfügbaren Farben nennt man auch die Farbregister. (In der QBASIC-Hilfe heissen sie reichlich unverständlich "Attribute"). Welche Farbe ein Farbregister anzeigt, kann man mit dem PALETTE-Befehl definieren. Und zwar aus 64 x 64 x 64 = 256K möglichen Farben. Die Auswahlfarben sind zusammengemischt aus Rot-, Grün- und Blau-Komponenten. Man nennt das das RGB-Farbmodell, das an vielen Orten in der Computergrafik seine Verwendung findet, auch bei den modernen Grafikkarten und Bildschirmmodi. Auch hier werden die Farben durch ihre RGB-Werte beschrieben, allerdings können hier alle Farben in der Regel gleichzeitig auf dem Bildschirm dargestellt werden, die Arbeit mit Farbregistern ist hier nicht mehr notwendig. Alle Farbregister zusammen heissen auch die "Palette" (daher der QBASIC-Befehl). Jede der 16, bzw. 256 Farbregister der Palette wird also durch 3 64-Bit-Zahlen beschrieben. Jeder Farbwert (R, G oder B) wird allerdings in einem extra Byte abgelegt, so dass wir es bei der Definition der Farbe mit einer 3-Byte-Zahl zu tun haben. Es wäre natürlich nun einfach, wenn der PALETTE-Befehl von QBASIC einfach PALETTE,Farbregister,R-Wert, G-Wert,B-Wert heissen würde. Das wäre viel zu einfach. Microsoft hat es an dieser Stelle richtig schön kompliziert gemacht, so dass Sie bei den ersten Versuchen so gut wie nie mehr als eine Fehlermeldung auf den Bildschirm bekommen werden.. Am Besten, Sie versuchen das folgende Programm, das Ihnen eine Reihe von Blauwerten auf den Bildschirm malt: ' Blautoene DIM farb(256) AS LONG SCREEN 12 PALETTE 0, 0 f(0) = 0 FOR i = 1 TO 15 farb(i) = 65536 * i * 4 NEXT i PALETTE USING farb(0) GOSUB zeichne END zeichne: CLS FOR i = 0 TO 15 LINE (1, 1 + i * 20)-(320, 19 + i * 20), i, BF NEXT i RETURN Wenn alles klappt, bekommen Sie 15 dunkel- bis hellblaue Querbalken. Was passiert hier? Nun, als erstes kommt die Deklaration eines Arrays. Die Ergänzung "as long" kennen wir noch nicht. Sie ist aber wichtig. Systematisch werden wir uns mit solchen Ergänzungen später noch beschäftigen, einstweilen soll uns genügen, dass dies ein speziell "formatiertes" Array ist. Ohne diese Formatierung hagelt es nur Fehlermeldungen. In farb() werden die Farbwerte für die 16 Farbregister gespeichert. Der Palette Using-Befehl weiter unten übernimmt dann die Werte dieses Arrays in die Farbregister. Allerdings stellt sich die Frage, warum farb() dann 256 Zellen enthält und nicht nur 16. Wieder eine böse Falle. Aus welchen technischen Gründen auch immer, der PALETTE-Befehl braucht für die VGA-Modi mindestens 128 Zellen. Da SCREEN 13 ohnehin 256 Zellen braucht, sollte das Paletten-Array am Besten immer 256 Zellen enthalten. Der erste Palette-Befehl 0,0 sichert nur ab, dass Farbregister 0 weiterhin "Schwarz" ist, da dieses ja für Rand und Hintergrund verwendet wird. Dann geht's mit der Palettendefinitionsschleife los. Wie gesagt: Jeder Farbwert ein Byte, das Ganze eine 3-Byte-Zahl. In Hex ist das eine Zahl zwischen 0 und FFFFFFh. Wollen wir z.B. Knallrot, dann setzen wir den Rotwert auf FFh, die Grün- und Blauwerte auf null. Der Rotwert ist das niedrigste Byte, also ist das Ganze 0000FFh. Entsprechend ist Knallgrün 00FF00h und Knallblau FF0000h. FFFF00h wäre Türkis und 00FFFFh Gelb. FF00FFh ist Magenta, FFFFFFh Weiss. 777777h ist Grau, da hier alle Farbwerte gleich stark sind, aber unterhalb des Maximums. Genauso ist 770000h eben ein dunkles Rot. Leider können wir aufgrund der 16-Bit-Restriktion der Hex-Verarbeitung von QBASIC das Ganze nicht einfach in Hexzahlen angeben. Also geben wir es in Form von 030201h = 256*256*3 + 256*2 + 1 an. Soweit so schön. Im Programm steht aber 65536*3 + 256*2 +1. Das ist doch das Gleiche, oder? Wieder Falle. Intern erzeugt 256*256 bei QBASIC einen Überlauf! Um QBASIC also dazu zu bewegen, einen 3-Byte-Wert zu erzeugen, muss man es ihm gleich einen 3-Byte-Wert explizit vor die Nase setzen und das ist 65536 = 10000h. Und damit klappt's dann. Puh! Weil's so schön war, im SCREEN13 noch ein Beispielprogrämmchen: DIM farb(256) AS LONG SCREEN 13 PALETTE 0, 0 farb(0) = 0 FOR i = 1 TO 63 'Magenta-Toene farb(i) = 65536 * i + i NEXT i FOR i = 64 TO 127 'Tuerkis-Toene farb(i) = 65536 * (i - 64) + 256 * (i - 64) NEXT i FOR i = 128 TO 191 'Grau-Toene farb(i) = 65536 * (i - 128) + 256 * (i - 128) + i - 128 NEXT i PALETTE USING farb(0) GOSUB zeichne END zeichne: CLS FOR i = 0 TO 191 LINE (1, i)-(320, i), i, BF NEXT i RETURN |
Das Stichwort "Sprites" war der Stromstoss für den Spieleprogrammierer vor 15 Jahren. Es handelt sich um kleine bewegte Bildchen, die über den Bildschirm gleiten oder hüpfen. Das beste Beispiel für ein "Sprite" ist der Mauscursor. Wahrscheinlich haben Sie sich noch keine Gedanken darüber gemacht, wie Sie einen Mauscursor programmieren würden, aber wenn Sie das Problem näher anschauen, wird es Ihnen nicht mehr so ganz einfach vorkommen:
Wie wir gesehen haben, müsste dieser ganze Vorgang so schnell passieren, dass er kürzer dauert, als ein Bruchteil der Verweildauer des Zeigers an der neuen Position. Ansonsten kann man den Ab- und Aufbau des Zeigers mit dem Auge mitverfolgen und das Bild "hoppelt". Oder man verwendet eben einen Extra-Speicherbereich, der sehr schnell in das aktuelle Bild ein- und ausgeblendet werden kann.
In den Zeiten des C16 konnte dieses schnelle Ein- und Ausblenden eigentlich nur mit Zusatzhardware realisiert werden, den s.g. Spritegeneratoren. Der beliebteste Homecomputer der damaligen Zeit, der C64, zeichnete sich durch seine leistungsfähigen schon eingebauten Spritegeneratoren aus.
In QBASIC auf einem heutigen PC sind "C64-like" Sprites überhaupt kein Problem. Das eingangs dieses Teils bei der Installation von QBASIC empfohlene Spiel "Mooncrap" illustriert das eindrucksvoll. Aber auch ist Sprite-Programmierung kein ganz einfaches Kapitel.
Am Besten wäre es natürlich, man könnte Sprites in einem Malprogramm zeichnen und dann in QBASIC verwenden. Das geht auch. Aber wie man gängige Pixelgrafikdateiformate aus Programmiersprachen heraus beherrscht, das gehört noch nicht zu unserem Repertoire. Also werden wir uns einstweilen darauf beschränken, die Pixel per Programm zu speichern oder zu zeichnen.
Möglichkeiten:
Die erste Vorgehensweise wurde in "kap115.htm">C16-Hochauflösende Grafik im Bereich "Beispielprogramm zu SSHAPE/GSHAPE" schon demonstriert. Die zweite Möglichkeit ist auch nicht schwer. Nehmen wir ein kleines Bild mit 8 x 10 Pixeln. Jedes Pixel hat einen Farbwert zwischen 0 und 255. Jeder Farbwert ist die Nummer des Paletteneintrags. Tipp: Um Ihr erstes Sprite mittels DATA zu entwerfen, schreiben Sie sich zuerst ein kleines Progrämmchen, das Ihnen übersichtlich die Farbe der voreingestellten Paletteneinträge zeigt, falls Sie sich nicht jedes Mal die PALETTE selbst vordefinieren wollen.
Sie müssen die nun folgenden Programme nicht abtippen. Sie können auch einfach die Programmtexte in Ihrem Browser markieren und in einer Textdatei abspeichern, die Sie dann mit QBASIC wieder öffnen. |
Meine Version:
Nun kanns los gehen. Meine Zeichnung sieht so aus:
'---------------------------------------- 'Beispielprogramm zum Generieren von Sprites 'mit DATA-Werten '---------------------------------------- GOTO Main 'Zeigt Screen13-Defaultpalette an ZeigePalette: SCREEN 13 FOR i = 0 TO 100 COLOR i PRINT i MOD 10; IF i MOD 10 = 0 THEN PRINT " "; i NEXT i END Spritedaten: DATA 0,0,0,0,0,0,0,0 DATA 0,0,0,1,1,0,0,0 DATA 0,0,1,1,1,1,0,0 DATA 0,1,2,1,1,2,1,0 DATA 0,1,1,2,1,1,1,0 DATA 0,1,1,2,1,1,1,0 DATA 0,1,4,1,1,4,1,0 DATA 0,0,1,4,4,1,0,0 DATA 0,0,0,1,1,0,0,0 DATA 0,0,0,0,0,0,0,0 xsize = 8 ysize = 10 RETURN Zeichnesprite: RESTORE Spritedaten FOR iy = y TO y + ysize - 1 FOR ix = x TO x + xsize - 1 READ farbe PSET (ix, iy), farbe 'PRINT ix, iy, farbe NEXT ix NEXT iy WHILE (INKEY$ = ""): WEND RETURN Main: SCREEN 13 x = 100 y = 100 GOSUB Spritedaten GOSUB Zeichnesprite END
Ich habe im Unterprogramm "ZeichneSprite" eine Zeile dringelassen, die auskommentiert ist, die ich aber zum Debuggen verwendet habe. So. Und wie sieht Ihr Sprite aus?
Das Programm kann man leicht erweitern, um das Sprite herumzubewegen. Prinzipiell. wir berücksichtigen dabei allerdings nicht, was unter dem Sprite eventuell angezeigt war und nun von ihm überschrieben wird. Wir schreiben noch eine zweite Routine namens "LoescheSprite" und rufen beide dann wechselnd auf.
Hier mein Sprite, wie es als Spielball zwischen den Bildschirmrändern hin- und herfliegt:
'---------------------------------------- 'Beispielprogramm zum einfachen Bewegen von 'Sprites durch Neuzeichnen '---------------------------------------- GOTO Main 'Zeigt Screen13-Defaultpalette an ZeigePalette: SCREEN 13 FOR i = 0 TO 100 COLOR i PRINT i MOD 10; IF i MOD 10 = 0 THEN PRINT " "; i NEXT i END Spritedaten: DATA 0,0,0,0,0,0,0,0 DATA 0,0,0,1,1,0,0,0 DATA 0,0,1,1,1,1,0,0 DATA 0,1,2,1,1,2,1,0 DATA 0,1,1,2,1,1,1,0 DATA 0,1,1,2,1,1,1,0 DATA 0,1,4,1,1,4,1,0 DATA 0,0,1,4,4,1,0,0 DATA 0,0,0,1,1,0,0,0 DATA 0,0,0,0,0,0,0,0 xsize = 8 ysize = 10 RETURN Zeichnesprite: RESTORE Spritedaten FOR iy = y TO y + ysize - 1 FOR ix = x TO x + xsize - 1 READ farbe PSET (ix, iy), farbe 'PRINT ix, iy, farbe NEXT ix NEXT iy RETURN LoescheSprite: LINE (x, y)-(x + xsize - 1, y + ysize - 1), 0, BF RETURN Warte: FOR j = 1 TO 200: z = SIN(1!): NEXT j RETURN Main: SCREEN 13 x = 1 y = 1 xdir = 1 ydir = 1 GOSUB Spritedaten WHILE (INKEY$ = "") GOSUB Zeichnesprite GOSUB Warte GOSUB LoescheSprite x = x + xdir y = y + ydir IF (x > 320 OR x < 0) THEN xdir = -xdir IF (y > 200 OR y < 0) THEN ydir = -ydir WEND END
Wenn Sie nichts sehen sollten, es zu langsam oder zu schnell geht, dann müssen Sie die Zahl "200" in der Routine "Warte" anders einstellen.
Sie sehen, dass das Hauptprogramm "Main" ganz einfach geblieben ist - dank Unterprogramme.
Natürlich ist das noch kein gutes Spriteprogramm. Das Sprite löscht auf seiner Spur alles weg und es bewegt sich zwar recht schnell, aber etwas ruckelig. Als Nächstes lernen wir, wie das Sprite sich den Hintergrund merkt. Dazu gibt es eine einfache Anweisung:
GET | Syntax: GET (x1,y1)-(x2,y2),buf buf ist ein Array der Grösse xsize*ysize, das ganz am Anfang des Programms mit DIM deklariert werden muss. GET speichert nun den Bildschirmbereich (x1,y1)-(x2,y2) in buf. |
PUT | Syntax: PUT (x,y),buf,flag Malt den Bildausschnitt von buf an die Stelle (x,y). "flag" ist ein Schlüsselwort, das den Malmodus bezeichnet. Die möglichen Modi sind: AND, OR, PSET, PRESET oder XOR. Weitere Informationen finden Sie dazu in der Online-Hilfe von Qbasic. |
Für unseren Zweck ist bei PUT nur der Modus PSET relevant, der einfach das neue Bild über den alten Hintergrund drübermalt und sich nicht drum schert, was da schon steht. Die anderen Modi verknüpfen in irgendeiner Form die Farben des Hintergrunds mit den Farben von buf.
Übung 1: Bauen Sie eine Routine "BewegeSprite" mit den Befehlen Get, Put und der schon bekannten Routinen "ZeichneSprite". Die Routine "LoescheSprite" werden Sie nicht mehr brauchen. Die Routine "BewegeSprite" soll das Sprite von (x1,y1) nach (x2,y2) bewegen. folgendes ist zu tun:
Viel Spass!
Meine Lösung lautet:
'------------------------------------------------- 'Beispielprogramm zum einfachen Bewegen von 'Sprites ueber einen Hintergrund durch Neuzeichnen '------------------------------------------------- DIM BHG(9 * 11 + 1) GOTO Main 'Zeigt Screen13-Defaultpalette an ZeigePalette: SCREEN 13 FOR i = 0 TO 100 COLOR i PRINT i MOD 10; IF i MOD 10 = 0 THEN PRINT " "; i NEXT i END Spritedaten: DATA 0,0,0,0,0,0,0,0 DATA 0,0,0,1,1,0,0,0 DATA 0,0,1,1,1,1,0,0 DATA 0,1,2,1,1,2,1,0 DATA 0,1,1,2,1,1,1,0 DATA 0,1,1,2,1,1,1,0 DATA 0,1,4,1,1,4,1,0 DATA 0,0,1,4,4,1,0,0 DATA 0,0,0,1,1,0,0,0 DATA 0,0,0,0,0,0,0,0 xsize = 8 ysize = 10 RETURN ZeichneSprite: RESTORE Spritedaten FOR iy = y TO y + ysize - 1 FOR ix = x TO x + xsize - 1 READ farbe IF farbe = 1 THEN farbe = 53 IF farbe = 2 THEN farbe = 46 PSET (ix, iy), farbe 'PRINT ix, iy, farbe NEXT ix NEXT iy RETURN LoescheSprite: LINE (x, y)-(x + xsize - 1, y + ysize - 1), 0, BF RETURN Warte: FOR j = 1 TO 200: z = SIN(1!): NEXT j RETURN ZeichneHintergrund: FOR ix = 0 TO 320 STEP 20 LINE (ix, 1)-(ix, 200), 6 NEXT ix RETURN SpeichereBHG: ' BHG = BildHinterGrund rspeich = 0 IF (x > 0 AND y > 0 AND x + xsize - 1 < 320 AND y + ysize - 1 < 200) THEN GET (x, y)-(x + xsize - 1, y + ysize - 1), BHG rspeich = 1 END IF BHGinit = 1'Zeigt, dass BHG sinnvolle Werte enthaelt RETURN MaleBHG: IF (x > 0 AND y > 0 AND x + xsize - 1 < 320 AND y + ysize - 1 < 200) THEN PUT (x, y), BHG, PSET END IF RETURN BewegeSprite: '...von (x1,y1) nach (x2,y2) x = x1: y = y1 IF (BHGinit = 1) THEN GOSUB MaleBHG 'LOCATE 20, 20: PRINT 1; 'WHILE (INKEY$ = al>""): WEND x = x2: y = y2 GOSUB SpeichereBHG 'LOCATE 20, 20: PRINT 2; 'WHILE (INKEY$ = al>""): WEND IF rspeich = 1 THEN GOSUB ZeichneSprite 'LOCATE 20, 20: PRINT 3; 'WHILE (INKEY$ = al>""): WEND RETURN Main: SCREEN 13 BHGinit = 0 GOSUB ZeichneHintergrund x0 = 1 y0 = 1 xdir = 1 ydir = 1 x1 = x0: y1 = y0 GOSUB Spritedaten WHILE (INKEY$ = "") x2 = x0 y2 = y0 GOSUB BewegeSprite x1 = x0: y1 = y0 'Zwischenspeichern der alten Koordinaten --> BHG! GOSUB Warte IF (x0 + xdir > 320 - xsize OR x0 + xdir < 0) THEN xdir = -xdir IF (y0 + ydir > 200 - ysize OR y0 + ydir < 0) THEN ydir = -ydir x0 = x0 + xdir y0 = y0 + ydir WEND END
Ich habe hier wieder ein paar auskommentierte Debug-Zeilen dringelassen. "Main" habe ich etwas schöner gestaltet, indem nun die Grenzenprüfung die Grösse des Sprites berücksichtigt. Beachten Sie, dass "SpeichereBHG" einen Rückgabewert rspeich liefert, der informiert, ob der Hintergrund überhaupt abgespeichert werden konnte. Ist dies nicht der Fall, dann darf auch nichts Neues gezeichnet werden. Das sichert ab, dass nicht plötzlich die Ordnung von "Speichern" und "Zeichnen" durcheinander kommt.
Übung 2: Modifizieren Sie das Programm von oben (oder ihr eigenes!) so, dass das schwarze Viereck um das eigentliche Sprite herum verschwindet. Das ist ganz einfach und erfordert nur eine Halbzeile!
Übung 3: Etwas schwieriger, aber nicht so schwierig, wie es scheint: Schreiben Sie ein Programm, das mehrere identische Sprites gleichzeitig über den Bildschirm fliegen lässt!
Übung 4: Modifizieren Sie das Programm so, dass Sie die Sprites nicht immer neu mit PSET auf den Bildschirm pixeln, sondern ebenfalls mit PUT übertragen. Gewinnt das Programm an Geschwindigkeit?
Übung 5: Fügen Sie nun ein zweites, andersartiges Sprite ein, dessen Bewegung Sie mit den Cursortasten steuern können. Nennen wir dieses Sprite "Janosch". Und die anderen Sprites sind Fliegen. Geben Sie einen Beep aus, (Anweisung BEEP), wenn eine Fliege Janosch trifft. Hurra! Wir haben ein richtiges Action Game!
Wenn Sie sich mehr für Grafikprogrammierung mit QBASIC, insbesondere Sprites, interessieren: Es gibt eine Menge guter Literatur zum Thema auf qbasic.de
.