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.