grafika pascal
Grafika w Graph
Moduł Graph pozwala na tworzenie naprawdę prostej (czyli niezbyt efektownej) grafiki. Jego pierwotna DOSowa wersja używała karty graficznej bezpośrednio (na poziomie przerwań BIOSu), korzystając przy tym z własnych "sterowników". W tamtych zamierzchłych czasach obsługiwał niemal wszystkie karty graficzne, jednak do dziś używany jest tylko jeden z tamtych standartów: VGA.
Za sprawą aparatów fotograficznych w telefonach każdy chyba wie, jaką rozdzielczością charakteryuzje się tryb VGA; dla tych co nie wiedzą dodam, że 640×480 w 16 kolorach (4-bitowa głębia). K'woli ścisłości: istnieje również tryb VGA 256-kolorowy (głębia 8-bitowa), o rozdzielczości 320×200. Nie jest on jednak dostępny z poziomu modułu Graph.
Uruchomienie trybu graficznego
Samo zadeklarowanie użycia Graph nie oznacza jeszcze, że od razu uruchomiony zostanie tryb graficzny. Musimy to zrobić ręcznie, tak, jak w poniższym programie:
Pobierz plik programu
Program UruchamiamyGraph;
Uses
Graph, Crt;
Const
Tekst : String = 'Wcisnij dowolny klawisz...';
Procedure UruchomGrafike;
Var
Karta, Tryb, Blad : Integer;
Begin
Karta:=VGA; { Ustawiamy kartę jaką posiadamy }
Tryb:=2; { Ustawiamy żądany tryb graficzny }
initGraph(Karta, Tryb, ''); { Inicjujemy grafikę }
Blad:=graphResult;
If (Blad<>grOK) Then
Begin
WriteLn('Wystąpił błąd podczas uruchamiania trybu graficznego: ',
graphErrorMsg(Blad));
Halt(1);
End;
End;
Procedure WylaczGrafike;
Begin
closeGraph;
End;
Begin
UruchomGrafike;
SetColor(White);
OutTextXY((GetMaxX-TextWidth(Tekst)) Div 2,
(GetMaxY-TextHeight(Tekst)) Div 2,
Tekst);
Repeat Until KeyPressed;
WylaczGrafike;
End.
Okazuje się, że to jeszcze nie wszystko. Jeśli kompilujesz program za pomocą TP to jedynym sensownym standardem kart graficznych będzie VGA. Tryb możesz ustawić na Detect
. Spowoduje to wykrycie najwyższego możliwego trybu. Trzeba też podać ścieżkę do katalogu sterowników grafiki i czcionek (pliki BGI i CHR) - jest to trzeci argument procedury initGraph
.
W przypadku FPC nie trzeba podawać tej ścieżki. Musisz się jednak przygotować, że tryb Graph tego kompilatora różni się od oryginału (głównie dlatego, że musi działać na różnych platformach). W systemie Windows otworzy się w nowym oknie, co większość ludzi nie uważa za najlepsze rozwiązanie. Na Linuksie do kompilacji będzie nam potrzebna biblioteka svgalib razem z nagłówkami (pakiet libsvga1-dev), a gotowy program musimy uruchomić z prawami roota (co pewnie zniechęci większość użytkowników tego systemu).
Podstawy
Najbardziej podstawową procedurą tego unitu jest PutPixel(X, Y: Word; Color: Byte);
. Powoduje ona "zaczernienie" piksela na pozycji (X, Y), przy założeniu, że lewy górny róg ekranu ma współrzędne (0, 0). Poza tym do takich procedur możnaby zaliczyć Line(Ax, Ay, Bx, By)
, która narysuje linię od punktu (Ax, Ay) do (Bx, By) oraz Circle(X, Y, r)
, czyli koło o promieniu r.
Color
to indeks koloru lub odpowiednia stała - kolory są takie same jak w przypadku modułu Crt - patrz dodatek A. Zauważ, że dwie ostatnie procedury nie przyjmują tego argumentu. Zamiast tego używają one aktualnego koloru kursora graficznego. Można go zmienić za pomocą procedury SetColor(Color: Byte)
.
Przydatne będą dla nas również dwie funkcje: GetMaxX: Word
i GetMaxY
, które zwracają współrzędną X i Y prawego dolnego rogu ekranu.
W trybie Graph nie działają instrukcje wczytania i wyprowadzenia (Read
i Write
), a przynajmniej powinno tak być. Dlatego też do wczytywania danych z klawiatury musimy użyć modułu Crt, natomiast do wyprowadzania - specjalnej procedury modułu Graph: OutTextXY(X, Y: Word; T: String)
. Różni się ona od instrukcji wyprowadzenia tym, że możemy wypisywać tyko wartości String
; nie możemy także połączyć ich przecinkami - musimy użyć znaku plusa.
Kursor graficzny
W trybie graph istnieje pewien specjalny twór, zwany kursorem graficznym. W przeciwieństwie do zwykłego kursora nie widać go. Jest to po prostu miejsce, w którym kończyliśmy ostatnio rysować. Do czego się on nam przydaje? Otóż istnieją pewne procedury, które rysują względem tego właśnie miejsca.
Najprostsze to LineTo(nX, nY: Word)
i LineRel(dX, dY: Integer)
. Pierwsza z nich rysuje linię od kursora do punktu (nX, nY). Natomiast druga - linię do punktu (X+dX, Y+dY), jeśli założymy, że X i Y to współrzędne kursora. Można zatem powiedzieć, że rysuje wektor [dX,dY] o punkcie przyłożenia w (X, Y).
Możemy także ręcznie przemieścić kursor bez rysowania czegokolwiek. Służą do tego procedury MoveTo(nX, nY: Word)
i MoveRel(dX, dY)
, działające analogicznie do poprzednich.
Pobierz plik programu
Program Plotka;
Uses
Graph, Crt;
Const
IloscLudzi = 2000;
Var
MaxX, MaxY : Word;
I, J : LongInt;
Czlowiek : Array [0..IloscLudzi-1] Of
Record
X, Y : Double;
Vx, Vy : Double;
Slyszal : Word;
End;
Procedure UruchomGrafike;
Var
Karta, Tryb, Blad : Integer;
Begin
Karta:=VGA; { Ustawiamy kartę jaką posiadamy }
Tryb:=2; { Ustawiamy żądany tryb graficzny }
initGraph(Karta, Tryb, ''); { Inicjujemy grafikę }
Blad:=graphResult;
If (Blad<>grOK) Then
Begin
WriteLn('Wystąpił błąd podczas uruchamiania trybu graficznego: ',
graphErrorMsg(Blad));
Halt(1);
End;
MaxX:=GetMaxX;
MaxY:=GetMaxY;
End;
Procedure WylaczGrafike;
Begin
closeGraph;
End;
Begin
UruchomGrafike;
Randomize;
For I:=0 To IloscLudzi-1 Do
With Czlowiek[I] Do
Begin
X:=Random(MaxX+1);
Y:=Random(MaxY+1);
Vx:=0;
Vy:=0;
Slyszal:=0;
PutPixel(Trunc(X), Trunc(Y), DarkGray);
End;
Czlowiek[Random(IloscLudzi)].Slyszal:=1;
Repeat
For I:=0 To IloscLudzi-1 Do
With Czlowiek[I] Do
Begin
PutPixel(Trunc(X), Trunc(Y), Black);
Vx:=Vx+(Random(101)-50)/1000;
Vy:=Vy+(Random(101)-50)/1000;
If (Vx>1) Then Vx:=1;
If (Vy>1) Then Vy:=1;
If (Vx<-1) Then Vx:=-1;
If (Vy<-1) Then Vy:=-1;
X:=X+Vx;
Y:=Y+Vy;
If (X<0) Or (X>MaxX) Then Vx:=-Vx;
If (Y<0) Or (Y>MaxY) Then Vy:=-Vy;
For J:=0 To IloscLudzi-1 Do
If (I<>J) And (Abs(X-Czlowiek[J].X)<1) And (Abs(Y-Czlowiek[J].Y)<1) And (Czlowiek[J].Slyszal>0) Then
Inc(Slyszal);
If (Slyszal=0) Then
PutPixel(Trunc(X), Trunc(Y), DarkGray)
Else
PutPixel(Trunc(X), Trunc(Y), White);
End;
Until KeyPressed;
WylaczGrafike;
End.