RetroAge Artykuł, Poradnik techniczny Grę napiszę sobie…
ArtykułPoradnik techniczny

Grę napiszę sobie…

Loading

Nie tylko Święci garnki lepią i nie tylko programiści gry piszą. Programista ze mnie żaden, a kilka gier na „małe” Atari już stworzyłem. Dziś pokażę Wam jak taką małą prostą grę można stworzyć sobie samemu, nawet nie posiadając komputera Atari (wystarczy PC).

Jeśli nie dysponujemy komputerem Atari ze stacją dysków (a najlepiej z jakimś jej emulatorem – np. SIO2SD) pobieramy ->LINK<- program Atirra, który będzie dość dobrze udawał wymagany komputer, całkiem dobrze sprawując się w roli dev-kit’u. 8bitowe komputery Atari posiadają wbudowany interpreter języka BASIC, który przy użyciu komend znanych z języka angielskiego umożliwia tworzenie różnego rodzaju programów. Na potrzeby naszej gry użyjemy jednak bardziej rozbudowanej wersji interpretera pod nazwą Turbo Basic XL 1.5, która jest około 3 razy szybsza od podstawowej wersji, a dołączony kompilator potrafi przyspieszyć wykonywany program o dodatkowe 10-15 razy. Ponadto TBXL zawiera zestaw dodatkowych instrukcji ułatwiających tworzenie bardziej zaawansowanych programów. Obraz dyskietki z językiem możemy pobrać tu ->link<-

Podstawowa konfiguracja „Altirra”

  1. W menu górnym:

System -> Configure system…

Z listy wybieramy „System”, a następnie ustawiamy „Hardware type” na „65XE/130X”

Następnie z listy wybieramy „Devices”, klikamy na „Add” i z listy na samym dole wybieramy „Printer”

  1. W menu górnym:
    View->Printer Output (wyświetli nam okienko wirtualnej drukarki Atari)
  2. W menu górnym

File->Attach Disk->Drive 1 

Gdzie wybieramy plik z obrazem dyskietki Turbo Basic XL.

  1. Wciskamy Shift+F5 (reset) i czekamy na załadowanie się TBXL (niebieski ekran z napisem „READY”)

Zaczynamy programować

Na początku wypada się przywitać:

PRINT „HELLO WORLD”

Niektóre komendy języka BASIC posiadają także skróty, które warto opanować, dlatego też taki sam efekt osiągniemy pisząc:

PR. „HELLO WORLD”

Lub jeszcze krócej:

?”HELLO WORD”

Na raz możemy wprowadzić 3 linie instrukcji rozdzielanych dwukropkiem:

?”HELLO WORLD”:?”ALA MA KOTA”:?”JESTEM TBXX”

Przy użyciu komendy PRINT bardzo ważne jest używanie cudzysłowów.  Pomijając ten ważny znak:
? HELLO WORD

Zostaniemy poinformowani o błędzie w programie.

Inaczej będzie się miała sprawa w przypadku jednego wyrazu:
? HELLO

