![]() |
![]() |
....wenn wir schon beim Spielen sind. Die meisten Spiele haben sehr ausgefeilte Bildschirm (Screen)-Ausgaben. Denken wir an solche Spieleklassiker wie "Tetris", "PacMan" oder "Space Invaders": Da fliegen Gegenstände, Monster, Raumschiffe über den Bildschirm. Das ist mit unserem PRINT, selbst wenn wir beliebige Zeichenketten ausgeben können, nicht so einfach zu machen. Ausserdem erfolgt die Steuerung des Bildschirmgeschehens nicht mit zeilenorientierten Eingaben, die alle mit einem ENTER abzuschliessen sind. Sondern man drückt eine Taste und sofort passiert etwas. Kann das der C16 aus? Klar kann er das.
Um interessante Bildschirm (Screen-)-Ausgaben zu gestalten, müssen wir den Bildschirm zuerst komplett löschen können. Das machen wir mit dem Befehl SCNCLR, was für "Screen Clear" steht:
10 I=0 20 PRINT "HALLO! "; 30 LET I=I+1 40 IF I<30 THEN GOTO 20 50 PRINT "DRUECKEN SIE ENTER, DANN " 60 PRINT "WIRD DER BILDSCHIRM GELOESCHT"; 70 INPUT A$ 80 SCNCLR
Der Screen des C16 ist organisiert wir eine Tabelle: Er hat 40 Spalten, in die jeweils ein Buchstabe passt. Und 25 Zeilen:
00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | |
00 | ||||||||||||||||||||||||||||||||||||||||
01 | ||||||||||||||||||||||||||||||||||||||||
02 | ||||||||||||||||||||||||||||||||||||||||
03 | ||||||||||||||||||||||||||||||||||||||||
04 | ||||||||||||||||||||||||||||||||||||||||
05 | ||||||||||||||||||||||||||||||||||||||||
06 | D | A | S | I | S | T | E | I | N | T | E | X | T | |||||||||||||||||||||||||||
07 | ||||||||||||||||||||||||||||||||||||||||
08 | ||||||||||||||||||||||||||||||||||||||||
09 | ||||||||||||||||||||||||||||||||||||||||
10 | ||||||||||||||||||||||||||||||||||||||||
11 | ||||||||||||||||||||||||||||||||||||||||
12 | ||||||||||||||||||||||||||||||||||||||||
13 | ||||||||||||||||||||||||||||||||||||||||
14 | ||||||||||||||||||||||||||||||||||||||||
15 | ||||||||||||||||||||||||||||||||||||||||
16 | ||||||||||||||||||||||||||||||||||||||||
17 | ||||||||||||||||||||||||||||||||||||||||
18 | ||||||||||||||||||||||||||||||||||||||||
19 | ||||||||||||||||||||||||||||||||||||||||
20 | ||||||||||||||||||||||||||||||||||||||||
21 | ||||||||||||||||||||||||||||||||||||||||
22 | ||||||||||||||||||||||||||||||||||||||||
23 | ||||||||||||||||||||||||||||||||||||||||
24 |
Normalerweise, wenn wir nichts weiter angeben, dann setzt der C16 von sich aus die Bildschirmposition des nächsten PRINT's. Aber wir haben schon zwei Methoden kennengelernt, diese Position zu beeinflussen: Ein Semikolon hinter der PRINT-Zeile schliesst die nächste Ausgabe hinter der ersten an, ein Komma vesetzt sie in derselben Zeile an die nächste Tabulator-Position.
Darüber hinaus gibt es noch die TAB-Funktion, die es erlaubt, die Spalte direkt anzugeben. (Eigentlich handelt es sich dabei auch nicht um eine Funktion, denn sie gibt nicht, wie eine Sinus-Funktion, einen Wert zurück. Es ist einfach eine Schlüsselwort innerhalb einer PRINT-Zeile.) PRINT TAB(20);"Hallo!" gibt das Wort "Hallo!" in Spalte 20 aus.
Das hilft ein bisschen, aber eine Zeilensteuerung erreichen wir dadurch auch noch nicht. Die bekommen wir nur mit Hilfe eines anderen Ausgabebefehls, des Befehls CHAR. Hier können wir beides angeben, Zeile und Spalte: CHAR ,10,10,"Hallo!" setzt den Text "Hallo!" in Zeile 10 und Spalte 10. Das können Sie zuerst auch ohne Programm, einfach auf der Kommandozeile versuchen. Vergessen Sie das führende Komma nicht!
CHAR ist allerdings mit PRINT nicht ganz identisch, da es keine Rechnungen, sondern nur Strings ausgeben kann. Aber das stört uns nicht weiters: Mit Hilfe von STR$() können wir auch das lösen. Übrigens können wir CHAR auch dazu benutzen, nur die Bildschirmposition für das nächste PRINT zu setzen:
10 SCNCLR 20 CHAR ,0,9,"" 30 PRINT TAB(10);1+1:
schreibt die PRINT-Ausgabe in Zeile 10 und Spalte 10.
Mithilfe von CHAR können Sie nun einerseits professionelle Bildschirmeingabemasken erstellen, wie Sie es z.B. von Kassencomputern kennen. Und andererseits können Sie CHAR für Spiele benutzen, um Objekte zu zeichnen oder sogar zu bewegen. Programmieren wir an unserer Mondlandung weiter. Wir wollen die Fähre nun zeichnen. Dazu nehmen wir die Sonderzeichen der ASCII-Tabelle aus dem vorigen Kapitel zuhilfe. Wie wär's mit der hier?
Als nächstes schreiben wir einen Programmteil, der die Fähre an eine bestimmte Position auf den Bildschirm schreibt. Die Spalte stehe im Speicher X, die Zeile im Speicher Y und dieses Zeichen beschreibe das oberste linke Zeichen der Fähre. Dann lautete dieser Programmteil (die Zeilennummern sind beliebig):
100 CHAR ,X,Y,CHR$(117);CHR$(101);CHR$(105) 110 CHAR ,X,Y+1,CHR$(106);CHR$(102);CHR$(110) 120 CHAR ,X,Y+2,CHR$(110);" ";CHR$(109)
Um die Fähre zu bewegen, müssen wir die Fähre an der alten Position löschen, dann die Position verändern und dann die Fähre neu zeichnen. Das folgende Programm lässt die Fähre über den ganzen Bildschirm huschen:
10 X=RND(1)*37 20 Y=RND(1)*23 70 CHAR ,X,Y,"_ _ _" 80 CHAR ,X,Y+1,"_ _ _" 90 CHAR ,X,Y+2,"_ _ _" 100 CHAR ,X,Y,CHR$(117)+CHR$(101)+CHR$(105) 110 CHAR ,X,Y+1,CHR$(106)+CHR$(102)+CHR$(110) 120 CHAR ,X,Y+2,CHR$(110)+" "+CHR$(109) 130 LET I=0 140 LET I=I+1 150 IF I<10 THEN GOTO 140 160 GOTO 10
Die "_" stehen wieder für Leerzeichen. Wie Sie sehen, müssen wir bei CHAR aufpassen: Wir können die Sonderzeichen nicht mittels eines ; eineinanderhängen (";" gibt's nur beim PRINT-Befehl), sondern müssen aus den drei Sonderzeichen mittels "+" einen String zusammenkleben. Eine weitere Besonderheit ist der Teil 130 bis 150. Man kann ihn auch weglassen, aber dann huscht die Fähre so schnell, dass man sie gar nicht sieht. 130 bis 150 tut eigentlich gar nichts, es zählt sinnlos die Variable I hoch, braucht so Zeit und lässt damit die Fähre länger an ihrer Position auf dem Bildschirm stehen.
Wir brauchen natürlich auch noch eine Mondoberfläche. Das kann einfachheitshalber ein gerader Strich sein. Oder - etwas intuitiver - eine gezackte Linie, die die Unebenheiten und Krater darstellt.
Den Rest des Programms haben wir ja schon. Wir müssen nun nur noch die Variable "S0" in Bildschirmkoordinaten Y, also Werte zwischen 1 und 24 übersetzen. Wobei wir aufpassen müssen: Ein kleines S0 entspricht einem grossen Y. So könnte es gehen:
10 LET Y=24-S0/250*24
Wenn S0 auf dem Anfangswert 200 steht, dann ist S0/250 etwa 0,8 und Y=24-0,8*24 dürfte ziemlich klein, also bei 2 bis 4 so liegen. D.h., die Fähre schwebt ganz oben. Wenn S0=0 ist, dann ist Y=24-0=24 und die Fähre ist ganz unten.
Vielleicht war Ihnen das im zweiten Kapitel dieses Tutorials mit dem vielen Rechnen ein bisschen lästig und Sie dachten: "Meine Güte, ich will doch programmieren lernen und keine Mathestunde". Nun ja, jetzt sehen Sie: Wir beschäftigen uns mit einem Computerspiel und müssen noch viel mehr rechnen! Aber so ist das mit dem Computer. Auch wenn der Benutzer "aussen" nur sich bewegende Raumfähren sieht - im Programm selbst ist ziemlich viel Mathematik und es muss ziemlich viel gerechnet werden. "Computed" eben.