Pascal-Tutorial (Vorwort, Installation, Kapitel 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)

Grafik, Schlusswort

12.1. Text- und Grafikmodus

Wichtig: Dieses Kapitel (12.1 und 12.2) beschreibt Grafikfunktionen und deren Einsatz unter Turbo Pascal. Wenn Sie Free Pascal verwenden, können Sie dieses Kapitel überspringen. Diese Art der Grafikdarstellung hat heute ohnehin keine Bedeutung mehr. Dieses Kapitel ist der Vollständigkeit halber noch enthalten.

Dieser Abschnitt soll Ihnen einen Einstieg in die grafischen Möglichkeiten mit Turbo Pascal liefern. Wenn Sie einen anderen Compiler als Turbo Pascal verwenden, könnte das Folgende evtl. nicht oder nicht richtig funktionieren. Da die Thematik Grafik sehr umfangreich ist, kann sie hier prinzipiell nur angeschnitten werden. Alles andere würde den Rahmen dieses Tutorials sprengen. Das Thema wird so behandelt, dass es Ihnen problemlos möglich sein müsste, weitere Informationen aus der Hilfe-Datei dazu einzuholen.

Wie Sie wissen, haben wir bisher nur im Textmodus gearbeitet. In diesem ist es möglich, 80 Zeichen auf 25 Zeilen anzuzeigen. Übrigens ist es auch möglich, einen anderen Textmodus auszuwählen. Das geschieht mit der Prozedur Textmodus(Modus). Je nach Modus können bis zu 80 Zeichen auf 25 Zeilen in Farbe oder monochrom dargestellt werden.

Allerdings ist die Grafikdarstellung, die wir jetzt gerne hätten, im Textmodus nicht möglich. Damit richtige Grafikdarstellung (im Textmodus kann man höchstens Grafiken darstellen, die aus ASCII-Zeichen bestehen; sog. ASCII-Art) möglich ist, muss in den Grafikmodus umgeschalten werden. Im Grafikmodus ist - im Gegensatz zum Textmodus - das Setzen einzelner Pixel möglich.

Der Bildschirminhalt benötigt allerdings auch recht viel Speicher. Um 1 Pixel abzuspeichern, wird in einer monochromen Darstellung 1 Bit benötigt (2 Werte: hell/dunkel). 4 Farben lassen sich mit 2 Bits darstellen, 16 Farben mit 4 Bits. Für 256 Farben benötigt man pro Pixel 1 Byte (8 Bits).

In welchen Modus umgeschalten wird, darum müssen wir uns nicht kümmern. Standarmäßig wird automatisch der günstigste Modus ausgewählt. Zur Initalisierung des Grafikmodus benötigen wir 2 Prozeduren: DetectGraph und InitGraph. DetectGraph ermittelt den günstigsten Grafikmodus sowie den benötigten Grafiktreiber. Grafiktreiber unter Turbo Pascal haben die Dateiendung .bgi (= Borland Graphics Interface).

DetectGraph (Grafiktreiber, Grafikmodus);

Anstelle von Grafiktreiber und Grafikmodus müssen Variablen (!) vom Typ Integer angegeben werden! Zahlen anzugeben ist hier nicht erlaubt. Wie Sie es wahrscheinlich erraten haben, erfolgt hier die Parameterübergabe by reference. Zum Umschalten in den Grafikmodus steht InitGraph bereit:

InitGraph (Grafiktreiber, Grafikmodus, Treiberverzeichnis);

Anstelle von Grafiktreiber und Grafikmodus müssen auch hier Variablen angegeben werden (Übergabe by reference). Der letzte Parameter kann direkt angegeben werden (call by value). Damit InitGraph, DetectGraph und einige andere verwenden werden können, muss die Unit Graph inkludiert werden. Wieder in den Textmodus zurück gelangen Sie mit der Prozedur CloseGraph:

CloseGraph;

Das nächste Beispiel schaltet einfach in den Grafikmodus um und anschließend wieder in den Textmodus zurück. Ausgegeben wird also nichts. Später werden wir uns noch um die Ausgabe kümmern. Ansonsten hätte ja das hier keinen Sinn.

