Pożyteczne procedury

Pisanie programu w języku Action! polega przede wszystkim na umiejętnym zestawieniu odpowiednich procedur. Każdy szanujący się programista musi więc mieć bogatą bibliotekę tych procedur. Aby nie wymyślić wszystkiego od nowa, otwieramy kącik, w którym będziemy publikować proste procedury. Liczymy także na wsparcie przez Czytelników.

Rozpoczniemy od dwóch prostych funkcji matematycznych — ABS i SGN. Pierwsza z nich zwraca wartość bezwzględną podanej liczby. Wystarczy więc tylko sprawdzić znak argumentu i zmienić go na przeciwny, jeśli jest ujemny.

INT FUNC Abs(INT k)

IF k<0 THEN RETURN(-k) FI

RETURN(k)

Funkcja SGN zwraca wartość określającą znak podanego argumentu. Jeżeli argument jest ujemny, to wynikiem będzie liczba -1, a gdy: ■ ■ -l Dla 3-gumentu zerowego rezultatem będzie oczywiście zero

INT FUNC Sgn(INT k)

IF k<0 THEN RETURN(-1)

ELSE

IF k>0 THEN RETURN(1)

FI

RETURN(O)

Korzystając z pokazane] wyżej zasady możemy zbudować funkcję odczytującą poziomy ruch joysticka. Przy ruchu w lewo funkcja zwróci wartość -1, w prawo +1, a w położeniu neutralnym 0 Można tu zastosować dwa warianty rozważania W pierwszym aktualne położenie joysticka odczytujemy korzystając z bibliotecznej funkcji Stick(n), gdzie n jest numerem joysTicna (C lub 1). Ponieważ jest to dokładnie to samo co Peek($278+n), można zastosować bezpośredni odczyt wartości z rejestru PAWI Użyjemy w tym celu dwuelementowej tablicy. Samo ustalenie kierunku ruchu jest bardzo proste. w rejestrze joysticka przy ruchu w lewo mogą się znaleźć wartości 9, 10 lub 11, przy ruchu w prawo 5. 6 lub 7, zaś w położeniu środkowym (w poziomie) — 13, 14 lub 15. Ostatecznie procedura ma następującą postać:

INT FUNC HStick(BYTE Joy)

BYTE ARRAY port(2)=$278

IF port(Joy)<8 THEN RETURN(1)

ELSEIF port(Joy)>>12 THEN RETURN(0)

FI

RETURN(-1>

Nieco bardziej skomplikowana będzie funkcja odczytująca pionowe położenie joysticka. W odpowiednim rejestrze odczytamy dla ruchu w górę wartości 6,10 lub 14, a dla ruchu w dół 5, 9 lub 13, a w położeniu neutralnym 7,11 lub 15. zauważmy jednak, ze w każdym z tych przypadków ważne są tylko dwa najmłodsze bity rejestru. Jeżeli uwzględnimy tylko te bity, to uzyskamy odpowiednio wartości 1 2,1 i 3. Teraz trzeba to wpisać do procedury i gotowe:

INT FUNC VStick(BYTE Joy)

BYTE ARRAY port(2)=$278

BYTE 1

i=port(Joy)&3

IF i=1 THEN RETURN(1) ELSE

IF i=3 THEN RETURN(0)

FI

RETURN(-1)

Kolejne procedury będą dotyczyły różnych operacji graficznych. Zaczniemy od narysowania prostokąta. Jako parametry wejściowe podamy współrzędne dwóch przeciwległych wierzchołków. Ich położenie względem siebie jest w tym przypadku nieistotne. Ponieważ maksymalna wartość współrzędnej pionowej wynosi 191 (tryb ósmy bez okna tekstowego), to wystarczy zmienna typu BYTE Dla współrzędnej poziomej Konieczna jest jednak zmienna typu CARD, gdyż w trybie ósmym może ona osiągnąć wartość 319. Do wykreślenia samego prostokąta potrzeba tylko cztery linie, więc procedura jest bardzo prosta. Dodatkowo zastosujemy w niej piąty parametr, który określi kolor rysowanej ramki.

PROC Frame(CARD x1 BYTE y1

CARD x2 BYTE y2,c)

oolor=c Plot(x1,y1)

DrawTo(x2,y1) DrawTo(x2,y2)

DrawTo(x1,y2) DrawTo(x1,y1)

RETURN

Mając już prostokąt będziemy chcieli wypełnić go kolorem. W takim przypadku nie wystarczy prosta zamiana ostatniej procedury DrawTo na Fili. Procedura wypełniania zawarta w systemie operacyjnym Atari zawsze wypełnia linię obrazu w prawo od narysowanego punktu. Musimy więc sprawdzić, czy lima ograniczająca wypełniane pole znajduje się z prawej strony, a jeśli nie, to zamienić wartości współrzędnych poziomych. Druga instrukcja warunkowa IF uniemożliwia błędne zamalowanie obrazu, gdy obie pionowe linie się pokrywają. Ponadto kolo: do wypełniania nie musi być taki sam jak kolor do rysowania Wprowadzimy więc dodatkowy parametr, który pędzie go definiował.

PROC Box(CARD xl BYTE y1

CARD x2 BYTE y2,c,f)

CARD aux

BYTE fcolor=$2FD

color=c fcolor=f

IF x1>x2 THEN

aux-x1 x1=x2 x2=aux FI

Plot(x1,y1) DrawTo(x2,y1)

DrawTo(x2,y2) DrawTo(x1,y2)

IF x1<>x2 THEN Fill(x1,y1) FI

RETURN

Teraz przyszedł czas na narysowanie okręgu. To zadanie jest znacznie bardziej skomplikowane, nie będziemy więc rozważać go szczegółowo. Wystarczy powiedzieć, że zastosowany został algorytm rysowania okręgu w ośmiokierunkowej symetrii zmodyfikowany przez usunięcie funkcji pierwiastkowania, której nie ma w Action!. Wyprowadzenie tego algorytmu było opisane w "Komputerze" 9/86. Gotowa procedura jest pokazana poniżej. Jej parametrami wejściowymi są współrzędne środka okręgu, jego promień i kolor, którym będzie wykreślony.

PROC Circle(CARD sx BYTE sy,r,c)

INT dx,dy,dxy,pdx,pdy

color=c

dx=0 pdx=r pdy=0

DO

dy=dx+pdy+pdy+1

dxy=dy-pdx-pdx+1

Plot(sx+pdx,sy+pdy)

Plot(sx-pdx,sy+pdy)

Plot(sx+pdx,ay-pdy)

Plot(sx-pdx,sy-pdy)

Plot(sx+pdy,sy+pdx)

Plot(sx-pdy,sy+pdx)

Plot(ax+pdy,sy-pdx)

Plot(sx-pdy,sy-pdx>

dx=dy pdy==+l

IF Abs(dxy)+0<Abs(dy) THEN

dx-dxy pdx==-1

FI

UNTIL pdy>pdx OD

RETURN

W ten sposób zaczynając od matematyki doszliśmy do rysunku. Korzystając z powyższych procedur można napisać prosty program graficzny obsługiwany przy pomocy joysticka. Ale to już samodzielnie — teraz Ty, Czytelniku.

 

Wojciech Zientara