Gdzie zostanie wyświetlone „0” (zero), gdyż dany wyraz zostanie potraktowany, jako zmienna liczbowa. Zmienne liczbowe możemy porównać do ogólnodostępnych pojemników, w których możemy przechowywać pojedyncze liczby. Zmiennych możemy używać między innymi, jako różnego rodzaju liczników (liczba żyć, punkty, energia wykonywać na nich operacje matematyczne (dodawanie, odejmowanie, mnożenie, dzielenie, potęgowanie…)

PUNKTY=10:? PUNKTY: PUNKTY=PUNKTY+10:?PUNKTY

Możemy także mieszać wyświetlany tekst z wartością zmiennej:

? „PUNKTY:”;PUNKTY:? „PUNKTY:”,PUNKTY

W przypadku dołączania zmiennej za pomocą średnika wartość zostanie wyświetlona zaraz za tekstem, natomiast używając przecinka wartość zostanie wyświetlona 8 pozycji dalej.

Jak zapewne zauważyliście, wszystkie wpisywane komendy wykonywane są natychmiast po zatwierdzeniu ich klawiszem „Return” na Atari lub „Enter” na PC. Do tworzenia dłuższych programów Atari BASIC używa numeracji linii. Polecam zaczynać numerację od 10 z krokiem co 10 – ułatwia to późniejszą rozbudowę programów poprzez dopisywanie linii pomiędzy „dziesiątkami”

10 ? „HELLO WORLD”

Tym razem program nie został wykonany, możemy dopisać kolejną linię:

20 ?”TO JA TBXX”

Aby uruchomić program używamy komendy

RUN

Trochę już naśmieciliśmy na ekranie, aby wyczyścić ekran używamy komendy:

CLS

Aby wyświetlić wcześniej napisany program (ten z numerowanymi liniami) używamy komendy:

LIST

Komendy tej możemy użyć również z parametrami:

LIST 10

Wyświetli nam tylko linię 10 programu

LIST 10,20

Wyświetli nam linie od 10 do 20

LIST „P:

„wydrukuje” nam program na (wirtualnej) drukarce

Stworzony przez nas program możemy zapisać na dyskietce za pomocą komendy:
SAVE „D1:nazwapliku.rozszerzenie

Przy czym nazwa pliku może mieć maksymalnie 8 znaków a rozszerzenie 3

Zapisany program wczytujemy za pomocą:

LOAD „D1:nazwapliku.rozszerzenie

Komendą DIR wyświetlamy zawartość dyskietki, polecenie to jest skróconą formą DIR „D1:*.*” gdzie „gwiazdek” oraz „pytajników” możemy używać na podobnej zasadzie jak na PC

DIR „D1:A*.BAS”

Wyświetli nam wszystkie pliki zaczynające się na „A” z rozszerzeniem „BAS”

Pozostałe składniki zupy zwanej „grą”

DIM – polecenie tworzące jedno lub dwu wymiarowe tablice zmiennych liczbowych, oraz zmienne tekstowe. Przykładowo:
DIM A(9)
utworzy nam tablicę zmiennej A o pojemności 10 liczb (0-9). Taką tablicę możemy porównać do wiersza o długości 10 pól w arkuszu kalkulacyjnym.

DIM B(9,9)

Utworzy nam tablicę zmiennej B o pojemności 100 liczby. Taką tablicę możemy porównać do obszaru 10 wierszy na 10 kolumn w arkuszu kalkulacyjnym.

DIM A$(9)

Utworzy nam zmienną tekstową o długości 9 znaków. Nazwy zmiennych tekstowych zawsze kończymy znakiem $. W przeciwieństwie do zmiennych liczbowych wszystkie zmienne tekstowe musimy wcześniej utworzyć instrukcją DIM.

FOR, TO, STEP, NEXT – polecenia tworzące pętle o określonej liczbie powtórzeń.

FOR A=0 TO 9:?A:NEXT A

Wyświetli nam cyfry 0-9, pomiędzy „FOR/TO” a „NEXT” możemy wstawić różne instrukcje, które chcemy, aby zostały powtórzone. Wewnątrz pętli możemy używać zwiększającej się z każdym powtórzeniem o 1 zmiennej A. Dodając instrukcję STEP możemy regulować zmianę wartości zmiennej:

FOR A=0 TO 9 STEP 0.5:? A:NEXT A
Z każdym powtórzeniem wartość A będzie rosła o 0.5 czyli do 9 otrzymamy 20 powtórzeń.

RND – Losuje liczbę z zakresu 0-0.999999999999

?RND: A=RND:?A

INT – zwraca liczbę całkowitą z danej liczby lub zmiennej:
?INT(0.5):?INT(1.5):A=10.7:?INT(A)

IF, THEN – operacje warunkowe IF (jeśli) warunek THEN (to) wykonaj daną operację:
IF A>B THEN B=B+1

Jeśli A jest większe od B to zwiększ wartość B o 1

POSITION x,y  – wyznacza współrzędne miejsca na ekranie od którego zostanie wykonany kolejny rozkaz PRINT:

POSITION 10,10:PRINT „ALA”

Instrukcję możemy skrócić do postaci POS.

SETCOLOR a,b,c – instrukcja pozwalająca ustawić widoczne na ekranie barwy. W trybie tekstowym, w którym aktualnie pracujemy parametr „a” może przyjąć jedną z trzech wartości:

1 – odpowiada za kolor tekstu
2 – odpowiada za kolor tła

4 – odpowiada za kolor ramki

Parametr „b” odpowiada za wartość koloru (0-15), natomiast parametr „c” za jasność koloru (0-15): W trybie tekstowym tekst oraz tło zawsze będą miały ten sam kolor, różniąc się jedynie jasnością.

SETCOLOR 2,0,0:SETCOLOR 1,0,10

Instrukcję możemy skrócić do formy SET.

REPEAT, UNTIL – służą do tworzenia pętli kończących się spełnieniem danego warunku:

A=0:REPEAT :?A: A=A+1: UNTIL A=10

PAUSE x – funkcja służąca chwilowemu zatrzymaniu wykonywanego programu, na przykład w celu spowolnienia go. Dla wartości X=1 zatrzymanie trwa 1/50 sekundy. W celu wstrzymania programu na 1 sekundę wartość X ustalamy na 50

PAUSE 25

STICK, STRIG – zmienne systemowe zwracające parametry joysticka, odpowiednio wychylenia drążka i przycisku FIRE.

Wartości odczytywane poprzez STICK(0) oraz STRIG(0) odnoszą się do joysticka podpiętego do portu 1, a STICK(1) oraz STRIG(1) do joysticka podpiętego do portu 2.

REPEAT:?STICK(0),STRIG(0):UNTIL STRIG(0)=0

Powyższy kod będzie nam wyświetlał parametry wychyleń joysticka, oraz wartość „1” oznaczającą niewciśnięty FIRE. Pętla zostanie zakończona po wciśnięciu FIRE – STRIG(0)=0

NEW – instrukcja kasująca obecny w pamięci program w celu utworzenia nowego.

END – instrukcja kończąca wykonywany program.

PROC, ENDPRO, EXEC – instrukcje pozwalające na tworzenie procedur, czyli zestawów powtarzających się w programie instrukcji. Procedurę rozpoczynamy instrukcją

PROC nazwa
a kończymy instrukcją ENDPROC

Procedurę w programie wywołujemy instrukcją
EXEC nazwa

Po zakończeniu procedury program powróci do miejsca, z którego procedura została wywołana.

NEW

10 A=0:?A:EXEC DODAJ:EXEC DODAJ:?A:END

20 PROC DODAJ:A=A+1:ENDPROC

O pamięci słów kilka

Komputer, na który stworzymy naszą grę jest urządzeniem 8bitowym. Bity to takie przełączniki dwustanowe – mogące przyjmować wartości „0” lub „1” sterujące pracą komputera. Grupa 8 bitów tworzy bajt. Bajty mogą przyjmować jedną z 256 wartości (2 do potęgi 8) licząc od zera. Wartości poszczególnych bajtów możemy wyliczyć na podstawie tabelki:

Gdzie wartość liczbowa stanowi 2 do potęgi „numer bitu”, a wartość całego bajtu stanowi suma wyników mnożenia wartości liczbowej bitu oraz jego stanu. Na podanym przykładzie wartość bajtu wynosi, więc 170. Maksymalny rozmiar pamięci, jaki na raz jest wstanie obsłużyć procesor 8bitowy to 64kB czyli 65536 bajtów. Pamięć ta na Atari jest podzielona na 256 stron po 256 komórek, numerowanych kolejno 0-65535. Ilość dostępnej dla programu pamięci możemy sprawdzić za pomocą zmiennej systemowej FRE:
?FRE(0)

Jak widać do 65536 bajtów „trochę” brakuje – dość duża część pamięci zajmowana jest przez system oraz interpreter BASIC’a.

O rolah poszczególnych komórek „systemowych” możemy przeczytać w różnego rodzaju „mapach pamięci Atari”, a na potrzeby naszej gry poznamy kilka z nich.

Wartości poszczególnych komórek możemy zmieniać instrukcją POKE

POKE 710,0

Spowoduje wpisanie do komórki o numerze 710 wartości 0. Komórka ta odpowiada za kolor tła – możemy, więc instrukcji tej użyć zamiast SET.2,0,0

Zawartość każdej komórki możemy podglądnąć za pomocą instrukcji PEEK(nr. komórki)

?PEEK(710):A=PEEK(710):?A

Powyższy kod wyświetli nam zawartość komórki 710, następnie przypiszą tą wartość zmiennej A. Na końcu zaś wyświetli wartość zmiennej A.

Piszemy grę!

Uwaga! Przy tworzeniu nazw procedur oraz zmiennych warto zwrócić uwagę na ich długość – im dłuższa nazwa tym więcej zajmuje miejsca w pamięci. Z drugiej strony stosując zbyt krótkie nazwy, możemy się pogubić, która, za co odpowiada. Dlatego też polecam pisząc program, co jakiś czas drukować go na „wirtualnej drukarce”, a następnie wklejać go do edytora tekstowego dopisując komentarze, co dana zmienna oznacza, lub co wykonuje dana część programu.

Podobnie jak z długością nazw, warto uważać z ilością linii programu. Każda linia programu może mieć maksymalnie 3 wiersze, dlatego warto stosować skróty instrukcji. Jak można zauważyć na lewo od kursora znajduje się margines o szerokości 2 znaków. Za szerokość marginesu odpowiada komórka pamięci 82

?PEEK(82)

Jak widać znajduje się tam wartość „2”, dlatego też:

POKE 82,0

Likwiduje margines, przez co zyskujemy dodatkowe 6 znaków na linię programu.

Wpisujemy

NEW

I zaczynamy – nasza gra będzie prostą układanką z cyframi, które należy ułożyć w odpowiedniej kolejności na polu gry o rozmiarach 3×3

10 DIM A(2,2):DIM B(2,2):WYN=0

15 POKE 752,1

20 EXEC GENLVL:EXEC WYSPLA

25 POKE 18,0:POKE 19,0:POKE 20,0

30 REPEAT: EXEC JOY:EXEC ZEGAR:EXEC SPRWYN:UNTIL WYN=8:END

Deklarujemy tablice zmienny A oraz B 3×3 pola, zerujemy wartość zmiennej WYN. Komórka 752 odpowiada za widoczność kursora (wartość 0), każda inna wartość powoduje jego zniknięcie. Następnie wywołujemy 2 procedury, oraz kasujemy wartość zegara systemowego – komórki 18,19,20. Na końcu tworzymy pętlę wywołującą 3 procedury do czasu osiągnięcia przez zmienną WYN wartości 8, co zakończy nasz program.

1000 PROC GENLVL

1010   L=1:FOR Y=0 TO 2:FOR X=0 TO 2:B(X,Y)=L:L=L+1:NEXT X:NEXT Y

1020   FOR Y=0 TO 2:FOR X=0 TO 2

1030       REPEAT: XX=INT(RND(0)*3):YY=INT(RND(0)*3):UNTIL  B(XX,YY)>0  

1040       A(X,Y)=B(XX,YY):B(XX,YY)=0

1050     NEXT X:NEXT Y

1060   L=1:FOR Y=0 TO 2:FOR X=0 TO 2:B(X,Y)=L:L=L+1

1070       IF A(X,Y)=1 THEN A(X,Y)=0:XP=X:YP=Y

1080     NEXT X:NEXT Y

1090 ENDPROC

Procedura generująca układankę. Tablica zmiennej B zostaje zapisana cyframi 1-9. Następnie losujemy pola zmiennej B, których wartość przenosimy do kolejnych pól zmiennej A, zerując wartość pola w zmiennej B. Jeśli wylosowane pole B posiada wartość 0 losowanie zostaje powtórzone. Na końcu do tablicy B zostaje z powrotem wpisana poprawna kolejność cyfr, a w polu tabeli A, w którym znajdowała się cyfra 1 wstawiamy 0, które będzie oznaczało puste pole. Współrzędne pustego pola przepisujemy do zmiennych XP oraz YP.

1100 PROC WYSPLA

1110   CLS :SETCOLOR 2,0,0

1120   FOR X=0 TO 2:FOR Y=0 TO 2:POSITION X+19,Y+10:PRINT A(X,Y)

1130       IF A(X,Y)=0 THEN POSITION X+19,Y+10:? " "

1140     NEXT Y:NEXT X

1150 ENDPROC

Procedura wyświetlająca pole gry. Czyścimy ekran, ustawiamy kolor tła na „czarny”. Wyświetlamy wartości tabeli A w kwadracie 3×3. W miejscu wartości „1” wyświetlamy spację.

1200 PROC JOY

1210   IF STICK(0)=14 THEN EXEC DOL:ENDPROC

1220   IF STICK(0)=13 THEN EXEC GORA: ENDPROC

1230   IF STICK(0)=11 THEN EXEC PRAWO:ENDPROC

1240   IF STICK(0)=7 THEN EXEC LEWO:ENDPROC

1290 ENDPROC

Procedura badająca wychylenia joysticka oraz uruchamiająca procedury odpowiadające poszczególnym kierunkom.

1300 PROC GORA

1310   IF YP=0 ENDPROC

1320 A(XP,YP)=A(XP,YP-1):A(XP,YP-1)=0

1330 XM=0:YM=-1:EXEC RYSMOV

1340 ENDPROC

1350 PROC DOL

1360   IF YP=2 THEN ENDPROC

1370 A(XP,YP)=A(XP,YP+1):A(XP,YP+1)=0

1380 XM=0:YM=1:EXEC RYSMOV

1390 ENDPROC

1400 PROC LEWO

1410   IF XP=0 THEN ENDPROC

1420 A(XP,YP)=A(XP-1,YP):A(XP-1,YP)=0

1430 XM=-1:YM=0:EXEC RYSMOV

1440 ENDPROC

1450 PROC PRAWO

1460   IF XP=2 THEN ENDPROC

1470 A(XP,YP)=A(XP+1,YP):A(XP+1,YP)=0

1480 XM=1:YM=0:EXEC RYSMOV

1490 ENDPROC

Zestaw procedur odpowiadających za ruch „pustego pola”. Najpierw badamy czy w przypadku ruchu w danym kierunku zmienne XP oraz YP nie przekroczą dozwolonych wartości (0 i 2). Następnie zamieniamy miejscami wartość przesuwanego pola tabeli A oraz  „pustego miejsca”. W parametrach XM oraz YM zapisujemy wartość zmiany współrzędnych pustego pola. Na końcu wywołujemy procedurę wyświetlająca dokonane zmiany na ekranie.

1500 PROC RYSMOV

1510   POSITION XP+19,YP+10:PRINT A(XP,YP)

1520   XP=XP+XM:YP=YP+YM

1530   POSITION XP+19,YP+10:PRINT " "

1540   PAUSE 25

1550 ENDPROC

Procedura wyświetla nowe położenia cyfry z tabeli A. Następnie zostają zmienione współrzędne pustego pola, oraz gra zostaje wstrzymana na pół sekundy.

1600 PROC SPRWYN
1610   WYN=0 
1620   FOR X=0 TO 2:FOR Y=0 TO 2 
1630       IF A(X,Y)=B(X,Y) THEN WYN=WYN+1 
1640     NEXT Y:NEXT X 
1650   IF WYN=8 THEN EXEC GRAT 
1660 ENDPROC 

Procedura sprawdzająca zgodność poszczególnych pól tabeli A z odpowiadającymi im polami tabeli B. W przypadku zgodności wartość WYN jest zwiększana o 1. Po osiągnięciu wartości 8 gra zostanie zakończona.  

1700 PROC GRAT
1705 POSITION 19,10:? "1"
1710 POSITION 11,17:PRINT "GRATULACJE"
1715 POSITION 11,19:? "CZAS GRY:";G;":";M;":";S
1720 ENDPROC

Procedura kończąca grę – wyświetla brakującą cyfrę „1” w miejsce pustego pola, oraz aktualny czas gry.

1800 PROC ZEGAR
1810 T=256*PEEK(18)+PEEK(19):T=256*T+PEEK(20)
1820 S=INT(T/50):M=INT(S/60):S=S-60*M
1830 G=INT(M/60):M=M-60*G
1840 POSITION 11,19:? "CZAS GRY:";G;":";M;":";S
1850 ENDPROC

Procedura wyliczająca oraz wyświetlająca czas trwania gry na podstawie zegara systemowego. S – sekundy, M – minuty, G – godziny.

Dzięki nabytej wiedzy bez problemu powinniście również utworzyć stronę tytułową dla powyższej gry.

Autor

Komentarze

  1. Cisza w komentarzach, pewnie wszyscy programują 🙂 Pamiętam jak za dzieciaka trochę grzebałem w Basicu na małym Atari, tutaj z tego co widzę Turbo Basic sporo ułatwia pracę nad kodem

  2. Chyba dlatego, że mało kto tu zagląda, a informacji brak…
    Artek fajny, ale ma kilka niedociągnięć – choć dla początkujących wystarczy. Skoro piszemy w TB XL – warto skorzystać z RAND(liczba) zamiast RND. Dodatkowo warto korzystać z instrukcji DPEEK(adres) zamiast 256*PEEk(adres)+PEEK(adres+1) – mnożenie w procesorze ośmiobitowym kosztuje cenne ułamki sekund, a tu gotowa konstrukcja… Oczywiście w pojedynczych przypadkach jest to pomijalne, ale jak musimy już odczytać wiele komórek… Wbrew pozorom – po kompilacji też to ma znaczenie.
    Ogólnie – artek fajny, czekam na więcej 😉

Skomentuj Q@sor Anuluj pisanie odpowiedzi

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.