PROGRAM Grafikmodus_umschalten;
USES Crt, Graph;
 
VAR Treiber, Modus: Integer;
 
BEGIN
  DetectGraph (Treiber, Modus);  (* stellt den besten Grafikmodus fest und setzt Treiber und Modus *)
 
  InitGraph (Treiber, Modus, 'C:\Turbo\BGI');  (* in Grafikmodus umschalten; passen Sie das Verzeichnis entsprechend an *)
 
  CloseGraph;  (* wieder in den Textmodus zurueck *)
END.

Die größten Kompabilitätsprobleme macht die Angabe des Grafiktreiber-Verzeichnisses. Wenn Sie Turbo Pascal installiert haben, dann ändern Sie einfach die Pfadangabe so ab, dass sie mit Ihrer TP-Installation übereinstimmt, und das Beispiel funktioniert problemlos.

12.2. Zeichnen und Ausgabe im Grafikmodus

Nachdem der Grafikmodus initialisiert wurde, kann die Bildschirmausgabe erfolgen.

Wir beginnen mit etwas Einfachem und zwar mit dem Zeichnen einer Linie. Die Linie benötigt einen Start- und einen Endpunkt. Vom Startpunkt zum Endpunkt wird die Linie gezogen. Sowohl der Start-, als auch der Endpunkt setzen sich aus X- und Y-Koordinate zusammen. Der Punkt X: 0, Y: 0 befindet sich auf dem Bildschirm links oben (in der linken oberen Ecke).

Line (X-Startpunkt, Y-Startpunkt, X-Endpunkt, Y-Endpunkt);

Zum Beispiel:

Line (100, 200, 500, 400);

In diesem Fall wird eine Linie vom Startpunkt X: 100, Y: 200 zum Zielpunkt X: 500, Y: 400 gezeichnet. Es besteht auch die Möglichkeit, die Farbe der Pixeln zu bestimmen. So können Sie Linien, Kreise, Rechtecke usw. in der gewünschten Farbe ausgeben. Hierfür steht die Prozedur SetColor zur Verfügung. Eine Farbe ist so lange gültig, bis Sie etwas anderes setzen.

SetColor (Farbe);

Anstelle von Farbe kann ein vordefinierter Farbname oder die Nummer der Farbe angegeben werden. Es dürfte ausreichend sein, sich vorerst auf die gängigsten Farbnamen wie Red, Green, Blue, Yellow, Black, White usw. zu beschränken.

SetColor (4);

SetColor (Red);

Als nächstes soll ein Rechteck mit der Prozedur Rectangle gezeichnet werden. Ähnlich wie bei der Linie wird lediglich ein Start- und ein Endpunkt verlangt:

Rectangle (X-Startpunkt, Y-Startpunkt, X-Zielpunkt, Y-Zielpunkt);

Rectangle (100, 200, 500, 400);

Hier wurden dieselben Parameter verwendet, die auch im obigen Line-Beispiel verwendet wurden. Vergleichen Sie die Bildschirmausgaben!

Zum Zeichnen von Kreisen steht die Prozedur Circle bereit. Als Parameter werden der Startpunkt sowie der Radius verlangt. Vom Startpunkt ausgehend wird im angegebenen Radius (Angabe in Pixeln) ein Kreis gezeichnet.

Circle (X-Koordinate, Y-Koordinate, Radius);

Ein Beispiel wäre:

Circle (500, 600, 80);    (* X: 500, Y: 600, Radius: 80px *)

Auch das Setzen einzelner Pixel ist möglich:

PutPixel (X-Koordinate, Y-Koordinate, Farbe);

Zum Beispiel:

PutPixel (100, 50, 4);   (* X: 100, Y: 50, Farbnummer: 4 (rot) *)

Ähnlich wie Sie es mit Write und WriteLn gewöhnt sind, Texte im Textmodus auszugeben, funktioniert das auch im Grafikmodus. Hierfür stehen die beiden Prozeduren OutText und OutTextXY zur Verfügung:

OutText (Text);

OutTextXY (X-Koordinate, Y-Koordinate, Text);

Den Bildschirm löschen können Sie mit ClearDevice:

