![]() |
![]() |
Grundsätzlich ist, es wurde schon erwähnt, Freebasic mit dem Grundsatz maximaler Kompatibilität zu QBASIC programmiert worden. An sich sollten viele QBASIC-Programme ohne Veränderung unter Freebasic kompilierbar sein und laufen - wenn auch nicht immer optimal. Im Gegensatz zu qbasic ist Freebasic eine junge Sprache, die sich zwar als erstes Ziel gesetzt hat, QBasic/Quickbasic 1:1 auf moderne Betriebssysteme zu übertragen, zweitens aber auch die Sprache weiterzuentwickeln. Beide Ziele stehen teilweise im Konflikt zueinander. Daher gibt es inzwischen mehrere "Sprachschalter", die man in FBIDE unter Settings->Freebasic in Compilercommand zwischen <$fbc$> und <$file$> eintragen kann oder auf der Konsole einfach hinter das fbc-Kommando hängt.
Eine Übersicht über die "Dialekte" erhält man hier.
Für den Anfang empfehle ich -lang fblite. Andere Dialekte haben das Problem, dass sie mit den Libraries (z.B. fbgfx) nicht mehr kompatibel sind. Bei fblite ist die QB-Kompatibilität noch sehr gross, aber die Libs funktionieren auch.
In diesem Kapitel soll auf einige Unterschiede zwischen Freebasic eingegangen werden, allerdings nur solche, die nicht die Sprachstruktur (SUB, FUNCTIONs, Deklarationen) betreffen, da darauf im nächsten Kapitel separat behandelt werden. Die Erwähnung der Unterschiede findet relativ knapp statt und ist auch nicht vollständig. Die Unterschiede sind auf www.freebasic.de in der Befehlsreferenz genau und vollständig dokumentiert, die Hinweise hier dienen nur der Umschiffung der ersten Klippen.
Beliebte Schleifen a la
WHILE INKEY$="":WEND
funktionieren zwar noch, sollten aber unter Freebasic der Vergangenheit angehören. Tastaturereignisse werden mit dem Befehl SLEEP abgefangen:
SLEEP a$=INKEY$ IF a$=".... ...
Warum? Nun, schauen Sie mal auf Ihre Rechenauslastung (gestarteter Taskmanager) im Systray: Mit der inkey$-Variante schicken Sie Ihren Rechner mit voller CPU-Leistung in eine Amokschleife, die dem Rechner die Power wegnimmt - für nichts und wieder nichts. "Sleep" tut genau das, was sein Name besagt: Es legt das Programm schlafen. Solange, bis ein Tastaturereignis beim Betriebssystem eintrudelt und dieses das Programm wieder aufweckt.
Es gibt noch zwei andere Befehle zu diesem Thema. GETKEY wartet auf einen Tastendruck, liefert den ASCII-Code zurück und löscht den Tastaturpuffer. Tasten abzufragen, deren Code mit zwei Bytes zurückgegeben wird wie z.B. Cursortasten, das geht allerdings nicht. Dann gibt es noch MULTIKEY, das gezielt auf eine bestimmte Taste oder Tastenkombionation lauscht (nicht wartet!), aber danach den Tastaturpuffer nicht löscht. Achtung: Damit dieses funktioniert, müssen Sie am Anfang die Zeile "#include "fbgfx.bi" stellen.
#INCLUDE "fbgfx.bi" WHILE NOT MULTIKEY(SC_Q) CLS IF MULTIKEY(SC_UP) THEN LOCATE 10,10 ? "Sie haben die Pfeil-nach-oben-Taste gedrückt!" END IF WEND
Das Besondere an MULTIKEY ist, dass es alle Keyboard-Tasten entgegennimmt, also auch die Windows-Tasten usw. Das Nette ist, dass man noch ein "#include "fbgfx.bi"" voranstellen und dann die dort notierten Konstanten zur Abfrage verwenden kann, da MULTIKEY nur ein Byte für jede Taste benötigt:
#INCLUDE "fbgfx.bi" DIM ans AS STRING WHILE 1=1 ans="" IF MULTIKEY(SC_ESCAPE) THEN ans="Sie haben die ESCAPE-Taste gedrückt!" IF MULTIKEY(SC_BACKSPACE) THEN ans="Sie haben die Backspace-Taste gedrückt!" IF MULTIKEY(SC_CONTROL) THEN ans="Sie haben eine Strg-Taste gedrückt!" IF (MULTIKEY(SC_BACKSPACE) AND MULTIKEY(SC_END)) THEN ans="Sie haben Backspace und END gleichzeitig gedrückt!" IF (MULTIKEY(SC_BACKSPACE) AND MULTIKEY(SC_END) AND MULTIKEY(SC_RWIN)) THEN ans="Der NEUE Klammergriff" IF (MULTIKEY(SC_LSHIFT)) THEN END LOCATE 10,10 PRINT SPACE$(60) LOCATE 10,10 PRINT ans; SLEEP WEND
Dieses Progrämmchen beenden Sie übrigens mit Druck auf die linke Shift-Taste. Alle Tastencodes finden Sie in der Datei fbgfx.bi im Unterverzeichnis "inc" des FBC-Programmverzeichnsisses.
Auf die geheimnisvollen #include-Zeilen kommen wir noch später zu sprechen.
In QBASIC kam man noch in praktisch jeder Lage mit der Tastenkombination Ctrl-Pause (Strg-Pause) aus dem Programm. Das ist bei Freebasic u.U. nicht mehr der Fall. Sie müssen hier schon eher selbst Sorge tragen, dass Sie auch immer unterbrechen können. Wenden Sie z.B. den SLEEP-Befehl an, fragen aber keine Taste danach gezielt ab, werden Sie in vielen Fällen Pech haben und auch Ctrl-Pause rettet Sie nicht. Daher empfiehlt es sich immer, in die inneren Schleifen lang laufender Programmteile ein
IF MULTIKEY(SC_ESCAPE) THEN END
einzubauen. (Wahlweise eine andere Taste/Tastenkombination)
Die Kompatibilität von Feebasic mit Qbasic erstreckt sich bis in den Grafikbereich. SCREEN, PSET, LINE, CIRCLE usw. funktionieren wie unter QBASIC gewohnt. Wenn auch die technische Umsetzung "hinter den Kulissen" ganz anders abläuft als unter der DOS-Emulation von command.com oder cmd.exe. Bei letzterer muss zwangsläufig in dem Moment, in dem ein DOS-Grafikmodus angesprochen wird, die Bildschirmorganisation auf DOS umgestellt werden - was natürlich nur im Vollbildmodus funktioniert. Freebasic hingegen simuliert die alten Funktionen von QBASIC ja nur, setzt sie aber mittels der Betriebssystem-API um. Diese Übersetzung von "Alter QBASIC-Befehl" in "Betriebssystem-API" heisst bei Freebasic "Gfx-Library". Für Grafik unter Windows gibt's zwei API's: DirectX für schnelle Grafik. Das schöne ist, dass die Gfx-Lib DirectX benutzt, wenn es installiert ist (und das ist praktisch immer der Fall). "Toll!" ruft man da aus: Das ist ja dann maximale Geschwindigkeit! Hundertmal schneller noch als in QBASIC! Compilierter Code! 32-Bit-Code! Und DirectX!" Nein, stimmt so leider nicht. Noch nicht. Der Kran z.B. läuft unter Freebasic 0.13 ziemlich genauso schnell wie unter QBASIC. Wenn man die gleiche Auflösung benutzt. In XGA-Auflösung läuft er sogar lansgamer, auf meiner 3 GHz-Kiste hier mit ca. 8 bis 10 Schritten pro Sekunde, auf der 1 GHz-Kiste meiner Frau mit ca. 1 Schritt pro Sekunde. Schade. Aber nichts, was sich nicht ändern liesse:
SCREEN 1 bis 13 funktionieren ganz normal, was die Benutzung einer Bildschirmseite anbelangt. Hier eine kleine Demo, die durch alle DOS-Grafimodi führt. Man beachte: Screen 3 bis 6 und Scren 10 stehen (wie auch schon in QBASIC unter Windows) nicht zur Verfügung.
Wenn Ihnen die 320x200-Modi im Fenster zu klein sind, können Sie das Ganze auch im Vollbild-Modus haben. Dazu modifizieren Sie die SCREEN-Anweisung in SUB main1():
SCREEN iscreen,,,1
Sie werden bemerken, dass die Screenmodus-Wechsel nun um einiges langsamer von statten gehen. Das hängt mit DirectX-Besonderheiten zusammen.
Etwas ärgerlich war, dass in QBASIC die Modi mit 2 oder mehr Bildschirmseiten so rar waren. Besonders die attraktiven Modi 12 und 13 hatten nur eine Seite. In Freebasic können Sie jedem der klassischen Bildschirmmodi mehrere Seiten mitgeben:
SCREEN 12,,2
verschafft auch Screen 12 zwei Bildschirmseiten
Sie werden am Beispielprogramm bemerkt haben, dass nun auch noch ein anderer Befehl Einzug gehalten hat,SCREENSET, der das Umschalten der sichtbaren, bzw. aktiven Seiten unternimmt. Dies ist eine Inkompatibilität zum alten QBASIC, in der das noch SCREEN erledigt, die man von Hand beseitigen muss, wenn man alte grafische QBASIC-Programme (wie z.B. den 3D-Kran) nach Freebasic überträgt.
In Freebasic sind Sie bei 256 Farben nicht auf popelige 320x200 Pixel beschränkt. Es gibt eine weitere Anzahl von SCREEN-Modi, z.Z. Modus 14 bis 21, die eine Auflösung bis 1280x1024 ermöglichen.
Vorsicht! Stellen Sie vor dem Ausprobieren des jeweiligen Screenmodus' sicher, dass dieser auch auf Ihrem Gerät zur Verfügung steht. Für Grafikkarten mit Baujahr nach 1998 dürften kein Modus ein Problem sein, aber für kleinere Flachbildschirme und für Notebooks kann es mit Screen 21 oder auch mit Screen 20 Probleme geben, was dann zum Absturz des kompletten Betriebssystems führen kann! |
Hier können Sie die Bildschirmseiten und die neuen Modi testen.
Schliesslich: Sollten Ihnen 256 Farben nicht ausreichen, dann können Sie ab Screen 14 auch eine 16-Bit- oder 24-Bit-Farbtiefe wählen. Hierzu geben Sie als zweites Argument hinter der Modusnummer die Farbtiefe in Bit an. Wenn Sie sich nicht mehr errinnern sollten, wie das mit Bits und Farben funktioniert hat, dann können Sie hier nachschauen.
SCREEN 19,16,2
schaltet einen Grafikbildschirm mit 800 x 600 Punkten, rund 65.000 Farben und 2 Bildschirmseiten ein. (Speicherbedarf 800x600x2x2=1920000 Bytes = ca. 2 MB).
Wie komme ich bei diesen Modi an meine Farben? Das sind ja dann riesige Paletten! Sind es nicht. Die Farbauswahl ist bei HiColor (16 Bit) und TrueColor (24 Bit) glücklicherweise sogar einfacher als bei weniger Farben. Freebasic stellt die Funktion RGB(r,g,b) bereit. r, g und b sind jeweils Integerzahlen für den Rot-, Grün- und Blauanteil. r,g und b haben den Bereich 0..255 (sowohl in HiColor als auch in TrueColor). Die Funktion liefert eine Integerzahl zurück, die direkt den Grafikbefehlen wie LINE, PSET usw. als Farbe übergeben wird. LINE (x1,y1)-(x2,y2),RGB(255,0,0) zeichnet z.B. eine rote Linie, LINE (x1,y1)-(x2,y2),RGB(0,0,255) eine blaue.
Bis jetzt startete immer zuerst ein Konsolenfenster. Bei Ausführen des SCREEN-Befehls öffnete sich ein neues Fenster; das alte Konsolenfenster aber blieb stehen. Kann man dieses Konsolenfenster abschalten? Kann man: Man kompiliert kurzerhand mit der Option "-s gui".
Weil wir schon beim Grafikfenster sind: Mit der Anweisung WINDOWTITLE "mein Titel" kann man dem Grafikfenster noch seinen eigenen Titel geben. Mittels
s1="Oma's Screentest, Screen: "+str$(iscreen) WINDOWTITLE s1
kann man z.B. die Anzeige der Screennummer in die Titelzeile des Fensters verlagern.
Arbeitet man mit weniger als 16 Bit Farbtiefe, muss man noch Paletten verwalten. Wie das geht, haben wir in Teil II, Kapitel Grafik und einfache Sprites in QBASIC besprochen. Freebasic ist allerdings 32-Bit und enthält die ganzen Fallen nicht, die innerhalb des 16-Bit-QBASIC der Umgang mit 3-Byte-Grössen mit sich brachte. Dies funktioniert also in Freebasic:
'Erzeugt eine Grauwertpalette DIM farb(256) AS INTEGER FOR i=0 TO 255 farb(i)=(i MOD 64)*256*256+(i MOD 64)*256+(i MOD 64) 'Bemerke: Reihenfolge BGR. Jeder Kanal hat 6 Bits, also 64 Stufen NEXT i PALETTE USING farb(0)
Zusätzlich kann man allerdings die RGB-Werte auch direkt angeben, ohne ein Array benutzen und ohne die Farbwerte multiplizieren zu müssen. In diesem Fall gibt man jeden Kanal in 8 Bits an, also in Werten zwischen 0 und 255.
'Erzeugt auch eine Grauwertpalette FOR i=0 TO 255 PALETTE i,i,i,i NEXT i
Hier können Sie die neuen Screenmodi mit vielen Farben testen.
Neu ist ja, dass wir es mit einem Compiler zu tun haben, wir also am Ende eine fertige exe-Datei haben, die wir auch von der Kommandozeile aus starten können. Vorteil eines solchen Kommandozeilenstarts ist, dass wir dem Programm auf der Kommandozeile Argumente mitgeben können, die unser Freebasic-Programm dann verarbeiten kann - eine attraktive Alternative zur interaktiven Eingabe. Hierzu ein Beispiel.
Nehmen wir an, wir haben ein Programm geschrieben, das aus einem beliebigen Text eine Sorte Zeichen entfernt, z.B. alle Kommas oder alle Punkte oder alle kleinen a's. Wir nennen es rmchar (für "remove char"). unser Kompilat heisst rmchar.exe. Die Frage ist nun: Wir bekommt das Programm mit, welche Datei es bearbeiten soll und welches Zeichen es rausmachen soll?
Aber wie kommen wir an die Argumente auf der Kommandozeile ran? Dazu gibt es die Funktion COMMAND(n). n ist eine Nummer und gibt die Nummer des Arguments an. Die Zählung beginnt bei eins, n=0 geht auch, aber das ist dann der Name der exe-Datei selbst ("rmchar.exe"). In unserem Beispiel müsste es also so heissen:
DIM filen AS STRING DIM c AS STRING filen=COMMAND(1) c=COMMAND(2) IF (LEN(filen)=0 OR LEN(c)=0) THEN ? "Syntax: rmcharSYSTEM END IF OPEN filen FOR INPUT AS #1 ... "
Wir sehen: Fehlt das entprechende Argument, kommt aus Command() ein Leerstring zurück. Dies abzutesten ist hier noch weitaus wichtiger als im Fall von Funktionsargumenten, da der Gelegenheitsuser, der unser kleines Programm benutzen wird, weitaus weniger Ahnung von dessen Syntax hat als der Programmierer (im ZWeifelsfall wir selbst...)
Im nächsten Kapitel gehts weiter mit bewegten Grafik-Objekten...