EKSPERYMENTY Z LOSEM, CZYLI RYBY Jest taki rodzaj programów komputerowych, które czësto wykorzystujâ funkcje losowe. Jaki? Oczywiôcie blanker -- program do oszczëdzania monitora. Po pewnym ustalonym czasie zamiast nieruchomego obrazu (mogâcego uszkodziê kineskop) pojawia sië programik, zapalajâcy gwiazdki, malujâcy fraktale itd. Poprzedni artykuî na ten temat dotyczyî zmieniania losowo efektów akustycznych -- mowy. Teraz przedstawië próbë takiego dziaîania na animowanym obrazie. Stanisîaw Wësîawski Na wstëpie muszë zaznaczyê, ûe nie jest to przykîad wyrafinowanego programowania. Wybraîem znowu Director z dwóch wzglëdów, po pierwsze juû kilkakrotnie byîa o tym mowa, po drugie Director operuje prostâ odmianâ BASIC-a, îatwâ do przeniesienia np. do AMOS-a. Samym AMOS-em moûna oczywiôcie podany przykîad wykonaê o wiele efektowniej, uûywajâc np. bobów. Jednak opis takich procedur byîby, o ile sië orientujë, o wiele bardziej obszerny. Sâ zresztâ w Redakcji lepsi fachowcy w tej dziedzinie. Zaîoûenie byîo takie: Po ekranie pîywajâ ryby. Jedna duûa i jedna maîa. Ryby pîywajâ raz w lewo, raz w prawo, ale nigdy nie wiadomo, kiedy znajdâ sië naprzeciwko siebie. Jeûeli taka sytuacja nastâpi, duûa ryba zje maîâ. Mogâ tam jeszcze byê inne ryby, ale gra toczy sië miëdzy wymienionymi dwiema. Na poczâtek wykonaîem planszë z rybami w postaci rysunku IFF, podzielonego za pomocâ opcji GRID na pola 160 x 80 pikseli. Rysunek przedstawia takâ planszë, zrobionâ niejako "na zapas". Jest tam wiëcej rysunków niû wykorzystaîem w projekcie. W pierwszym rzëdzie duûa ryba pîynie w lewo. Trzy kolejne rysunki na prawo to fazy machania ogonem. Poniewaû jednak powiëkszaîo to bardzo skrypt programu, postanowiîem zrezygnowaê z tej moûliwoôci. Drugi rzâd to ryba pîynâca w prawo. Trzeci i czwarty rzâd -- fazy otwierania pyska w lewo i prawo. Piâty i szósty to maîa ryba i îawice jako dodatek do programu. Komendy SETBLACK I FADE sâ typowe dla Directora i na dobrâ sprawë moûna by je opuôciê. Innymi typowymi komendami jest zestaw LOAD.., przeznaczony do îadowania gîównego ekranu i ekranów dodatkowych. Wybraîem najprostszâ moûliwâ sytuacjë i komenda LOAD "df1:ryba.1a" îaduje rysunek "czystego" ekranu jako ekran gîówny. Druga komenda LOAD 1,"df1:ryba.1" îaduje do bufora (numer 1) wîaôciwy ekran z rybami "do wycinania". Teraz wystarczy coô wyciâê z ekranu nr 1 komendâ BLIT i bez wspomnianych kiedyô komend DISPLAY i BLITDEST wycinek znajdzie sië na gîównym ekranie. Jest to doôê prymitywne (brak podwójnego buforowania itd.), ale bardzo skuteczne, a co najwaûniejsze, doôê krótkie. Duûâ rybë wycinam (i wklejam jednoczeônie) komendâ: BLIT 1,1,1+Pionowa,x,y,158,78 BLIT 1 to materiaî do wycinania. Kolejne dwie cyfry to X równe 1 i Y równe "1+pionowa". Zmienna PIONOWA moûe byê równa 80, czyli tyle, ile wysokoôci ma kaûde okienko obrazka ryby. To znaczy, ûe wycinam z miejsca o parametrach 1, 81, a jeûeli zmienna jest równa zero, to z miejsca o parametrach 1,1. Oznacza to, ûe raz wycinam drugâ rybë (pîynie w prawo), a raz pierwszâ (pîynie w lewo). X i Y to parametry miejsca wklejania wycinka. X zmienia sië od -160 do +640, poniewaû dotyczy górnego lewego naroûnika wycinka. Zmienna Y jest losowana, na przykîad tak (znak "?" odpowiada w Directorze funkcji Random): y=?3*80 Znaczy to, ûe moûemy oczekiwaê trzech liczb -- 0, 1, 2, a po pomnoûeniu przez 80 otrzymamy 0, 80 lub 160. Wynika z tego, ûe ryba moûe siëgaê najwyûej do pierwszej linii ekranu (zerowej) lub (w dóî) maksimum do 240 (160 + 80). Liczby 178 i 78 okreôlajâ dîugoôê i wysokoôê wycinania. Ryba jest wycinana z pewnym "naddatkiem" i nakîadana jak Brush-Replic, to znaczy razem ze swoim tîem. Ryba pîynâca w prawo napotka w pewnym momencie granicë, wyznaczonâ przez zmiennâ BRZEG, i musi zawróciê. Trzeba zmieniê jej rysunek, czyli wycinanie kawaîka o 80 pikseli niûej (ryba obrócona w prawo) i zmieniê kierunek ruchu. Mniej wiëcej w tym momencie zaczynajâ sië komplikacje. Program coraz bardziej sië wikîa i trzeba bardzo uwaûaê na nazwy zmiennych i podprogramów, ûeby nie zaplâtaê sië w programie. Kierunkiem ruchu steruje zmienna ZWROT, która raz jest równa -1, a raz +1. Skok, o jaki porusza sië ryba, jest zmiennâ U, pomnoûonâ przez zmiennâ ZWROT. Mamy X + U x ZWROT, co daje raz wartoôê malejâcâ, a raz rosnâcâ. Moûe to wyglâdaê zawile, ale nie ma na to rady. Algorytm przedstawia sië wobec tego nastëpujâco: Ryba startuje z prawej strony. Jeûeli jej pozycja X nie jest mniejsza od lewej krawëdzi ruchu -- BRZEG, to od X odejmuje sië U, co daje nowâ wartoôê X i stawia rybë na nowej pozycji bardziej w lewo. Postëpuje sië w ten sposób tak dîugo, dopóki X nie bëdzie mniejsze od BRZEG. Jeûeli to nastâpi, program wykona skok do podprogramu ZWROTY, gdzie losuje sië nowy "pas ruchu" -- zmiennâ Y, i przestawia zmiennâ ZWROT (mnoûâc jâ przez -1). Program rozpoznaje kierunek ruchu ryby gîównie przez sprawdzanie zmiennej ZWROT. Jeûeli jest ujemna, wszystko jest skierowane na ruch w lewo, jeûeli dodatnia -- odwrotnie. Analogicznie postâpiîem przy uruchomieniu drugiej ryby. Startuje ona z przeciwnej strony, wobec tego pierwsze odwoîanie do zmiennych X, ZWROT i BRZEG musi byê przeciwne. Pierwsza ryba to ciâg, zaczynajâcy sië od rozkazu "DO duzaRyba", a druga startuje od "DO maîaRyba". Wszystkie nazwy zmiennych maîej ryby, które nie sâ wspólne z duûâ, majâ dodanâ cyfrë 2 do nazwy. Np. X i X2, ZWROT i ZWROT2 itd. Trochë to pomaga poîapaê sië w tekôcie skryptu. Najwaûniejszâ jednak sprawâ jest skonstruowanie fragmentu programu, który wyîapuje miejsce spotkania ryb i uruchamia jego konsekwencje. Oczywiôcie uchwycenie momentu spotkania realizujemy funkcjâ IF, która musi sprawdziê, czy nastâpi jednoczeônie szereg warunków. Pierwszym warunkiem jest zgodnoôê wysokoôci ruchu ryb, czyli Y musi byê równe Y2. Odlegîoôci X i X2 muszâ byê wiëksze od zera, aby "moment" byî widoczny. Róûnica odlegîoôci powinna byê taka, aby ryby spotkaîy sië prawie dokîadnie pyskami. W Directorze realizuje sië to operatorem "&", zastëpujâcym znany z innych jëzyków "AND". Teraz moûna skierowaê program do linii, która wyôwietli kolejne fazy "îykania" i sprawë mamy czëôciowo z gîowy. Pozostaje problem -- co zrobiê z poîkniëtâ rybâ? Program bowiem pracuje trochë jak zegarek i regularnie realizuje wszystkie kolejne fazy ruchu, wszystkich "aktorów". Nie moûna tak po prostu "uômierciê" ryby. Najprostszym wyjôciem jest w tym momencie zmiana wysokoôci Y2 -- maîej ryby. Wyrzucamy jâ poza ekran (powyûej) i "poîkniëta ryba" znika z ekranu, pîynâc w rzeczywistoôci przez chwilë dalej w tym samym kierunku. Dziëki temu nie trzeba tworzyê dodatkowych linii programu i zakîócaê normalnego rytmu jego dziaîania. Teraz moûna tylko zapeîniê resztë ekranu (poniûej x = 240) innym ruchomym obrazem. Wprowadziîem tam îawice ryb z dolnej czëôci podstawowej planszy. Ryby, dla uîatwienia, pîynâ w jednym kierunku (w prawo), ale dla urozmaicenia ruchu, po kaûdym dotarciu do krawëdzi zmienia sië losowo rodzaj îawicy -- duûa lub maîa. Poniewaû nie wystëpuje tu problem kolizji obiektów, îawice poruszajâ sië ze zmiennâ szybkoôciâ -- z losowo zróûnicowanymi wielkoôciami "skoku". Po uruchomieniu caîoôci moûna obserwowaê namiastkë ûycia na ekranie. Ryby pîywajâ, co jakiô czas jedna zjada drugâ, po czym akcja pîynie dalej. Gdyby nie to, ûe chciaîem wykonaê moûliwie krótki zapis programu, moûna by wzbogaciê akcjë o wiele dodatkowych atrakcji. To znaczy zrobiê machanie ogonem duûej ryby co kilka klatek i np. zjadanie maîych ryb z îawicy, a nie tylko pojedynczych osobników. Moûna wprowadziê efekt ucieczki maîych ryb co jakiô czas i dodatkowo element pogoni. Miîoônicy znanego modelu typu "lisy i króliki" mogâ wprowadziê element uzaleûnienia liczby duûych ryb od iloôci pokarmu (maîych ryb) i odwrotnie. Pole do zabawy jest olbrzymie. Wreszcie trzeba powiedzieê, ûe ryby wybraîem tylko dlatego, ûe naturalnie wyglâda tu pusty ekran tîa. Przy bardziej ambitnym zaîoûeniu moûna zrobiê coô w rodzaju znanej gry >Sim Life<. Co sië zmieni w ôrodowisku naturalnym, jeûeli wprowadzimy losowo takie czynniki, jak zwierzëta, ich pokarm, naturalni wrogowie i klimat? I jeûeli jeden czynnik ma wpîyw na inne? Niepostrzeûenie wchodzimy w temat ekologii, co jest osobnym zagadnieniem, ale warto sië nad tym w wolnej chwili zastanowiê.