ClearDevice;   (* wie ClrScr im Textmodus *)

Sie haben nicht nur die Möglichkeit, einfache Kreise und Rechtecke zu zeichnen, sondern auch, diese zu füllen. FloodFill ist hierfür die benötigte Prozedur. FloodFill kann nur zum Füllen geschlossener Flächen eingesetzt werden. Die ersten zwei Parameter sind die Koordinaten eines Punktes (!) innerhalb der zu füllenden Fläche. Damit nicht der gesamte Bildschirm mit Farbe gefüllt wird, muss eine Grenzfarbe angegeben werden. Es wird alles von dem angegebenen Punkt aus mit der aktuellen Farbe (können Sie mit SetColor festlegen) gefüllt, bis die Grenzfarbe erreicht ist.

FloodFill (X-Koordinate, Y-Koordinate, Grenzfarbe);

Abschließend drei Anwendungsbeispiele:

PROGRAM Grafikdemo;
USES Graph, Crt;    (* Wichtig: Graph inkludieren! *)
 
VAR treiber, modus: Integer;
 
BEGIN
  DetectGraph (treiber, modus);
  InitGraph (treiber, modus, 'C:\Turbo\BGI\ ');
 
  OutText ('Zeichne Linie...');
  Delay (1000);   (* 1 Sekunde warten *)
  Line (40, 40, 300, 150);
 
  Delay (2000);
  ClearDevice;  (* Bildschirm loeschen *)
  OutText ('Zeichne Rechteck...');
  Delay (1000);
  Rectangle (40, 40, 300, 150);
 
  Delay (2000);
  ClearDevice;
  OutText ('Zeichne Kreis...');
  Delay (1000);
  Circle (200, 300, 40);
 
  Delay (2000);
  ClearDevice;
  CloseGraph;  (* zurueck in den Textmodus *)
  WriteLn ('Es wurde wieder in den Textmodus umgeschaltet!');
  ReadKey;
END.

Das Beispiel bedarf wahrscheinlich keiner weiteren Erläuterung. Beim nächsten Beispiel kommt PutPixel zum Einsatz. Es werden zufällige Punkte mit einer zufälligen Farbe positioniert, und das geschieht 10.000-mal.

PROGRAM Punkte;
USES Graph, Crt;
 
CONST Wdh = 10000;   (* Anzahl an Wiederholungen *)
VAR treiber, i, modus: Integer;
 
BEGIN
  DetectGraph (treiber, modus);
  InitGraph (treiber, modus, 'C:\Turbo\BGI\ ');
  Randomize;
 
  FOR i := 1 TO Wdh DO
  BEGIN
    PutPixel (Random(640),Random(480),Random(16));
    Delay(10);  (* 10 ms warten *)
  END;
 
  ReadKey;
  CloseGraph;
END.

Um die Koordinaten sowie eine entsprechende Farbe zu erzeugen, wird Random eingesetzt. Die Wartezeit von 10 ms sorgt dafür, dass nicht allzu viele Punkte mit denselben Koordinaten positioniert werden (hier merken Sie den Pseudo-Zufallszahlengenerator).

Das letzte Beispiel zeigt, wie FloodFill sowie SetColor eingesetzt werden:

PROGRAM Fuellen;
USES Graph, Crt;
 
VAR treiber, modus: Integer;
 
BEGIN
  DetectGraph (treiber, modus);
  InitGraph (treiber, modus, 'C:\Turbo\BGI\ ');
 
  SetColor (Blue);  (* aktuelle Farbe auf Blau setzen *)
  Circle (100,100,50);  (* einen blauen Kreis zeichnen *)
  FloodFill (70, 70, Blue);  (* die blauen Randlinien des Kreises dienen als Begrenzungsflaeche *)
 
  ReadKey;
  CloseGraph;
END.

12.3. Schlusswort, Fragen und Antworten

Zu jedem Vorwort gehört auch ein Schlusswort. Finde ich zumindest. Jedenfalls vermisse ich Schlussworte oft, wenn ich mir am Ende vieler Bücher denke: Und jetzt?

Wie lange brauche ich, bis ich (richtig) gut programmieren kann?

