moduł Allegro.pas

Transkrypt

moduł Allegro.pas
Podstawy Programowania 1
Wykład czternasty:
Wstęp do grafiki 2D (moduł Allegro.pas)
Wykład 14
1.
Wstęp do grafiki 2D (moduł Allegro.pas)
Wstęp
Współczesne systemy komputerowe wyposażone są w sprzęt pozwalający generować realistyczną grafikę trójwymiarową. Duże znaczenie w różnych zastosowaniach ma również grafika dwuwymiarowa (oznaczana w skrócie 2d). Jej tworzenie możliwe jest w środowisku Turbo Pascal przy pomocy modułu graph.
Jest on jednakże dostępny tylko dla tego środowiska, a jego możliwości są stosunkowo ubogie. Z tego
względu wszystkie programy zaprezentowane w tych materiałach będą kompilowane tylko w środowisku
Free Pascal z zainstalowanym modułem Allegro.pas.
Moduł ten jest nakładką (ang. wrapper ) na bibliotekę Allegro stworzoną dla języka c, której głównym
przeznaczeniem jest tworzenie gier komputerowych z grafiką 2d. Oznacza to, że programy napisane
w Pascalu z użyciem tego modułu można stosunkowo łatwo przepisać w języku c. Dodatkowo, nazwy
i parametry funkcji i procedur z Allegro.pas dosyć często pokrywają się z tymi, które są umieszczone
w graph. Ze względu na rozmiar modułu Allegro.pas zostaną tutaj zaprezentowane głównie te jego
elementy, które zostały użyte do napisania przykładowych programów.
Środowisko Free Pascal dostarcza również innych modułów do tworzenia grafiki 2d i 3d, w tym wersji
modułu graph, która dostępna jest tylko dla systemu Windows.
2.
Instalacja
Zarówno biblioteka Allegro, jak i moduł Allegro.pas są dostępne za darmo jako otwarte oprogramowanie. Strona domowa projektu Allegro to: http://alleg.sourceforge.net/, natomiast projekt
Allegro.pas ma osobną stronę: http://allegro-pas.sourceforge.net/.
2.1.
Windows
Na stronie projektu Allegro.pas można znaleźć moduł w wersji skompilowanej dla systemów rodziny
Windows lub w postaci źródłowej. Obie wersje zawierają także skompilowaną dla tego systemu wersję
biblioteki Allegro1 . W przypadku wersji z kodem źródłowym, po rozpakowaniu pobranego archiwum
należy uruchomić plik fix.bat z argumentem wywołania win32. Aby programy używające Allegro.pas
mogły być skompilowane należy kompilatorowi podać ścieżkę do katalogu zawierającego moduł. Możemy
to uczynić z poziomu ide wybierając w menu Options→Directories, a następnie wpisując ścieżkę w polu
zakładki Unit directories.
2.2.
Linux
W przypadku systemów Linux najpierw należy zainstalować bibliotekę Allegro. W przypadku niektórych dystrybucji gotowe pakiety ze skompilowaną postacią tej biblioteki znajdują się w repozytoriach.
Należy tylko po ich zainstalowaniu sprawdzić wersję biblioteki i dobrać odpowiednią wersję modułu Allegro.pas. Po rozpakowaniu archiwum tego modułu należy uruchomić skrypt fix.sh z argumentem linux
i wskazać kompilatorowi ścieżkę do katalogu z modułem, tak, jak to zostało opisane dla systemu Windows2 . Jeśli biblioteki Allegro nie ma w repozytorium dystrybucji lub nie ma odpowiedniej jej wersji, to
można pograć jej kod źródłowy ze strony projektu i skompilować ją samodzielnie. W tym celu należy
rozpakować archiwum, utworzyć katalog o nazwie build, przejść do tego katalogu i wydać polecenie
cmake ..3 . Po zakończeniu jego wykonania należy wydać polecanie make i później make install. Po
zainstalowaniu biblioteki należy postępować tak jak to zostało opisane wcześniej.
3.
Inicjalizacja i finalizacja grafiki w module Allegro.pas
Aby skorzystać w programie z możliwości modułu Allegro.pas należy włączyć go za pomocą instrukcji uses. Moduł ten nosi nazwę allegro4 . Większość procedur i funkcji z Allegro.pas, w szczególności
1 Znajduje
się ona w pliku z rozszerzeniem .dll.
przypadku Linuksa nie są dostępne skompilowane wersje modułu Allegro.pas
3 Dwie kropki to argument wywołania polecenia, oznaczający katalog nadrzędny.
4 Istnieją również inne moduły związane z Allegro.pas, które nie będą tu opisane, a które zawierają np. podprogramy do
tworzenia graficznego interfejsu użytkownika (gui).
2W
1
Wykład 14
Wstęp do grafiki 2D (moduł Allegro.pas)
wszystkie te, które będą opisane poniżej, wymaga, aby przed ich użyciem wywołać funkcję al install
lub al init. Pierwsza z nich zwraca wartość True w przypadku udanej inicjalizacji, albo wartość False
w przeciwnym przypadku. Przyjmuje ona jeden parametr typu loingint, który określa identyfikator
systemu na którym program będzie uruchomiony. Najczęściej używaną wartością tego parametru jest
al system autodetect, dlatego częściej używana jest funkcja al init, której działanie jest równoważne funkcji al install wywołanej ze wspomnianą wartością parametru.
Funkcja al install keyboard powinna być wywołana, jeśli w programie potrzebna jest obsługa
klawiatury. Nie przyjmuje ona żadnych parametrów wywołania i jak poprzednio opisane funkcje zwraca
wartość True w przypadku powodzenia lub False w przeciwnym przypadku.
Jeżeli program wymaga obsługi myszy, to należy w nim wywołać funkcję al install mouse. Funkcja
ta, podobnie jak opisane wcześniej nie przyjmuje żadnych parametrów wywołania, ale zwraca wartość
typu longint. Jeśli wynosi ona -1, to oznacza, że nastąpił błąd inicjalizacji myszy, jeśli jest równa 0,
to oznacza, że mysz już była zaincjalizowana, a jeśli jest większa od zera, to oznacza, że obsługa myszy
została pomyślnie zainstalowana.
Procedura al exit dokonuje finalizacji modułu Allegro.pas i powinna być wywołana tuż przed zakończeniem programu z niego korzystającego.
Istnieją jeszcze inne podprogramy związane z inicjalizacją modułu Allegro.pas, między innymi dotyczące obsługi dźwięku. Ich zastosowanie wykracza poza zakres tych materiałów dlatego nie będą one tu
opisane.
Listing 1 zawiera przykład procedury, która wykonuje czynności związane z inicjalizacją modulu
Allegro.pas, które będą wystarczające dla większości programów zawartych w tych materiałach.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
procedure i n i c j a l i z u j ;
begin
i f not a l i n i t then
begin
w r i t e l n ( ’ Blad i n i c j a l i z a c j i b i b l i o t e k i A l l e g r o ! ’ ) ;
readln ;
halt (1) ;
end ;
i f not a l i n s t a l l k e y b o a r d then
begin
a l m e s s a g e ( ’ Blad i n i c j a l i z a c j i k l a w i a t u r y ! ’ ) ;
readln ;
halt (1) ;
end ;
a l s e t c o l o r d e p t h (32) ;
i f not a l s e t g f x m o d e (AL GFX AUTODETECT FULLSCREEN, 1 3 6 6 , 7 6 8 , 0 , 0 ) then
begin
a l m e s s a g e ( ’ Blad u s t a w i a n i a t r y b u g r a f i c z n e g o ! ’ ) ;
readln ;
halt ;
end ;
end ;
Listing 1: Procedura inicjalizacyjna
4.
Obsługa trybu graficznego
Procedura zawarta w listingu 1 zawiera wywołania al set color depth i al set gfx mode. Pierwsza ustala wielkość formatu opisu koloru pojedynczego piksela, czyli liczbę dostępnych kolorów. Piksel
jest najmniejszą jednostką, której kolor możemy zmienić na ekranie w trybie graficznym. Jest on odpowiednikiem punktu dla płaszczyzny. Liczba 32 oznacza, że kolor każdego piksela na ekranie zostanie
opisany za pomocą 4 bajtów. Format taki nosi nazwę rgba, gdzie litera r oznacza składową czerwoną
koloru, litera g, składową zieloną, litera b składową niebieską, a litera a tzw. kanał alfa, który decyduje o tym w jakim stopniu piksel będzie przezroczysty. Funkcja al set gfx mode włącza tryb graficzny.
W przypadku pomyślnego wykonania tej operacji zwraca wartość True, w przeciwnym przypadku wartość False. Przyjmuje pięć parametrów typu longint. Pierwszy jest identyfikatorem sterownika karty
graficznej. Najczęściej za ten parametr podstawiane są stałe al gfx autodetect fullscreen - uruchomienie trybu graficznego w wersji pełnoekranowej, al gfx autodetect windowed - uruchomienie
2
Wykład 14
Wstęp do grafiki 2D (moduł Allegro.pas)
trybu graficznego w wersji okienkowej lub al gfx text - przejście do trybu tekstowego. Kolejne dwa
parametry określają maksymalną wielkość ekranu w trybie graficznym wyrażoną w pikselach. Dwa kolejne parametry określają wielkość tzw. ekranu wirtualnego, który wykorzystywany jest przy animacji.
Jeśli pierwszym parametrem wywołania była stała al gfx text, to wartości pozostałych parametrów
powinny wynosić zero. Procedura al message służy do wyświetlania okienka informującego o błędzie,
który sygnalizuje ostatnio wywołana funkcja z modułu Allegro.pas. Opis tego błędu jest przechowywany
w zmiennej al error, a jego kod w zmiennej al errno. Rozmiary ekranu, po dokonaniu inicjalizacji trybu graficznego, przechowywane są w dwóch zmiennych typu longint o nazwach al screen w - liczba
pikseli w poziomie oraz al screen h - liczba pikseli w pionie.
5.
Tworzenie obrazu
Wszystkie podprogramy rysujące zgromadzone w module Allegro.pas tworzą kształty na strukturze
nazywanej bitmapą. Jest to specjalnie zarządzany fragment pamięci dostępny za pomocą zmiennej typu al bitmapptr5 . Moduł Allegro.pas zawiera także zmienną o nazwie al screen, która jest bitmapą
umieszczoną w pamięci wideo, a więc cokolwiek zostanie w niej zapisane będzie natychmiast odwzorowane na ekranie. Większość podprogramów, które są zawarte w module Allegro.pas przyjmuje najczęściej
tę zmienną jako pierwszy parametr wywołania.
Współrzędne ekranu i dowolnej bitmapy liczone są względem lewego górnego rogu. Piksel znajdujący
się w tym miejscu ma współrzędne o wartości (0, 0).
Moduł Allegro.pas dostarcza wielu podprogramów do rysowania prostych kształtów, które w grafice
komputerowej nazywa się prymitywami. Najprostszym przykładem prymitywu jest piksel. Rysowanie
piksela polega na zmianie jego koloru. Do tego służy w Allegro.pas procedura al putpixel. Przyjmuje
one cztery parametry. Pierwszym jest zmienna typu al bitmapptr, trzy kolejne są typu longint i opisują położenie (współrzędne x i y) piksela i jego nowy kolor. Wartość koloru może być określona za pomocą
funkcji al makecol. Przyjmuje ona trzy parametry typu longint, które są wartościami składowych koloru, czyli czerwieni, zieleni i koloru niebieskiego. Warto zauważyć, że te wartości są liczbami naturalnymi
z zakresu od 0 do 255, a więc typ longint jest użyty tutaj trochę „na wyrost”.
Odcinek rysuje procedura al line. Przyjmuje ona sześć parametrów wywołania. Pierwszym jest
zmienna wskazująca na bitmapę (typu al bitmapptr), a pięć kolejnych jest typu longint. Drugi i trzeci
parametr są współrzędnymi punktu początkowego odcinka, a czwarty i piąty punktu końcowego. Ostatni
parametr określa kolor.
Do rysowania okręgów przeznaczona jest procedura al circle. Przyjmuje ona pięć parametrów wywołania. Pierwszym jest zmienna wskazująca na bitmapę, a cztery kolejne parametry mają typu longint
i są to kolejno: współrzędne środka okręgu, długość promienia wyrażona w pikselach oraz kolor okręgu.
Prostokąt rysowany jest za pomocą wywołania procedury al rect. Przyjmuje ona sześć parametrów.
Pierwszy z nich jest taki sam jak w przypadku poprzednich procedur. Kolejna czwórka jest typu longint
i określa kolejno współrzędne lewego górnego oraz prawego dolnego rogu. Ostatni parametr jest także
typu longint i określa kolor prostokąta.
Grafika 2d może przedstawiać obraz statyczny lub dynamiczny. Aby animacje były płynne obraz
musi być wyświetlany z częstotliwością co najmniej 24 klatek na sekundę. Moduł Allegro.pas wspiera
tworzenie animacji poprzez dostarczenie mechanizmu obsługi tak zwanych stron. Strona jest po prostu
bitmapą na której program rysuje pojedynczą klatkę animacji, a następnie wyświetla ją na ekranie.
Pierwszą czynnością jaką program musi zrobić zanim użyje bitmapy jest przydzielenie na nią pamięci, co
wykonuje wywołując funkcję al create video bitmap. Przyjmuje ona dwa parametry typu loingint
określające szerokość i wysokość bitmapy, a zwraca wartość typu al bitmapptr. Tak przydzieloną pamięć
przed zakończeniem programu lub przed kolejnym wywołaniem al set gfx mode należy zwolnić. W tym
celu trzeba wywołać procedurę al destroy bitmap. Przyjmuje ona jeden parametr wywołania i jest
nią zmienna typu al bitmapptr. Aby wyświetlić klatkę animacji zawartą na stronie należy wywołać
procedurę al show video bitmap i przekazać do niej jako parametr wywołania zmienną wskaźnikową
do bitmapy na której ta klatka jest narysowana. Aby wyczyścić bitmapę należy wywołać procedurę
al clear to color. Przyjmuje ona dwa parametry. Pierwszym jest zmienna wskaźnikowa do bitmapy,
a drugą numer koloru na jaki ma być ustawiona cała jej powierzchnia.
5 Jest
to tak zwana zmienna wskaźnikowa. Wskaźnikami będziemy dokładniej zajmować się w przyszłym semestrze.
3
Wykład 14
6.
Wstęp do grafiki 2D (moduł Allegro.pas)
Obsługa wejścia-wyjścia
Moduł Allegro.pas posiada własny interfejs, który odpowiedzialny jest za obsługę komunikacji z użytkownikiem. W następnych podrozdziałach zostaną opisane procedury, funkcje i inne elementy, które są
do tego celu przeznaczone.
6.1.
Obsługa klawiatury
Naciśnięcie przez użytkownika dowolnego klawisza sygnalizuje funkcja al keypressed zwracając
wartość True. Moduł Allegro.pas zawiera także procedurę do czyszczenia bufora klawiatury o nazwie
al clear keybuf. Nie przyjmuje ona żadnych parametrów wywołania. Allegro.pas dostarcza także tablicy o nazwie al key, której elementy opisują stan poszczególnych klawiszy klawiatury. Jeśli wartość
danego elementu jest różna od zera, to oznacza to, że klawisz ten został wciśnięty. Wartości indeksów
wszystkich elementów tej tablicy zostały oznaczone specjalnymi, czytelnymi stałymi. Jeśli np. chcemy sprawdzić czy klawisz Escape nie został wciśnięty, to możemy to uczynić przyrównując wyrażenie
al key[al key esc] do zera. Inne z tych stałych, które zostały użyte w przykładowych programach, to
al key q dla klawisza „q” oraz al key space dla klawisza spacji.
6.2.
Obsługa tekstu
W trybie graficznym tekst nie może być wyświetlany za pomocą procedur write i writeln. W module
Allegro.pas służy do tego procedura al textout ex. Przyjmuje ona sześć parametrów wywołania. Pierwszy jest zmienną wskaźnikową do bitmapy, drugi zmienną wskaźnikową do struktury opisującej czcionkę.
Najczęściej za ten parametr podstawiana jest zmienna o nazwie al font. Domyślna czcionka w Allegro.pas jest niestety małych rozmiarów, ale użycie innej czcionki jest dosyć kłopotliwe. Trzeci parametr,
to łańcuch znaków, który ma zostać wypisany. Kolejna para parametrów procedury al textout ex to
współrzędne miejsca na ekranie, od którego ma rozpocząć się wyświetlanie łańcucha znaków. Oba parametry są typu longint, podobnie jak piąty i szósty parametr, które określają odpowiednio kolor znaków
i kolor tła na którym te znaki zostaną umieszczone. Jeśli chcemy, aby napis był zamieszczony na przezroczystym tle, to podajemy wartość -1. Jeśli chcemy aby wypisywany na ekranie tekst był wyśrodkowany,
to możemy użyć procedury al textout centre ex. Przyjmuje ona te same parametry wywołania co
poprzednio opisywana procedura, ale zakłada, że przekazane jej współrzędne należą do punktu, który
należy do środka wyświetlanego napisu.
7.
1
Przykłady
program g r a f i k a ;
2
3
4
uses
allegro , crt ;
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
procedure i n i c j a l i z u j ;
begin
i f not a l i n i t then
begin
w r i t e l n ( ’ Blad i n i c j a l i z a c j i b i b l i o t e k i A l l e g r o ! ’ ) ;
readln ;
halt (1) ;
end ;
i f not a l i n s t a l l k e y b o a r d then
begin
a l m e s s a g e ( ’ Blad i n i c j a l i z a c j i k l a w i a t u r y ! ’ ) ;
readln ;
halt (1) ;
end ;
a l s e t c o l o r d e p t h (32) ;
i f not a l s e t g f x m o d e (AL GFX AUTODETECT FULLSCREEN, 1 3 6 6 , 7 6 8 , 0 , 0 ) then
begin
a l m e s s a g e ( ’ Blad u s t a w i a n i a t r y b u g r a f i c z n e g o ! ’ ) ;
readln ;
4
Wykład 14
25
26
27
Wstęp do grafiki 2D (moduł Allegro.pas)
halt (1) ;
end ;
end ;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
p r o c e d u r e DrawRandomCircle ;
var
x , y : integer ;
r , red , g r e e n , b l u e : word ;
begin
x:=random (AL SCREEN W) ;
y:=random (AL SCREEN H) ;
r :=random ( 5 0 ) ;
r e d :=random ( 2 5 6 ) ;
g r e e n :=random ( 2 5 6 ) ;
b l u e :=random ( 2 5 6 ) ;
a l c i r c l e ( a l s c r e e n , x , y , r , a l m a k e c o l ( red , g r e e n , b l u e ) ) ;
end ;
42
43
44
45
46
47
48
49
50
51
begin
inicjalizuj ;
randomize ;
al clear keybuf ;
repeat
DrawRandomCircle ;
until al keypressed ;
al exit ;
end .
Listing 2: Losowe okręgi
Program z listingu 2 tworzy wzór na ekranie złożony z losowo narysowanych okręgów. Ich rysowaniem
zajmuje się procedura DrawRandomCircle. W wierszach6 34 i 35 procedura losuje przy pomocy funkcji
random współrzędne środka okręgu. Proszę zauważyć, że środek ten może być położony w dowolnym
miejscu ekranu, a więc niektóre okręgi będą częściowo znajdowały się „poza ekranem”. W wierszu 36
losowana jest długość promienia (od 0 do 49 pikseli), a w trzech kolejnych wierszach składowe koloru
okręgu. Pojedynczy okrąg jest rysowany za pomocą wywołania procedury al circle. W bloku głównym
programu procedura DrawRandomCircle jest wywoływana w pętli, która kończy się po naciśnięciu przez
użytkownika dowolnego klawisza (wiersze 47-49).
1
program f r a k t a l ;
2
3
4
uses
allegro ;
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
procedure i n i c j a l i z u j ;
const
width : i n t e g e r =1366;
h e i g h t : i n t e g e r =768;
begin
i f not a l i n i t then
begin
w r i t e l n ( ’ Blad i n i c j a l i z a c j i b i b l i o t e k i A l l e g r o ! ’ ) ;
readln ;
halt (1) ;
end ;
i f not a l i n s t a l l k e y b o a r d then
begin
a l m e s s a g e ( ’ Blad i n i c j a l i z a c j i k l a w i a t u r y ! ’ ) ;
readln ;
halt (1) ;
end ;
a l s e t c o l o r d e p t h (32) ;
i f not a l s e t g f x m o d e (AL GFX AUTODETECT FULLSCREEN, width , h e i g h t , 0 , 0 ) then
begin
a l m e s s a g e ( ’ Blad u s t a w i a n i a t r y b u g r a f i c z n e g o ! ’ ) ;
readln ;
halt (1) ;
6 Numery
wierszy nie są częścią programu! Zostały one wprowadzone, aby ułatwić jego opis.
5
Wykład 14
29
30
Wstęp do grafiki 2D (moduł Allegro.pas)
end ;
end ;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
p r o c e d u r e draw ( x , y : r e a l ) ;
var
choice : integer ;
begin
al clear keybuf ;
w h i l e not a l k e y p r e s s e d do
begin
c h o i c e :=random ( 4 ) ;
case choice of
0: begin
x := −0.678∗ x −0.02∗ y ;
y := −0.18∗ x +0.81∗ y +10;
end ;
1: begin
x : = 0 . 4 ∗ x +0.4∗ y ;
y := −0.1∗ x +0.4∗ y ;
end ;
2: begin
x := −0.4∗x −0.4∗ y ;
y := −0.1∗ x +0.4∗ y ;
end ;
3: begin
x := −0.1∗ x ;
y : = 0 . 4 4 ∗ x +0.44∗ y −2;
end ;
end ;
a l p u t p i x e l ( a l s c r e e n ,640 − t r u n c ( 1 4 ∗ x ) ,730 − t r u n c ( 1 4 ∗ y ) , a l m a k e c o l ( 0 , 2 5 5 , 0 ) ) ;
end ;
end ;
61
62
63
64
65
66
67
begin
randomize ;
inicjalizuj ;
draw ( 0 , 0 ) ;
al exit ;
end .
Listing 3: Fraktal
Fraktale są obiektami geometrycznymi, które cechuje powtarzalność struktury7 . Istnieje wiele metod
tworzenia takich obiektów. Zaliczają się do nich tzw. L-Systemy, układy odwzorowań afinicznych (ifs)
oraz równania rekurencyjne i zespolone8 . Fraktale są używane w grafice komputerowej do tworzenia
obiektów przypominających obiekty naturalne, takie jak: chmury, pagórki porośnięte trawą, itd. Program
z listingu 3 prezentuje użycie układu odwzorowań do wygenerowania ciekawego fraktala.
Obiekt ten jest rysowany „punkt po punkcie”.Współrzędne każdego następnego punktu są wyliczane
na podstawie współrzędnych poprzedniego punktu, za pomocą następującego układu równań:
0
x =a·x+b·y+c
y0 = d · x + e · y + f
Zmienne x0 i y 0 są współrzędnymi nowego punktu, a x i y współrzędnymi poprzedniego punktu. Istnieją
cztery zestawy współczynników a, b, c, d, e i f . Każdy z nich jest wybierany na drodze losowej przed
wyliczeniem współrzędnych następnego punktu. Oto zestawy tych współczynników:
a
a
a
a
= −0, 67; b = −0, 02; c = 0; d = −0, 18; e = 0, 81; f = 10
= 0, 4; b = 0, 4; c = 0; d = −1; e = 0, 4; f = 0
= −0, 4; b = −0, 4; c = 0; d = −0, 1; e = 0, 4; f = 0
= −0, 1; b = 0; c = 0; d = 0, 44; e = 0, 44; f = −2
7 Matematyczne wprowadzenie do fraktali można znaleźć w książce Jacka Kudrewicza „Fraktale i chaos”, WNT, Warszawa, 1993.
8 Niektóre z tych metod zostały opisane na stronie: http://lodev.org/cgtutor/.
6
Wykład 14
Wstęp do grafiki 2D (moduł Allegro.pas)
Im więcej punktów wyliczymy tym efekt wizualny będzie lepszy. Kod programu rysującego omawiany
fraktal składa się ze zmienionej procedury inicjalizuj (rozmiar ekranu zapisany jest w zmiennych zainicjalizowanych) oraz z procedury draw posiadającej dwa parametry formalne, będące współrzędnymi
punktu początkowego dla metody obliczania fraktala. Ten punkt nie jest rysowany. Kolejne punkty są
wyliczane wewnątrz pętli while. Najpierw losowany jest układ równań, który zostanie użyty do obliczenia
współrzędnych nowego punktu, następnie wyliczane są te współrzędne. Do narysowania odpowiadającego im piksela używana jest procedura al putpixel. Niestety, nie istnieje jednoznaczne odwzorowanie
punktów na piksle, gdyż punkty mają współrzędne rzeczywiste, a piksle całkowite. Musimy więc użyć
funkcji trunc do przeliczenia współrzędnych punktu na współrzędne piksela. Zanim to nastąpi współrzędne punktu są skalowane (mnożone) przez współczynnik 14. Tak wyliczone współrzędne piksela są
odejmowane od 640 (rzędna) i 730 (odcięta), co sprawia, że obraz jest widoczny w połowie szerokości
ekranu, powiększony i nie jest odwrócony. Wszystkie piksele otrzymane w ten sposób są zaznaczane na
ekranie na zielono, bowiem rysowany fraktal nazywany jest „choinką” z uwagi na swój kształt. Pętla
while jest wykonywana do momentu naciśnięcia przez użytkownika dowolnego klawisza.
1
program s i n u s ;
2
3
4
uses
allegro ;
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
p r o c e d u r e i n i c j a l i z u j ( width , h e i g h t : l o n g i n t ) ;
begin
i f not a l i n i t then
begin
w r i t e l n ( ’ Blad i n i c j a l i z a c j i b i b l i o t e k i A l l e g r o ! ’ ) ;
readln ;
halt (1) ;
end ;
i f not a l i n s t a l l k e y b o a r d then
begin
a l m e s s a g e ( ’ Blad i n i c j a l i z a c j i k l a w i a t u r y ! ’ ) ;
readln ;
halt (1) ;
end ;
a l s e t c o l o r d e p t h (32) ;
i f not a l s e t g f x m o d e (AL GFX AUTODETECT FULLSCREEN, width , h e i g h t , 0 , 0 ) then
begin
a l m e s s a g e ( ’ Blad u s t a w i a n i a t r y b u g r a f i c z n e g o ! ’ ) ;
readln ;
halt (1) ;
end ;
end ;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
procedure drawsinus ;
const
deg2rad = pi /180;
var
x , x1 , h a l f s c r , x r a t i o : l o n g i n t ;
y , y1 : r e a l ;
begin
x :=0;
h a l f s c r :=AL SCREEN H s h r 1 ;
x r a t i o :=AL SCREEN W d i v 3 6 0 ;
y :=0;
f o r x1 :=1 t o 360 do
begin
y1 := h a l f s c r ∗ s i n ( x1 ∗ d e g 2 r a d ) ;
a l l i n e (AL SCREEN, x r a t i o ∗x , h a l f s c r −round ( y ) , x r a t i o ∗x1 , h a l f s c r −round ( y1 ) , a l m a k e c o l
(0 ,255 ,0) ) ;
y:= y1 ;
x:= x1 ;
end ;
end ;
49
50
51
begin
i n i c j a l i z u j (1366 ,768) ;
7
Wykład 14
52
53
54
55
Wstęp do grafiki 2D (moduł Allegro.pas)
drawsinus ;
w h i l e ( ( a l k e y [ AL KEY Q]=0) and ( a l k e y [ AL KEY ESC]=0) ) do ;
al exit ;
end .
Listing 4: Sinus
Program z listingu 4 rysuje na ekranie jeden okres funkcji sinus. W skład kodu źródłowego wchodzi procedura inicjalizuj, tym razem z dwoma parametrami, które określają wielkość ekranu oraz procedura
drawsinus. Rysowanie wykresu funkcji odbywa się za pomocą tej ostatniej. Stała deg2rad zdefiniowana
wewnątrz procedury jest używana do przeliczenia stopni na radiany. Rzędne punktów są przechowywane
w zmiennych x i x1 typu integer, a odcięte w zmiennych y i y1 typu real. Zmienne halfscr i x ratio
służą do przechowywania połowy wysokości ekranu i liczby pikseli w poziomie przypadających na jeden
stopień.
Pierwszą czynnością wykonywaną w procedurze drawsinus jest inicjalizacja zmiennych odpowiednimi wartościami (wiersze 37-40). Połowa wysokości ekranu wyliczana jest (wiersz 38) przez przesunięcie
w prawo o jeden wartości zmiennej al screen h. Odpowiada to całkowitemu dzieleniu tej wartości przez
dwa, ale jest szybsze w działaniu. Liczba pikseli przypadających na stopień wyliczana jest poprzez podzielenie wartości zmiennej al screen w przez 360 (wiersz 39). Dzięki tak obliczonym wartościom tych
zmiennych sinus będzie narysowany w połowie wysokości ekranu i na jak największej jego powierzchni9 .
Rysowanie wykresu funkcji odbywa się w pętli for. W wierszu 43 wyliczana jest odcięta (y1) punktu
należącego do wykresu, którego rzędna wynosi x1. Do tego celu używana jest funkcja sin będąca częścią
języka Pascal. Jej wynik mnożony jest przez połowę wysokości ekranu. Inaczej, ze względu na to, że sinus
ma wartości z przedziału [-1,1], na ekranie zobaczylibyśmy tylko zniekształconą prostą. Do funkcji sin
przekazywana jest rzędna x1 pomnożona przez wartość deg2rad. Fragment wykresu, od punktu (x, y)
do punktu (x1, y1) jest rysowany za pomocą wywołania procedury al line. Rzędne tych punktów są
skalowane przez wartość zmiennej x ratio, a odcięte zaokrąglane przez funkcję round i odejmowane od
wartości zmiennej halfscr. Po wywołaniu tej procedury wartości zamiennych x1 i y1 są przypisywane
zmiennym x i y. Dzięki temu bieżący punkt do którego wykres został narysowany staje się punktem od
którego będzie rysowany nowy fragment wykresu. Dodatkowo gwarantuje to ciągłość rysowanego sinusa.
W bloku głównym, po wywołaniu procedury drawsinus, program w pętli while oczekuje aż użytkownik naciśnie klawisz „q” lub Escape (wiersz 53) proszę zwrócić uwagę, że ta pętla jest pusta - po
słowie kluczowym do jest średnik.
1
program p i m o n t e c a r l o ;
2
3
4
uses
allegro , crt ;
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
procedure i n i c j a l i z u j ;
const
width : i n t e g e r = 1 3 6 6 ;
height : integer = 768;
begin
i f not a l i n i t then
begin
w r i t e l n ( ’ Blad i n i c j a l i z a c j i b i b l i o t e k i A l l e g r o ! ’ ) ;
readln ;
halt (1) ;
end ;
i f not a l i n s t a l l k e y b o a r d then
begin
a l m e s s a g e ( ’ Blad i n i c j a l i z a c j i k l a w i a t u r y ! ’ ) ;
readln ;
halt (1) ;
end ;
a l s e t c o l o r d e p t h (32) ;
i f not
a l s e t g f x m o d e (AL GFX AUTODETECT FULLSCREEN, width , h e i g h t , 0 , 0 ) then
begin
a l m e s s a g e ( ’ Blad u s t a w i a n i a t r y b u g r a f i c z n e g o ! ’ ) ;
readln ;
halt (1) ;
9 Ze
względu na zaokrąglenie wartości zmiennej x ratio nie będzie to cała szerokość ekranu.
8
Wykład 14
29
30
Wstęp do grafiki 2D (moduł Allegro.pas)
end ;
end ;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
procedure l p i ;
type
naturalne = 0 . . maxlongint ;
const
r =300;
xs =650;
ys =400;
var
n ,m: n a t u r a l n e ;
x , y : integer ;
s , s1 : s t r i n g ;
xr , yr , p i : r e a l ;
begin
m: = 0 ;
n:=0;
s := ’ ’ ;
s 1 := ’ ’ ;
al clear keybuf ;
w h i l e not a l k e y p r e s s e d do
begin
x r:=− r+random ( 2 ∗ r )+random ;
y r:=− r+random ( 2 ∗ r )+random ;
x:= t r u n c ( x r ) ;
y:= t r u n c ( y r ) ;
inc (n) ;
i f s q r t ( s q r ( x r )+s q r ( y r ) )<=r then
begin
a l p u t p i x e l ( a l s c r e e n , x+xs , y+ys , a l m a k e c o l ( 2 5 5 , 0 , 0 ) ) ;
i n c (m) ;
end
e l s e a l p u t p i x e l ( a l s c r e e n , x+xs , y+ys , a l m a k e c o l ( 0 , 2 5 5 , 0 ) ) ;
i f m mod 5000 = 0 then
begin
p i :=4∗m/n ;
a l t e x t o u t e x ( a l s c r e e n , a l f o n t , ’ P r z y b l i z o n a w a r t o s c PI : ’+s , 5 0 0 , 5 0 , a l m a k e c o l
( 0 , 0 , 0 ) , −1) ;
str ( pi :0:2 0 , s ) ;
a l t e x t o u t e x ( a l s c r e e n , a l f o n t , ’ P r z y b l i z o n a w a r t o s c PI : ’+s , 5 0 0 , 5 0 , a l m a k e c o l
( 2 5 5 , 2 5 5 , 2 5 5 ) , −1) ;
a l t e x t o u t e x ( a l s c r e e n , a l f o n t , ’ L i c z b a i t e r a c j i : ’+s1 , 5 0 0 , 6 0 , a l m a k e c o l ( 0 , 0 , 0 )
, −1) ;
s t r (n , s1 ) ;
a l t e x t o u t e x ( a l s c r e e n , a l f o n t , ’ L i c z b a i t e r a c j i : ’+s1 , 5 0 0 , 6 0 , a l m a k e c o l
( 2 5 5 , 2 5 5 , 2 5 5 ) , −1) ;
end ;
end ;
end ;
75
76
77
78
79
80
81
begin
randomize ;
inicjalizuj ;
lpi ;
al exit ;
end .
Listing 5: Liczba π
Istnieje wiele sposobów wyliczenia wartości liczby π. Jednym z nich jest zastosowanie metody należącej
do zbioru algorytmów określanych wspólnym mianem metod Monte Carlo. Odkrycie tych metod zawdzięczamy polskiemu matematykowi, pracującemu w Stanach Zjednoczonych, Stanisławowi Ulamowi.
Ich działanie opiera się na liczbach losowych. Są one używane do otrzymywania przybliżonych wartości
rozwiązań równań, których nie można wyznaczyć w sposób analityczny, lub rozwiązanie ich innym sposobem byłoby zbyt czasochłonne. Do takich metod zaliczana jest opisana niżej metoda10 na obliczenie
10 Opis tej i innych metod wyznaczania wartości liczby π znajduje się na stronie prowadzonej przez Eve Astrid Anderson:
http://www.eveandersson.com/pi/.
9
Wykład 14
Wstęp do grafiki 2D (moduł Allegro.pas)
przybliżonej wartości liczby π. Załóżmy, że mamy koło wpisane w kwadrat. Bok kwadratu jest wtedy
π·r 2
π
dwa razy dłuższy od promienia koła. Stosunek pola koła do pola kwadratu wynosi zatem (2·r)
2 = 4.
Losujemy punkty wewnątrz kwadratu i sprawdzamy, czy leżą one również wewnątrz koła. Niech m będzie
liczbą punktów, które leżą wewnątrz koła, a n liczbą wszystkich wylosowanych punktów. Przybliżona
wartość liczby π będzie wynosiła π ≈ 4·m
n . Program, który ilustruje użycie tej metody znajduje się w listingu 5. Najważniejsze operacje wykonywane w programie zawarte są w procedurze lpi. Zdefiniowany
jest tam typ naturalne, który obejmuje swym zakresem liczby naturalne od 0 do maxlongint, oraz
trzy stałe: r=300 oznaczająca długość promienia koła, oraz xs=650 i ys=400 oznaczające współrzędne
środka wyświetlanego obrazu. Zmienne x i y są współrzędnymi zaznaczanych pikseli, zmienne s i s1
typu string będą wykorzystywane podczas konwersji wartości liczb π na łańcuchy znaków. Zmienne xr
i yr będą przechowywać współrzędne wylosowanych punktów. Zmienna pi będzie przechowywała wyliczoną, przybliżoną wartość liczby π. Wykonanie procedury rozpoczyna się inicjalizacji zmiennych m i n,
którym przypisywana jest wartość 0 i zmiennych s i s1, którym przypisywane są łańcuchy puste. Następnie w pętli while, losowane są współrzędne punktów leżących wewnątrz kwadratu o środku w punkcie
o współrzędnych (0, 0). Kolejną czynnością wykonywaną w tej pętli, jest konwersja współrzędnych rzeczywistych punktu, na współrzędne całkowite piksela i zwiększenie wartości zmiennej n o 1. W instrukcji
warunkowej if program sprawdza, czy wylosowany punkt należy także do koła. Zgodnie z definicją koła,
wszystkie punkty należące do niego leżą względem jego środka, w odległości mniejszej lub równej długości
jego promienia. Ponieważ środek koła użytego w programie położony jest w punkcie
p o współrzędnych
(0, 0), to odległość punktu od środka koła można wyznaczyć ze wzoru Euklidesa: x2 + y 2 . Jeśli punkt
należy do wnętrza koła, to odpowiadający mu piksel jest jest kolorowany na czerwono i zwiększana
jest wartość m. Jeśli nie, to piksel jest zaznaczany na zielono. W obu przypadkach do współrzędnych
piksela dodawane są stałe xs i ys, aby obraz był widoczny w całości i znajdował się w pobliżu środka
ekranu11 . Co 5000 iteracji pętli wyliczana jest wartość π (wiersz 65) i wypisywana na ekranie, wraz
z informacją o liczbie wykonanych iteracji. Częstsze wypisywanie tych wartości znacznie spowolniłoby
wykonanie programu. Proszę zwrócić również uwagę na sposób wypisywania tekstu na ekranie. Najpierw
jest wypisywane są na czarno wartości ciągów znaków, aby wymazać poprzednią zawartość ekranu (wiersze 66 i 69), a dopiero potem wypisywana jest wartość bieżąca (wiersze 68 i 71). Ponieważ procedura
al textout ex wypisuje tylko ciągi znaków, to wartości zmiennych m i n najpierw należy skonwertować
do takiej postaci za pomocą procedury str (wiersze 67 i 70), a dopiero potem wypisać. Pętla while
kończy się jeśli użytkownik naciśnie dowolny klawisz na klawiaturze.
1
program animate ;
2
3
uses a l l e g r o ;
4
5
6
const
npages =2;
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
p r o c e d u r e i n i c j a l i z u j ( width , h e i g h t : l o n g i n t ) ;
begin
i f not a l i n i t then
begin
w r i t e l n ( ’ Blad i n i c j a l i z a c j i b i b l i o t e k i A l l e g r o ! ’ ) ;
readln ;
halt (1) ;
end ;
i f not a l i n s t a l l k e y b o a r d then
begin
a l m e s s a g e ( ’ Blad i n i c j a l i z a c j i k l a w i a t u r y ! ’ ) ;
readln ;
halt (1) ;
end ;
a l s e t c o l o r d e p t h (32) ;
i f not a l s e t g f x m o d e (AL GFX AUTODETECT FULLSCREEN, width , h e i g h t , npages ∗ width , npages ∗
h e i g h t ) then
begin
a l m e s s a g e ( ’ Blad u s t a w i a n i a t r y b u g r a f i c z n e g o ! ’ ) ;
readln ;
11 Warto zwrócić uwagę, że obraz w tym programie jest odwrócony. Ponieważ jest on symetryczny, to nie wpływa to na
jego treść.
10
Wykład 14
27
28
29
Wstęp do grafiki 2D (moduł Allegro.pas)
halt (1) ;
end ;
end ;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
p r o c e d u r e draw ;
type
p a g e s t a b l e = a r r a y [ 0 . . npages −1] o f AL BITMAPptr ;
var
pages : p a g e s t a b l e ;
a c t i v e p a g e : AL BITMAPptr ;
i : byte ;
x : longint ;
begin
f o r i := low ( p a g e s ) t o h i g h ( p a g e s ) do
begin
p a g e s [ i ] : = a l c r e a t e v i d e o b i t m a p (AL SCREEN W, AL SCREEN H) ;
i f p a g e s [ i ]=NIL then
begin
a l m e s s a g e ( ’ Blad a l o k o w a n i a p a m i e c i na s t r o n y . ’ ) ;
readln ;
al exit ;
halt (1) ;
end ;
end ;
x :=0;
i := low ( p a g e s ) ;
a c t i v e p a g e := p a g e s [ i ] ;
repeat
a l c l e a r t o c o l o r ( active page , al makecol (0 ,0 ,0) ) ;
a l r e c t ( a c t i v e p a g e , x mod AL SCREEN W, ( AL SCREEN H s h r 1 ) ,100+ x mod AL SCREEN W
, ( AL SCREEN H s h r 1 ) +100 , a l m a k e c o l ( 2 5 5 , 2 5 5 , 0 ) ) ;
inc (x ,5) ;
al show video bitmap ( active page ) ;
i :=( i +1) mod npages ;
a c t i v e p a g e := p a g e s [ i ] ;
u n t i l ( a l k e y [ AL KEY ESC]<>0) o r ( a l k e y [ AL KEY Q]<>0) ;
f o r i := low ( p a g e s ) t o h i g h ( p a g e s ) do
a l d e s t r o y b i t m a p ( pages [ i ] ) ;
end ;
65
66
begin
i n i c j a l i z u j (1366 ,768) ;
draw ;
al exit ;
67
68
69
70
end .
Listing 6: Animacja - prostokąt
Program z listingu 6 pokazuje prostą animację na ekranie komputera - poruszający się w prawo kwadrat
o długości boku równej 100 pikseli. Do wykonania tej animacji użyto mechanizmu stron. Ich liczba jest
określona stałą napages. Proszę zwrócić uwagę, że procedura inicjalizuj w tym programie wywołuje
procedurę al set gfx mode z dwoma ostatnimi parametrami różnymi od zera. Określają one wielkość
ekranu wirtualnego na którym będą rozmieszczone bitmapy opisujące strony. Wielkość ta jest wielokrotnością szerokości i wysokości widocznego ekranu. Animacja rysowana jest w procedurze draw. Zawiera ona
tablicę elementów typu al bitmapptr o nazwie pages i liczbie elementów odpowiadającej liczbie użytych
stron. Zadeklarowana jest w niej także zmienna active page, typu bitmapptr oraz zmienna i typu byte
i zmienna x typu longint. W pierwszej pętli for (wiersze 40-50) procedura przydziela pamięć na strony.
Jeśli nie udałoby się przydzielić pamięci na jedną ze stron, to element tablicy jej odpowiadający miałby
wartość nil. Po zakończeniu tej pętli inicjalizowana są zmienne x (współrzędna pozioma w animacji),
i (indeks tablic npages), oraz active page (wskazuje na tę stronę na której program będzie rysował
kolejną klatkę). W pętli repeat . . . until, która kończy się w momencie naciśnięcia przez użytkownika klawisza „q” lub Escape, program rysuje i wyświetla kolejne klatki animacji. Najpierw czyszczona
jest bitmapa związana z aktywną stroną poprzez ustawienie koloru jej powierzchni na czarny. Następnie
rysowany jest na niej kwadrat o wymiarach 100 pikseli na 100. Współrzędne poziome lewego górnego
i prawego dolnego rogu dzielone są modulo szerokość ekranu. Dzięki temu jeśli kwadrat „zawędruje” poza
prawą krawędź ekranu, to w następnej klatce będzie rysowany po lewej jego stronie. Do współrzędnych
11
Wykład 14
Wstęp do grafiki 2D (moduł Allegro.pas)
pionowych tych rogów dodawana jest połowa wysokości ekranu, dzięki czemu animacja widoczna jest
w okolicach jego środka. Następnie zwiększana jest o 5 wartość zmiennej x i wyświetlana jest klatka
animacji zapisana na stronie aktywnej (wiersz 58). Po wykonaniu tych działań zwiększana jest wartość
indeksu tablicy modulo liczba jej elementów. Ponieważ tablica ta indeksowana jest od zera, to takie
działanie zapewnia, że wartość zmiennej i zmienia się cyklicznie od 0 do npages-1. Ostatnią czynnością
wykonywaną w pętli, poza sprawdzeniem warunku zakończenia, jest wskazanie nowej aktywnej strony
(wiersz 60). Po zakończeniu pętli repeat . . . until w pętli for zwalniana jest pamięć przydzielona na
strony.
1
program animate ;
2
3
uses allegro , crt ;
4
5
type
ball = record
x , y : longint ;
r : byte ;
dx , dy : s h o r t i n t ;
end ;
6
7
8
9
10
11
12
13
const
npages = 2 ;
14
15
16
var
ba : b a l l ;
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
p r o c e d u r e i n i c j a l i z u j ( width , h e i g h t : l o n g i n t ) ;
begin
i f not a l i n i t then
begin
w r i t e l n ( ’ Blad i n i c j a l i z a c j i b i b l i o t e k i A l l e g r o ! ’ ) ;
readln ;
halt (1) ;
end ;
i f not a l i n s t a l l k e y b o a r d then
begin
a l m e s s a g e ( ’ Blad i n i c j a l i z a c j i k l a w i a t u r y ! ’ ) ;
readln ;
halt (1) ;
end ;
a l s e t c o l o r d e p t h (32) ;
i f not a l s e t g f x m o d e (AL GFX AUTODETECT FULLSCREEN, width , h e i g h t , npages ∗ width , npages ∗
h e i g h t ) then
begin
a l m e s s a g e ( ’ Blad u s t a w i a n i a t r y b u g r a f i c z n e g o ! ’ ) ;
readln ;
halt (1) ;
end ;
end ;
40
41
42
43
44
45
46
47
48
49
procedure s e t b a l l ( var b : b a l l ) ;
begin
randomize ;
b . x:=random (AL SCREEN W s h r 1 ) +20;
b . y:=random (AL SCREEN H s h r 1 ) +20;
b . r :=20;
b . dx : = 1 0 ;
b . dy := −10;
end ;
50
51
52
53
54
55
56
57
58
59
p r o c e d u r e draw ( v a r b : b a l l ) ;
type
p a g e s t a b l e = a r r a y [ 0 . . npages −1] o f AL BITMAPptr ;
var
pages : p a g e s t a b l e ;
a c t i v e p a g e : AL BITMAPptr ;
i : byte ;
begin
f o r i := low ( p a g e s ) t o h i g h ( p a g e s ) do
12
Wykład 14
60
begin
p a g e s [ i ] : = a l c r e a t e v i d e o b i t m a p (AL SCREEN W, AL SCREEN H) ;
i f p a g e s [ i ]=NIL then
begin
al exit ;
w r i t e l n ( ’ Blad a l o k o w a n i a p a m i e c i na s t r o n y . ’ ) ;
readln ;
halt (1) ;
end ;
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
Wstęp do grafiki 2D (moduł Allegro.pas)
end ;
i := low ( p a g e s ) ;
a c t i v e p a g e := p a g e s [ i ] ;
repeat
a l c l e a r t o c o l o r ( active page , al makecol (0 ,0 ,0) ) ;
a l c i r c l e ( active page , b . x , b . y , b . r , al makecol (255 ,255 ,0) ) ;
al show video bitmap ( active page ) ;
b . x:=b . x+b . dx ;
b . y:=b . y+b . dy ;
i f ( b . x−b . r <=0) o r ( b . x+b . r>=AL SCREEN W) then b . dx:=−b . dx ;
i f ( b . y−b . r <=0) o r ( b . y+b . r>=AL SCREEN H) then b . dy:=−b . dy ;
i :=( i +1) mod npages ;
a c t i v e p a g e := p a g e s [ i ] ;
u n t i l ( a l k e y [ AL KEY ESC]<>0) o r ( a l k e y [ AL KEY Q]<>0) ;
f o r i := low ( p a g e s ) t o h i g h ( p a g e s ) do
a l d e s t r o y b i t m a p ( pages [ i ] ) ;
end ;
86
87
begin
i n i c j a l i z u j (1366 ,768) ;
s e t b a l l ( ba ) ;
draw ( ba ) ;
al exit ;
88
89
90
91
92
end .
Listing 7: Animacja - piłka
Program, który jest zaprezentowany w listingu 7 tworzy trochę bardziej skomplikowana animację. Rysuje on żółtą piłkę, która odbija się od brzegów ekranu zgodnie z regułą kąta padania i odbicia, znaną
z lekcji fizyki. Piłka ta będzie reprezentowana na ekranie jako okrąg. Aby program mógł wykonać przedstawione zadanie musi znać wszystkie niezbędne informacje dotyczące stanu piłki. Został w nim zatem
zdefiniowany typ rekordowy o nazwie ball. Pola tego typu rekordowego będą przechowywały wspomniane informacje. Pola x i y przechowują informacje o bieżącym położeniu środka piłki, pole r przechowuje
długość promienia piłki, natomiast pola dx i dy przechowują, odpowiednio składową poziomą i pionową
wektora prędkości piłki. Procedura initialize jest taka sama jak w programie z listingu 6. Procedura
setball, jako argument wywołania przyjmuje zmienną typu ball i odpowiedzialna jest za jej inicjalizację. Współrzędne środka piłki są losowane, ale w ten sposób, aby piłka całym swoim obwodem znajdowała
się na ekranie. Długość promienia piłki jest ustalana na 20 pikseli, natomiast składowa pozioma wektora prędkości na 10, a pionowa na -10. Ponieważ wartości bezwzględne obu składowych są równe, to
piłka będzie zderzała się z krawędzią ekranu pod kątem 45◦ i pod takim samym kątem zostanie odbita.
Składowa pionowa jest również ujemna, a pozioma dodatnia, więc do pierwszego odbicia piłka będzie się
poruszała się w górę i w prawo. Animacja piłki odbywa się w procedurze draw. Jej konstrukcja jest podobna do konstrukcji procedury draw z listingu 6. Zasadnicze różnice występują wewnątrz pętli repeat
. . . until. Wewnątrz niej kolor bieżącej strony jest ustawiany na czarny, rysowany jest okrąg według
danych zawartych w rekordzie typu ball i strona zostaje wyświetlona na ekranie (wiersze 73-75). Następnie wyznaczane jest położenie piłki w następnej klatce animacji. Do jej współrzędnych dodawane są
wartości składowej poziomej i pionowej wektora prędkości (wiersze 76 i 77). Potem program sprawdza,
czy w nowym położeniu piłka nie dotyka brzegiem którejś z poziomych (wiersz 78) lub pionowych (wiersz
79) krawędzi ekranu. Ponieważ ten test przebiega w obu przypadkach podobnie, to zostanie opisany tylko
ten z pierwszej instrukcji warunkowej. Wykrycia zderzenia z prawą krawędzią można dokonać odejmując
od współrzędnej poziomej środka okręgu jego promień i sprawdzając, czy otrzymana wartość jest równa lub mniejsza od zera. Zderzenie z lewą krawędzią wykrywa się dodając do tej współrzędnej długość
promienia okręgu i porównując otrzymaną wartość z szerokością ekranu. Jeśli któryś z tych testów da
odpowiedź pozytywną, to należy zmienić znak składowej poziomej prędkości piłki na przeciwny. Reszta
13
Wykład 14
Wstęp do grafiki 2D (moduł Allegro.pas)
procedury draw jest taka sama jak w programie z listingu 6. W bloku główny przed jej wywołaniem
wywoływana jest procedura set ball.
1
program e f e k t y ;
2
3
4
uses
allegro ;
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
p r o c e d u r e i n i c j a l i z u j ( width , h e i g h t : l o n g i n t ) ;
begin
i f not a l i n i t then
begin
w r i t e l n ( ’ Blad i n i c j a l i z a c j i b i b l i o t e k i A l l e g r o ! ’ ) ;
readln ;
halt (1) ;
end ;
i f not a l i n s t a l l k e y b o a r d then
begin
a l m e s s a g e ( ’ Blad i n i c j a l i z a c j i k l a w i a t u r y ! ’ ) ;
readln ;
halt (1) ;
end ;
a l s e t c o l o r d e p t h (32) ;
i f not a l s e t g f x m o d e (AL GFX AUTODETECT FULLSCREEN, width , h e i g h t , 0 , 0 ) then
begin
a l m e s s a g e ( ’ Blad u s t a w i a n i a t r y b u g r a f i c z n e g o ! ’ ) ;
readln ;
halt (1) ;
end ;
end ;
28
29
30
31
32
33
34
35
36
37
p r o c e d u r e ordraw ;
var
x , y : longint ;
begin
f o r x :=0 t o AL SCREEN W do
f o r y :=0 t o AL SCREEN H do
a l p u t p i x e l (AL SCREEN, x , y , a l m a k e c o l ( ( x o r y ) mod 2 5 6 , ( x o r y ) mod 2 5 6 , (
x o r y ) mod 2 5 6 ) ) ;
a l t e x t o u t c e n t r e e x (AL SCREEN, AL FONT, ’ o r ’ ,AL SCREEN W d i v 2 , AL SCREEN H d i v 2 ,
a l m a k e c o l ( 0 , 0 , 2 5 5 ) , −1) ;
end ;
38
39
40
41
42
43
44
45
46
47
p r o c e d u r e anddraw ;
var
x , y : longint ;
begin
f o r x :=0 t o AL SCREEN W do
f o r y :=0 t o AL SCREEN H do
a l p u t p i x e l (AL SCREEN, x , y , a l m a k e c o l ( ( x and y ) mod 2 5 6 , ( x and y ) mod
2 5 6 , ( x and y ) mod 2 5 6 ) ) ;
a l t e x t o u t c e n t r e e x (AL SCREEN, AL FONT, ’ and ’ ,AL SCREEN W d i v 2 , AL SCREEN H d i v 2 ,
a l m a k e c o l ( 2 5 5 , 0 , 0 ) , −1) ;
end ;
48
49
50
51
52
53
54
55
56
57
p r o c e d u r e xordraw ;
var
x , y : longint ;
begin
f o r x :=0 t o AL SCREEN W do
f o r y :=0 t o AL SCREEN H do
a l p u t p i x e l (AL SCREEN, x , y , a l m a k e c o l ( ( x x o r y ) mod 2 5 6 , ( x x o r y ) mod
2 5 6 , ( x x o r y ) mod 2 5 6 ) ) ;
a l t e x t o u t c e n t r e e x (AL SCREEN, AL FONT, ’ x o r ’ ,AL SCREEN W d i v 2 , AL SCREEN H d i v 2 ,
a l m a k e c o l ( 2 5 5 , 0 , 0 ) , −1) ;
end ;
58
59
60
61
p r o c e d u r e muldraw ;
var
x , y : longint ;
14
Wykład 14
62
63
64
65
66
67
Wstęp do grafiki 2D (moduł Allegro.pas)
begin
f o r x :=0 t o AL SCREEN W do
f o r y :=0 t o AL SCREEN H do
a l p u t p i x e l (AL SCREEN, x , y , a l m a k e c o l ( ( x∗y ) mod 2 5 6 , ( x∗y ) mod 2 5 6 , ( x∗y )
mod 2 5 6 ) ) ;
a l t e x t o u t c e n t r e e x (AL SCREEN, AL FONT, ’ ∗ ’ ,AL SCREEN W d i v 2 , AL SCREEN H d i v 2 ,
a l m a k e c o l ( 0 , 0 , 2 5 5 ) , −1) ;
end ;
68
69
70
71
72
73
74
75
76
77
procedure s i e r p i n s k i ;
var
x , y : longint ;
begin
f o r x :=0 t o AL SCREEN W−343 do
f o r y :=0 t o AL SCREEN H do
if
x and y = 0 then
a l p u t p i x e l (AL SCREEN, x , y , a l m a k e c o l ( 2 5 5 , 2 5 5 , 2 5 5 ) ) ;
end ;
78
79
80
81
82
83
84
procedure w a i t f o r k e y ;
begin
al clear keybuf ;
w h i l e a l k e y [ AL KEY SPACE]=0 do ;
end ;
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
begin
i n i c j a l i z u j (1366 ,768) ;
sierpinski ;
wait for key ;
ordraw ;
wait for key ;
anddraw ;
wait for key ;
xordraw ;
wait for key ;
muldraw ;
wait for key ;
al exit ;
end .
Listing 8: Tekstury
Dosyć często w grafice komputerowej zachodzi konieczność wypełnienia pewnego obszaru obrazu wzorcem (teksturą). Jeśli chcemy aby tło lub jego fragment miało ciekawe wypełnienie, to zamiast stosować
gotowe podprogramy możemy użyć prostszej techniki polegającej na wyliczeniu koloru danego piksela
na podstawie jego współrzędnych, przy użyciu takich operatorów, jak or, xor, not, and, +, -, *. Taka
możliwość została zademonstrowana w programie z listingu 8. Procedury xordraw, anddraw, ordraw
oraz muldraw wypełniają ekran monitora pikselami, w których każda składowa koloru wyliczana jest
odpowiednio jako: różnica symetryczna współrzędnej poziomej i pionowej piksela, iloczyn logiczny tych
współrzędnych, suma logiczna oraz zwykły iloczyn. Ponieważ wartości współrzędnych mogą być większe
od 255, to po wykonaniu każdej z tych operacji wynik jest dzielony modulo 256. Ostatnia z wymienionych procedur tworzy tzw. efekt mojry. Każda procedura wyświetla na środku ekranu symbol operatora
dzięki któremu powstał widoczny na ekranie efekt. Niestety, ze względu na wielkość domyślnej czcionki
modułu Allegro.pas napis ten jest słabo widoczny, dlatego w różnych procedurach jest on wpisywane
w różnych kolorach, aby zwiększyć jego widoczność. Ostatnia ze zdefiniowanych procedur, które tworzą
obraz (sierpinski) rysuje fraktal, którego nazwa pochodzi od nazwiska jego odkrywcy. Jest on nazywany trójkątem Sierpińskiego. Algorytm generowania takiego obrazu okazuje się być bardzo prosty: jeśli
iloczyn logiczny współrzędnych piksela jest równy zero, to taki piksel zaznaczamy na biało, w przeciwnym przypadku pozostawiamy go bez zmian (jest czarny). Zakresy liczników pętli for w tej procedurze
zostały tak dobrane, aby na ekranie ukazał się tylko jeden trójkąt Sierpińskiego. W programie jest zdefiniowana również procedura wait for key. Czyści ona bufor klawiatury i oczekuje w pustej pętli while
aż użytkownik naciśnie klawisz spacji.
15

Podobne dokumenty