W grupie na Facebooku Commodore Plus/4 Węgry wspomniałem już pobieżnie, że zacząłem pracować nad portem The Pit na Plus/4.
Jako wprowadzenie, przytoczę to, co tam napisałem:
Do czego potrzebne są dźwięki, o których wspomniałem w poprzednim poście? Do mojego wielkiego ulubieńca, który był moim pierwszym spotkaniem z grami wideo, jeśli nie liczyć Videoton Teletennis.
W połowie lat osiemdziesiątych w klubie oficerskim osiedla wojskowego (!!!) z jakiegoś powodu stał automat arcade, na którym działała gra The Pit. Wrzuciliśmy do niego niezliczone pięcioforintówki z wizerunkiem Kossutha, aż w końcu odkryliśmy, że klucz do "sali", który trzeba było osobno prosić, jeśli chcieliśmy grać, jednocześnie otwierał też kasę automatu.
Oczywiście było to interesujące głównie do czasu, gdy nie miałem własnego komputera w domu, ponieważ ciągle powtarzająca się, choć z czasem przyspieszająca rozgrywka, nie była tak ekscytująca jak czekanie przed magnetofonem na załadowanie się aktualnej gry.
Mimo wszystko zrobiło to na mnie duże wrażenie i przypomniałem sobie o tym, gdy niedawno odkryłem, że Doug Turner, twórca Icicle Works (i innych wspaniałych gier kopania) około pięć lat temu wydał nowy rilez: The Pit.
Który nota bene jest zupełnie inną grą, z zupełnie inną wiedzą techniczną i poziomem, ale ma bezpośrednią paralelę. Inspiracją Douga, jego własnego Icicle Works, jest luźna interpretacja klona Boulder Dash w świąteczno-zimowym temacie. Z kolei inspiracją dla Boulder Dash był, według twórcy Petera Liepy, program BASIC autorstwa Chrisa Graya, który nie zachował się do współczesności. Jednak program Chrisa również nie był oryginalnym pomysłem - narodził się w salonie gier, podczas grania na automacie arcade. Tym automatem był The Pit.
Jest analogia? Widzimy podziemną przygodę w przekroju, jak w mrówczej farmie, kamienie spadają nam na głowy, i tak dalej, i tak dalej...
Co za piękne koło, prawda?
W ten sposób The Pit zachęcił mnie do stworzenia portu The Pit na Plus/4. Nie jest to zadanie naprawdę wymagające dla człowieka i techniki, ale biorąc pod uwagę, ile mam na to czasu i jak bardzo muszę wrócić do kodowania, jest to dla mnie idealne zadanie.
Załączyłem też trzy filmy, na wypadek gdyby ktoś nie znał gry. Pierwszy to oryginalna wersja Arcade, drugi to port na C64, a trzeci to przyszły port na Plus/4. Ten ostatni to tylko przedsmak, ponieważ jego kontynuacja jest jeszcze bardzo nieporadna.
Dobrze jednak ilustruje to, że wstawianie dźwięków cyfrowych byłoby silną przesadą (chyba że cyfryzujemy prostokąt, ale po co, prawda?), a efektów dźwiękowych też nie potrzeba zbyt wiele, dlatego nadal łamię sobie głowę nad rozwiązaniem tego (w krótkim fragmencie słychać TEDZakkera).
Jeszcze jeden powód, dla którego szukam wydajnego rozwiązania: chcę zmieścić się w 16K. Oryginalna wersja na C64 była kartridżowa, zhakowana wersja również działa w miejscu kartridża, mieści się wygodnie w 16K, z dużą ilością wolnego miejsca.
Aha, i jaki będzie tytuł? Oczywiście The Pit, bo taki jest oryginał, ale wymyślę coś, aby je odróżnić. Na przykład The Pit Arcade, lub coś podobnego.
Chociaż mam stosunkowo mało czasu, który mogę na to przeznaczyć (jak to zwykle bywa u dorosłych), projekt posuwa się do przodu i prawdopodobnie zostanie ukończony w przewidywalnym czasie.
Powodem, dla którego stało się to postem na blogu, jest to, że ze względu na swoją względną prostotę pojawiło się dość dużo specyficznych problemów do rozwiązania, nawet jeśli część z nich spowodowałem sam.
Po pierwsze, oryginalny program na C64 (przynajmniej ten, który do mnie dotarł) został zhakowany z kartridża i mieści się w 16K, z jeszcze sporą ilością wolnego miejsca. Dlatego jednym z celów stało się zmieszczenie wersji na Plus/4 również w 16K, a nawet uruchomienie jej na C16 (to nie to samo!).
Po drugie: oryginał zawiera mnóstwo sprite'ów (elementów działających sprzętowo, niezależnie od tła, takich jak gracz, wrogowie itp...), które na Plus/4 można zrealizować tylko programowo, co jest bardzo wymagające pod względem zasobów. Jednak charakterystyczne dla gry jest to, że większość z nich jest mała (1x1 znak) i stosunkowo rzadko spotykają się z tłem lub sobą nawzajem, więc maskowanie sprite'ów („czesanie” sprite'a i tła) jest prawie całkowicie zbędne.
Dlatego już na samym początku ustalono, że sprite'y będą działać w następujący sposób:
1. Gracz: postać o rozmiarze 1x1 znaku, która teoretycznie mogłaby być wyświetlana na masce sprite'a 2x2 znaki. Jak możemy to uprościć?
- pozostaje ruch pikselowy, ale można się zatrzymać tylko na granicy znaku. To trochę ułatwia grę, ponieważ w oryginale celowanie w granice pikseli było szczególnie irytujące.
- Gracz, poruszając się w piasku, zawsze kopie przed sobą obszar o wielkości jednego znaku - ale z tego powodu zawsze porusza się po pustym, już wykopanym miejscu. Dlatego nie spotyka się z tłem, nie trzeba maskować.
- Podnosząc skarb, znowu nie ma potrzeby maskowania - ponieważ go podnosi, pozostawiając tutaj również tylko puste miejsce.
- Zderzając się z wrogiem, nie trzeba maskować, ponieważ ŚMIERĆ! ŚMIERĆ! ŚMIERĆ!, co w oryginalnej grze ma dziwną, splątaną animację. Można to przedstawić za pomocą stałych faz, a do tego w granicach znaku.
- Nie musi maskować pocisku, ponieważ wystrzeliwuje go przed siebie i ten oddala się od niego.
- Jeśli skała spada, sytuacja jest taka sama jak z wrogiem, nie ma dodatkowej pracy.
- Co więcej, nasz gracz nie porusza się po skosie, porusza się tylko w kierunku pionowym LUB poziomym, oba jednocześnie nie są możliwe.
Z powyższych powodów ruch gracza i jego wyświetlanie są znacznie uproszczone. Praktycznie musi poruszać się przed pustym miejscem, mógłby być nawet wyświetlany znak po znaku, ale wtedy jego ruch byłby bardzo kanciasty. W celu uzyskania ruchu pikselowego opracowano następujące rozwiązanie:
- Jeśli gracz znajduje się w granicach znaku, po prostu umieszczamy go jako jeden znak, do którego kopiujemy aktualną fazę animacji.
- Poruszając się na boki, od aktualnej pozycji W LEWO a nie, W PRAWO otrzymuje dodatkowy znak, w tych dwóch przesuwamy go w kierunku poziomym o 1-7 pikseli, 8. dzieje się już jeden znak dalej.
- Podczas ruchu w górę i w dół dzieje się to samo, ale drugi znak pojawia się jeden wiersz poniżej aktualnej pozycji.
- Nie nadpisujemy tym tła, ponieważ przed ruchem sprawdzamy, co znajduje się w czterech możliwych kierunkach i pozwalamy iść dalej tylko w przypadku pustego miejsca. Jeśli w którymś kierunku piasek jest przeszkodą, ale gracz chciałby się poruszyć, kopiemy - wtedy będzie tam puste miejsce, może iść dalej.
- Ponieważ obszar gry jest otoczony nieprzekraczalnymi przeszkodami poza wejściem, z powyższych powodów nie ma potrzeby sprawdzania minimalnej i maksymalnej pozycji, które można przemierzyć, ponieważ przeszkody zatrzymają gracza, zanim wyjdzie poza obszar, który można przemierzyć. Wejście (i wyjście obok czołgu) jest otoczone znakami $00, które są tak samo puste jak przejezdne znaki $20, ale blokują dalszy ruch gracza.
Dodatkowym bonusem jest układ obszaru gry, przez który prawa strona ekranu nie jest dostępna dla gracza. Małe wyjaśnienie:
Ekran Commodore Plus/4 ma rozmiar 25 wierszy na 40 znaków, w pikselach 320x200. Pozycję pionową (0-199 lub szesnastkowo $00-$C7) można opisać jednym bajtem, ale pozioma już nie, jej wartość (jeśli cały ekran jest dostępny) może wynosić $0000-$013F, co można przechowywać tylko na dwóch bajtach. Nawet jeśli pozycja sprite'a nie może być $013F / $C7, ponieważ wtedy byłby widoczny tylko jeden piksel w lewym dolnym rogu.
Ale w przypadku The Pit nie ma takiego problemu, korzystając z oryginalnego poziomu, gracz (a tym samym także wrogowie), uwzględniając również jego rozmiar, może iść maksymalnie do pozycji $D0 / $B8. To już można przechowywać na jednym bajcie. Różnica nie wydaje się znacząca, ale w ten sposób oszczędzamy pamięć dzięki krótszemu programowi, a także czas procesora na niepotrzebne obliczenia z +1 bajtem.
2. Wrogowie: prawie wszystko, co dotyczy gracza, dotyczy również ich. Dodatkowym bonusem jest to, że ponieważ bardzo rzadko spotykają się ze sobą, nie trzeba się tym głębiej zajmować. Zderzając się ze sobą, po prostu się nadpiszą, co w ferworze gry nie będzie zauważalne, a więc i irytujące.
3. Pociski: są dwa rodzaje pocisków, gracza i czołgu. Ten ostatni będzie miał prostą, znakową reprezentację, nie wymaga więcej. Pocisk gracza również nie będzie bardziej skomplikowany, ponieważ porusza się przed pustym tłem, zderzając się z przeszkodą, ulega zniszczeniu (= po prostu znika), a zderzając się z wrogiem, znika razem z nim.
4. Bomby w dolnej jaskini: Ich wyświetlanie jest podobne do pocisku, a do tego poruszają się tylko w jednym kierunku, więc można je obsłużyć jeszcze prościej.
5. Potwór w basenie z kwasem, czołg, UFO: nie mają tak naprawdę roli w grze. Wszystkie trzy można wyświetlić za pomocą prostej, znakowej historii, poruszając się na minimalnym obszarze. Tylko czołg otrzyma animację z przesuniętymi o pół fazy znakami z powodu stosunkowo długiej, prosto przebytej drogi.
Aby zmieścić się w 16K, nie musiałem podejmować zbyt dużych wysiłków, ponieważ sama gra nie jest zbyt skomplikowana.

Zestaw znaków The Pit w obecnym stanie. To nie ostateczna wersja, fazy animacji jeszcze z niego wyjdą.
(Nawiasem mówiąc, do grafiki bazowałem głównie na wersji C-64, ale niektóre szczegóły przejąłem z oryginalnej, arcade'owej wersji)

Dźwięk UFO, 45 bajtów
Większość powyższych oszczędza oczywiście tylko minimalną ilość miejsca, ale aby zrozumieć, dlaczego te okruchy są również ważne, wróćmy teraz do powyższego, pozornie bez powodu napisanego na zielono tekstu - jego rozmiar to około 4500 znaków, czyli około 4,4 kB.
Ta mała zielona część tekstu cztery razy z rzędu już nie zmieści się w 16K!
Jeszcze jedna mała rzecz na koniec: podczas rozwoju często używam swego rodzaju prowizorycznych metod debugowania, które można później łatwo i szybko usunąć z ostatecznej wersji. Wtedy na pasywnym, nieistotnym obszarze ekranu podczas działania programu można doskonale wyświetlić informacje, które pomagają w debugowaniu, a nawet samym procesie rozwoju. Takie widać również na tym zrzucie ekranu:

"Tryb debugowania" w The Pit
Dobrze widoczne są z jednej strony klasyczny "pomiar czasu rastera", kolor ramki ustawiony na początku przerwania i przywrócony na końcu, z drugiej strony na dole ekranu w rzędzie pikselowe współrzędne X i Y gracza, pikselowe współrzędne X i Y w obrębie znaku, znakowe współrzędne X i Y, licznik kopania (0-7, a odpowiednio @-G) oraz aktualny kierunek ruchu (poziomy, pionowy lub - w tym przypadku - żaden).
W tabeli High Score zamiast nazw u góry znajdują się przeszkody otaczające gracza w czterech kierunkach, poniżej aktualny kierunek ruchu.
Ponadto w trybie debugowania wspomniany wyżej pusty, ale różniący się od wolnego obszaru znak $00, czyli @, nie jest pusty, zawiera pojedynczy piksel, aby można go było odróżnić od naprawdę pustego, przejezdnego znaku $20 (spacja). Dlatego widać na przykład, że obok UFO gracz może wyjść tylko w dół.
Ponadto w trybie debugowania można wyłączyć (i tutaj jest wyłączony) ruch wrogów, spadanie skał, strzelanie czołgu itd... Może to bardzo pomóc, gdy trzeba znaleźć jakiś błąd, którego źródło jest jeszcze całkowicie niejasne.
Cały ten tryb debugowania można wykomentować kilkoma ; przed zapisaniem gotowej wersji, a podczas zapisywania można go pominąć. W naszym przypadku - właśnie ze względu na cel 16K znajduje się powyżej $4000, więc nie przeszkadza również w dostępnej pamięci.
Cóż, na razie tyle, następnym razem - mam nadzieję - zgłoszę się z gotowym The Pit.