Diese Frage stellen vorwiegend Anfänger. Die Antwort kann eigentlich nur Jahre lauten. Wie viele, hängt von den eigenen Zielen und der Definition von gut ab. Was ist gut, mit welchem Ergebnis gebe ich mich zufrieden? Ziele: Was will ich - vorrangig - programmieren? Kleine Skripte für Websites, Shell-Skripte, Anwendungsprogramme, Hardware-Treiber, umfangreiche Spiele, das eigene Betriebssystem? Je schwieriger die Aufgabe, je mehr Kenntnisse nötig sind, umso länger werden Sie brauchen.

Aber auch lebenslang ist eine gute Antwort (Grüße an die Schüler, die nichts mehr von lebenslangem Lernen hören können! ;-) ). Ähnlich gelagert wäre wohl die Frage: Wie lange benötige ich, bis ich ein guter Chirurg bin?. Mit der Chirurgie gemeinsam hat die Programmierung übrigens, dass beide Tätigkeiten nicht durch Theorie allein erlernt werden können. Stattdessen hilft nur üben, anwenden und ausprobieren. Aber einen Vorteil haben Sie als Programmierer: Programmieren können Sie auch autodidaktisch - aus Büchern, Tutorials und anderen Quellen - lernen. Das für den Lerneffekt wichtige Feedback erhalten Sie vom Compiler.

Wie kann ich meine Pascal-Kenntnisse erweitern?

Am besten mit einem weiterführenden Buch zu Pascal! Es gibt glücklicherweise immer noch eine gute Auswahl an deutschsprachigen Pascal-Büchern. Die bisherigen Kenntnisse werden Ihnen beim Verstehen der Bücher helfen.

Daneben gibt es noch einige andere Tutorials zu Pascal. In der Link-Rubrik (Pascal) finden Sie Links zu Pascal-Tutorials und verwandten Pascal-Themen. Vermissen Sie eine gute Seite in der Link-Rubrik, können Sie sie dort eintragen (vorschlagen).

Bücher bieten aber oft mehr Tiefgang und detailliertere Informationen als im Internet zu finden sind. Bücher sind auch meist nicht so oberflächlich wie Tutorials wie dieses hier. :-)

Mein Programm funktioniert nicht! Was tun bei Fragen? Wo finde ich Hilfe?

Eines vorweg: Bitte schreiben Sie mir keine E-Mail! Ich leiste keinen E-Mail-Support. Ich habe leider nicht die Zeit, auf jede programmier-bezogene (inhaltliche) Frage persönlich eingehen, noch Fehler in fremden Programmen zu suchen.

Was tun wenn's nicht läuft? Finden Sie den Fehler selbst! Fehlersuchen gehört zum Programmieren dazu! Nur durch Programmieren lernt man Programmieren. Stundenlang einen Fehler suchen gehört dabei dazu (weiß ich aus eigener Erfahrung).

Es läuft immer noch nicht? Weitersuchen, ggf. nochmal die Grundlagen lesen und lernen. Auch eine kurze Pause wirkt oft wahre Wunder, um Fehler in der eigenen Denkweise zu erkennen ("So kann's ja gar nicht funktionieren ..."). Fremde Hilfe in Anspruch zu nehmen, sollte immer nur den letzten Ausweg darstellen.

Natürlich können Sie Fragen stellen, auch erhöht reger Austausch unter Programmierern den Lerneffekt. Mehr dazu im Forum. Nutzen Sie bitte, bevor Sie einen neuen Beitrag schreiben, die Suchfunktion. Fragen werden i.d.R. mehrfach gestellt, und Ihre Frage lässt sich so vielleicht bereits beantworten.

Ich freue mich natürlich über Feedback zu diesem Tutorial. Zum Beispiel: Was ist gut erklärt, was lässt sich noch verbessern? Gibt es Fehler? Schreiben Sie aber bitte alle inhaltlichen Fragen zur Programmierung, wenn Sie sie nicht selbst lösen konnten, immer ins Forum!


Weiterhin viel Spaß beim Programmieren wünscht der Autor dieses Tutorials,
Andreas Hammer

Vorheriges Kapitel