Piszemy DEMOPoprzedni odcinek cyklu zakończyliśmy przykładem pokazującym gracza na ekranie. Mogliśmy zobaczyć go bez żadnych problemów, gdyż jego kolor byt różny od jednolitego koloru tła. W przypadku, gdy na ekranie znajduje się więcej elementów graficznych w różnych kolorach, to należy określić, czy i które kolory mają być przesłonięte obiektem i odwrotnie. Nazywamy to priorytetem - kolor o wyższym priorytecie będzie zasłaniał kolor o priorytecie niższym. Priorytety
Ustawienie jednego z tych bitów ustawia kolory w kolejności przedstawione) w tabelce (pionowe kolumny). Ustawienie kilku bitów ustala nieokreślony priorytet. Gdy obszary o tym samym priorytecie się pokrywają to uzyskują kolor czarny. W rejestrze Gtiactl ważną rolę odgrywają także bity 4 i 5. Ustawienie pierwszego z nich nadaje pociskom kolor określany przez Colpf3, dzięki czemu uzyskuje się piątego gracza. Ponieważ gracz ten jest połączeniem czterech pocisków to każda jego część może być poruszana oddzielnie. Natomiast bit piąty oddziaływuje na priorytety. Jego ustawienie spowoduje, że gdy nastąpi nałożenie dwóch graczy to ich część wspólna otrzyma kolor powstały w wyniku operacji logiczne) ORA na dwóch kolorach tych graczy. Kolizje
Cyfry umieszczone w kolumnach Kolor1-Kolor3 oznaczają, który bit rejestru zostanie ustawiony po wykryciu kolizji, np. jeśli gracz "zderzy się" z kolorem 2 ekranu to w rejestrze Colp2pf zostanie ustawiony bit 1. Kolejne osiem rejestrów określa kolizje obiektów:
Rejestry kolizji można tylko odczytywać, gdyż przy zapisie komórki pamięci o tych adresach pełnią inną funkcję. Z tego wynika, że nie mogą być kasowane. Jest to możliwe dzięki istnieniu rejestru Hitclr ($D01E). Wpisanie dowolnej wartości do tego rejestru skasuje wartości w rejestrach kolizji. Tak więc procedura wykrywania kolizji powinna rozpocząć się sprawdzeniem pewnych zdarzeń w rejestrach kolizji, natomiast zakończyć wpisaniem dowolnej wartości do Hitclr, aby umożliwić odczytanie kolejnych kolizji. Vdelay
Po przeczytaniu tylu suchych informacji należy się czytelnikom kilka przykładów. Przykład 1Program Equ $8800 List_mem Equ %00000110 List_err Equ %00000101 Code_mem Equ %00010000 Code_dsk Equ %00100000 Cdtma2 Equ $0228 Cdtmv2 Equ $021A Colpm0s Equ $02C0 Dmactls Equ $022F Gtictls Equ $026F Hposp0 Equ $D000 Sizep0 Equ $D008 Pmbase Equ $D407 Pmcntl Equ $D01D Random Equ $D20A Help Equ $F0 Help_2 Equ $F2 Pm_addr Equ $A000 Play_1 Equ Pm_addr+$0400 Play_2 Equ Pm_addr+$0500 Play_3 Equ Pm_addr+$0600 Play_4 Equ Pm_addr+$0700 Opt List_err+Code_mem Org Program Jsr Init_pl LdxProgram rozpoczyna się skokiem do procedury Init_pl, gdzie zerowany jest obszar grafiki PMG, ustawiany jest Pmbase, kolory, pozycje i rozmiary graczy. Na koniec trzy najważniejsze rejestry Dmactls, Gtictls i Pmcntl otrzymują wartości umożliwiające ukazanie się obiektów. Program główny zawiera jeszcze tylko inicjację przerwania Timer 2. Procedura przerwania rozpoczyna się od etykiety Timer_2. Zmienna Licznik określa przerwy pomiędzy kolejnymi losowaniami punktów umieszczanych na ekranie. Dlatego też punkty są w dużych odległościach od siebie i nie zasłaniają całkowicie obrazu. W każdym obiegu procedury przerwania licznik jest zmniejszany. W przypadku, gdy nie jest zerem to dane grafiki PMG są przepisywane o jeden bajt w dół. Natomiast gdy Licznik osiągnie wartość zero to po drodze losowana jest nowa wartość dla Licznika i losowane są punkty poprzez ustawienie losowo wybranego bitu w odpowiednim bajcie grafiki PMG. W programie wykorzystaliśmy rejestr Random ($D20A), z którego odczytywane są wartości losowe. Przykład 2Program Equ $8800 List_mem Equ %00000110 List_err Equ %00000101 Code_mem Equ %00010000 Code_dsk Equ %00100000 Cdtma2 Equ $0228 Cdtmv2 Equ $021A Charset1 Equ $E000 Colpm0s Equ $02C0 Dmactls Equ $022F Gtictls Equ $026F Hposp0 Equ $D000 Pmbase Equ $D407 Pmcntl Equ $D01D Sizep0 Equ $D008 Adres Equ $F0 Licznik Equ $F2 Pomoc Equ $F3 Pomoc_2 Equ $F5 Tekst_Ad Equ $F7 Pm_adr Equ $A000 Opt List_err+Code_mem Org Program Ldx #$00 Txa L0 Sta Play_1,x Sta Play_2,x Sta Play_3,x Sta Play_4,x Inx Bne L0 Ldx Program główny czyści obszar PMG, następnie inicjuje grafikę PMG i przerwania Timer'a 2 podobnie. Jak w poprzednim przykładzie. Poza tym program ustawia adres tekstu (Tekst_ad) i Licznik. Na ekranie znajduje się czterech graczy w poczwórnej szerokości. Gracze umieszczeni są w tych samych miejscach ekranu obok siebie i ich pozycja nic zmienia się. Procedurę przerwania można podzielić na dwie części. Jedna z nich tworzy litery w obszarze PMG, druga przesuwa je. Ważną rolę odgrywa tu Licznik. Gdy ma wartość zero to tworzone jest pięć nowych liter. Piąta litera nie jest wyświetlana, lecz bierze udział w trakcie przesuwania tekstu. Dane dla kolejnej litery pobierane są ze standardowego zestawu znaków Atari - Char - set1 ($E000). Adres danych znaku oblicza procedura Oblicz_adresy. Jak wiemy, każdy znak to 8 bajtów. Jednak gracz o wysokości ośmiu linii ekranu jest za mały i byłby zbyt "spłaszczony", zwłaszcza przy poczwórnej szerokości obiektów. Dlatego też każdy bajt matrycy znaków powielany jest osiem razy w pamięci PMG. Tak dzieje się z wszystkimi pięcioma literami. Po tej operacji cztery litery pojawiają się na ekranie. Płynne przesuwanie tekstu realizowane jest przy niezerowej wartości Licznika. Przesuw płynny zmusza do przesuwania bitów poszczególnych bajtach pamięci PMG. Do tego najlepiej nadaje się rozkaz ASL procesora, dlatego że bit 7 przesuwanego znaku umieszczany jest w znaczniku C procesora. Jeśli jest on ustawiony, to należy go odtworzyć w kolejnym graczu. Nasz program realizuje to przy użyciu rozkazów BCC i ORA (okolice etykiety L3). Nawiasem mówiąc zamiana BCC na BCS daje ciekawy efekt. Bitowe przesuwanie liter powtarzane jest 8 razy (i oczywiście uzależnione jest od Licznika). Przykład 3Program Equ $8800 List_mem Equ %00000110 List_err Equ %00000101 Code_mem Equ %00010000 Code_dsk Equ %00100000 Cdtma2 Equ $0228 Cdtmv2 Equ $021A Colpm0s Equ $02C0 Dmactls Equ $022F Gtictls Equ $026F Hitclr Equ $D01E Hposp0 Equ $D000 Hposp2 Equ $D002 Hposp3 Equ $D003 Hposm0 Equ $D004 Jstick0 Equ $0278 Kolm0p Equ $D008 Nmien Equ $D40E Pmbase Equ $D407 Pmcntl Equ $D01D Random Equ $D20A Sizep0 Equ $D008 Trig0s Equ $0284 Poz_0x Equ $0600 Poz_1x Equ $0601 Poz_0y Equ $0602 Poz_1y Equ $0603 Pm_0x Equ $0604 Pm_1x Equ $0606 Pm_0y Equ $0606 Pm_1y Equ $0607 Dod_m0 Equ $0608 Dod_m1 Equ $0609 Cyfry0 Equ $060A Cyfry1 Equ $0610 Score Equ $0616 Kier_0 Equ $061A Kier_1 Equ $0618 M0 Equ $061C M1 Equ $061D Przyc0 Equ $061E Przyc1 Equ $061F Pomoc Equ $F0 Pomoc2 Equ $F2 Pomoc3 Equ $F4 Adr_pl Equ $A000 Opt List_err+Code_mem Org Program Jmp Start * WYSWIETLA PUNKTY * (X-NR GRACZA) Punkty Txa Pha Lda #$60 Sta Pomoc2 Lda Aby umożliwić dokładniejszą analizę programu podamy znaczenie zmiennych i stałych w nim użytych. Kolejne zmienne 3 umieszczone są w kolejnych komórkach 8 stronie. Poz_0x do Poz_1y okreslają pozycje obu postaci (pionowe i poziome). Podobnie Pm_0x do Pm_1y określają pozycję wystrzelonych nabojów. Dod_m0 i Dod_m1 określają jaką wartość dodawać do pozycji X pocisków. Kolejne dwie zmienne Cyfry0 i Cyfry1 są sześciobajtowe. Każdy bajt to liczba z przedziału od 0 do 9 oznaczająca kolejną cyfrę licznika punktów gracza. Score to czterobajtowa zmienna określająca ile punktów należy dodać każdemu z graczy w najbliższej przyszłości. W każdym obiegu przerwania dodawany jest jeden punkt, dopóki Score każdego gracza nic wyzeruje się. Takie zwiększanie punktów powoduje, że dodane punkty nie pojawiają się natychmiast. Dużym ułatwieniem od strony programowej jest zapisanie w pamięci najpierw dwóch młodszych bajtów punktów graczy, a potem starszych, nie tak jak zwykle: młodszy/starszy gracza 0 i młodszy/starszy gracza 1. Dzięki takiemu rozwiązaniu odwołania do młodszego lub starszego bajtu punktów gracza o numerze w rejestrze X stają się prostsze, gdyż bajt młodszy określa etykieta Score, starszy natomiast Score+$02 (rejestr X zawiera oczywiście numer gracza). Kolejne dwie zmienne Kier_0 i Kier_1 określają kierunek odpowiedniego gracza. Gracz zwrócony w lewo wygląda zupełnie inaczej, niż gracz obrócony w prawo. I te właśnie zmienne decydują o tym skąd pobierać dane do wyglądu postaci. M0 i M1 to zmienne logiczne. Wartość $01 umieszczona w nich oznacza, że pocisk wystrzelony przez odpowiedniego gracza znajduje się na ekranie i porusza się w stronę określoną przez kierunek gracza. Za każdym obiegiem przerwania sprawdzane są przyciski joystick'ów obu graczy. Zmienne Przyc0 i Przyc1 przyjmują wartość 1 w momencie naciśnięcia przycisków joystick'ów, co umożliwia poruszanie się pocisków i jednocześnie zapobiega podwójnemu odczytaniu wartości z komrórek odpowiadających za stan przycisków joystick'ów. Program główny inicjuje PMG i Timer'a 2 oraz ustawia wartości początkowe zmiennym. Cała gra wykonywana jest przez przerwanie Timer'a 2, który wywołuje inne procedury. Procedura zaczynająca się od etykiety Punkty wyświetla punkty graczy pobierając dane dla wyglądu odpowiedniej cyfry z tablicy Znaki. Kolejna procedura, Dodaj, sprawdza, czy nie pozostały do dodania jakieś punkty graczom i jeśli tak, to zwiększa odpowiednio Liczniki i zwiększa Score. Jest ona wywoływana w każdym obiegu przerwania. Procedura Pokaz_gr umieszcza na ekranie graczy w odpowiednich pozycjach. Podobne zadanie pełni procedura Pokaż dla pocisków, odwrotne zadanie - Zmaz. Procedury wykorzystują maski bitowe Zapalenie i Zgaszenie. W samej procedurze przerwania Timer'a 2 nowa dla nas jest tylko obsługa joystick'a. Joystick na cztery zasadnicze położenia: w lewo, w prawo, do przodu i wstecz. Osiem bitów rejestru PortA ($D300) przedstawia położenie dwóch joystick'ów wg tabeli:
Normalnie wszystkie bity są ustawione. Zmiana położenia joystick'a powoduje wyzerowanie odpowiedniego bitu (lub bitów). Zazwyczaj jednak korzysta się z rejestrów cieni Jstick0 ($0278) i Jstick1 ($0279). W pierwszym z nich cztery najmłodsze bity określają położenie joystick'a 0, natomiast rejestr drugi określa położenie joystick'a 1 (też bity 0-3). Do wykrywania stanu przycisków joystick'ów służą rejestry GTIA o nazwach Trig0 ($D010) i Trig1 ($D011) oraz ich cienie Trig0s ($0284) i Trig1s ($0285). Skasowanie bitu 0 oznacza, że przycisk został naciśnięty. Gra może uprzyjemnić pisanie programów w Basic'u, pod warunkiem, że w programie głównym umieści się rozkaz PLA procesora. W następnym artykule zajmiemy się dźwiękiem Atari. Dla tych, którzy preferują dane homogenizowane, przedstawiamy poniżej ostatni przykład z "Piszemy DEMO" w postaci danych szesnastkowych. Należy je połączyć ze Zgrywusem+ z TA 2/92, co pozwoli uzyskać program maszynowy, zdatny do uruchomienia bezpośrednio pod kontrolą DOS lub COS. 1000 REM *--------------------------* 1002 REM : DEMO-GRA : 1004 REM : R. Bielecki, T. Bielak : 1006 REM : (c) 1992 Tajemnice ATARI : 1008 REM *--------------------------* 1010 DATA ffff00885f8a4cd1898a48a960 1020 DATA 85f2a90aa0a6e001d004a910a0 1030 DATA a785f084f3a90685f1a000b1f0 1040 DATA 480a85f4680a0a0a38e5f485f4 1050 DATA 9848a6f4a000bd008c91f2e8c8 1060 DATA c006d0f518a5f2690885f268a8 1070 DATA c8c006d0d268aa60bd1606d005 1080 DATA bd1806f02e8a48e001d002a206 1090 DATA a000fe0a06bd0a06c90ad00ba9 1100 DATA 009d0a06e8c8c006d0eb68aade 1110 DATA 1606bd1606c9ffd003de180660 1120 DATA 8a481869a485f1bd020685f0bd 1130 DATA 00069d00d0bd1a06aae001d002 1140 DATA a209a000bd3c8c91f0e8c8c00a 1150 DATA d0f568aa60bd0606a8b900a33d 1160 DATA 538c9900a360bd0606a8b900a3 1170 DATA 1d558c9900a360a200bd78024a 1180 DATA b00c48bd0206c922f003de0206 1190 DATA 684ab00c48bd0206c9d4f003fe 1200 DATA 0206684ab01148bd0006c93df0 1210 DATA 08a9009d1a06de0006684ab011 1220 DATA 48bd0006c9bdf008a9019d1a06 1230 DATA fe000668208988bd8402f008a9 1240 DATA 009d1e064c6b89bd1e06d03aa9 1250 DATA 019d1e06bd1c06f00320b588a9 1260 DATA 019d1c06bd02061869059d0606 1270 DATA bd000648bd1a06a8b9578c9d08 1280 DATA 0668c001d0031869069d04069d 1290 DATA 04d020c388bd1c06f02518bd04 1300 DATA 067d08069d04069d04d0c931f0 1310 DATA 0cc932f008c9ccf004c9cdd008 1320 DATA a9009d1c0620b588e8e002f003 1330 DATA 4cd388a200bd08d0dd598cd016 1340 DATA 18ad0ad2293f69017d16069d16 1350 DATA 069003fe180620b58820508820 1360 DATA 0388e8e002d0d7a9018d1a028d 1370 DATA 1ed060a2008a9d00a39d00a49d 1380 DATA 00a59d00a69d00a7e8d0eea9a0 1390 DATA 8d07d4a203bd4f8c9dc002a900 1400 DATA 9d08d0ca10f2a232a0c68e02d0 1410 DATA 8c03d0a23e8e2f02a201a0038e 1420 DATA 6f028c1dd0a203a9009d1c06ca 1430 DATA 10faa2139d0a06ca10faa2018e 1440 DATA 1a06ca8e1b06a246a0aa8e0006 1450 DATA 8e02068c01068c0306a2002003 1460 DATA 88208988e8200388208988a2d1 1470 DATA a0888e28028c2902a9408d0ed4 1480 DATA 4cc889008c5a8c367f41417f36 1490 DATA 367f00000000307949494f0636 1500 DATA 7f49494900367f08087830064f 1510 DATA 49497930064f49497f36367f40 1520 DATA 404000367f49497f36367f4949 1530 DATA 7930001838103cfc38182c0018 1540 DATA 1c083c3f1c1834000f965858fc 1550 DATA f3030cfe020201e002e1020088 Tomasz Bielak
Rafał Bielecki |