Fairtris — a fair implementation of Classic Tetris®

1

@furious programming: To na razie tyle w sprawie testów - dalej będę grał dla rozrywki.
Zrzut_05.PNGZrzut_06.PNG

0

Może zmiany tła co ileś linii?

0
pstmax napisał(a):

@furious programming: Pełna mobilizacja, co do grafiki i będzie naprawdę super gierka - idealna na sprzęt w biurach administracji państwowej […]

Bardziej bym wolał, aby gierka rozniosła się po szkołach, tak jak dawno temu np. DSJ. ;)

Pytanie: Co to RNG Type ?

Typ generatora klocków. Na razie zaimplementowany jest jedynie generator RANDOM, który wypluwa zupełnie losowe klocki, nie patrząc na powtórki czy długi brak któregoś klocka. Ten generator jest jedynym zaimplementowanym, więc zmiana opcji RNG na inną niczego nie zmienia. Generatory będę implementował na samym końcu.


7-BAG to wariant najprostszy — jeden zestaw siedmiu klocków (po jednym każdego rodzaju), który będzie mieszany i po kolei klocki z niego będą wybierane. On jest najłatwiejszy, bo pomiędzy losowaniami klocka danego typu nie może być przerwy dłuższej niż 12 klocków. Klocek danego typu może być wylosowany maksymalnie dwa razy z rzędu.

FAIR to algorytm opracowany przeze mnie — w skrócie będzie to zestaw zestawów klocków (jeszcze nie wiem dokładnie ilu 7x8, 7x9, 8x8 lub 8x9 — wybiorę po testach każdego wariantu). Sekwencje klocków wypluwane przez niego będą mocno zbliżone do oryginalnego, NES-owego algorytmu, ale w odróżnieniu od niego, odstęp pomiędzy powtórnym wylosowaniem klocka nie będzie mógł być większy niż 12 klocków (oryginalny jest na tyle niedorozwinięty, że przerwa pomiędzy powtórnym wylosowaniem danego klocka może sięgać kilkadziesiąt klocków, a gdy używa się strzałki w dół, to powtórka może w ogóle nie nastąpić). I to samo z losowaniem jednego klocka kilka razy pod rząd — oryginalny może wypluwać pod rząd nawet 7-8 razy, a FAIR maksymalnie 3.

Oryginalny algorytm i mechanika gry, przez swój niedorozwój uniemożliwiają granie perfekcyjnie (tylko kasowanie tetrisów, aż do poziomu 29), a gra logiczna, której nie można przejść perfekcyjnie, nadaje się do kosza. Poza tym granie w taką jest cholernie irytujące, skoro z góry wiadomo, że gra prędzej czy później uwali gracza.

CLASSIC to algorytm wzięty 1:1 z oryginalnej gry. RANDOM to to co jest obecnie, czyli losowa papka — dla hardkorowców.

2
pstmax napisał(a):

Może zmiany tła co ileś linii?

Nie, tego nie będę robił. Gra będzie głównie przeznaczona dla obecnej społeczności skupionej wokół klasycznego Tetrisa, dlatego powinna wyglądać tak jak oryginał. Ciemny motyw jest jedynie dodatkiem, bo byłem ciekaw jak będzie wyglądać gra w mniej starodawnym i krasiastym stylu. Ten oryginalny motyw nie jest aż tak zły, ale błyskanie tła trochę wkurza, dlatego w ciemnym motywie miga znacznie mniejsza powierzchnia tła (poza tym miga słabiej).

Skórka CLASSIC musi być taka jaka jest (głównie chodzi o tło podczas grania), dlatego że Fairtris ma być kompatybilny z narzędziem zwanym Maxout Club, pozwalającym na pojedynkowanie się w klasycznego Tetrisa (grając na prawdziwej konsoli lub emulatorze). A żeby był w stanie rozpoznać obraz i liczniki, moja gierka musi wizualnie udawać oryginał. :D


A tutaj moja testowa gra — region NTSC z poziomu 0:

top out.png

summary.png

Szału nima, bo grając testowałem różne rzeczy, ale i tak spoko. ;)

2

Nowa wersja do testów — Fairtris 1.0.0.15 (beta)

Obecnie skupiam się na dokończeniu głównej mechaniki gry i tę najprawdopodobniej mam już dopiętą na ostatni guzik. Wczoraj przysiadłem do implementacji pierwszego z generatorów — padło na 7-BAG. Długo mi zajęło pisanie jego kodu, ale chciałem go porządnie przetestować, tak aby mieć 100% pewności, że działa prawidłowo. No i na to wychodzi, że działa elegancko.

CHANGELOG:

  • Czas pomiędzy przyklejeniem się klocka do stosu a pojawieniem się nowego u góry stosu (co zwie się ”lock delay”) został dopasowany do wersji oryginalnej — ten mechanizm nie jest nigdzie opisany szczegółowo, dlatego musiałem analizować grę w emulatorze, klatka po klatce. Czucie gry teraz jest znacznie bliższe oryginałowi, co jest bardzo ważne.

  • Zaimplementowałem obsługę hard-dropu — wciskając strzałkę w górę, klocek od razu przykleja się do stosu, bez względu na to na jakiej wysokości się znajduje. Opuszczanie klocków w ten sposób daje dodatkowe punkty — dostaje się tyle, ile wierszy różnicy było pomiędzy pozycją klocka przed opuszczeniem a pozycją końcową (maksymalnie 19).

  • Naprawiłem obliczanie liczby punktów soft-dropu (czyli opuszczenia klocka strzałką w dół) — oryginał ma zepsute kalkulacje tych punktów i dostaje się bardzo dziwne wartości, natomiast moja wersja poprawnie liczy te punkty (dostaje się tyle, ile wierszy opadł klocek). Tak wymyśliło to Nintendo i tak zrobili (choć zabugowali te obliczenia), a więc i ja tak zrobiłem.

  • Dodałem zapamiętywanie trzech najlepszych wyników i ich zapis do plików konfiguracyjnych — trzy najlepsze wyniki są wyświetlane w menu PLAY. Biorąc pod uwagę, że każdy region i każdy typ generatora pozwalają na zdobywanie mniejszej lub większej liczby punktów, prowadzone są osobne listy wyników — łącznie 32 listy (8 regionów * 4 generatory).

  • Zaimplementowany jest pierwszy sensowny randomizer — 7-BAG. Jego działanie jest proste — bierze się zestaw wszystkich klocków (siedmiu), po jednym każdego typu, miesza zawartość plecaka i wyciąga klocki po kolei, aż do opróżnienia plecaka. A potem znów bierze się siedem klocków, miesza i wyciąga klocki po kolei. Randomizer sprawiedliwy, ale zbyt przewidywalny — choć gra się fajnie.

  • Poprawiłem odtwarzanie dźwięków. Każdemu efektowi dźwiękowemu nadałem priorytet — jeśli chce się odtworzyć nowy dźwięk, to poprzednio odtworzony albo musi się odtworzyć do końca, albo priorytet nowego musi być większy od poprzedniego. Mechanizm prosty, a skuteczny. Na razie mam do dyspozycji tylko jeden kanał audio, dlatego priorytety są istotne — po użyciu SDL ten problem zniknie.

  • Zmieniłem nazwę generatora losowego z RANDOM na UNFAIR — w końcu generuje on zupełnie niesprawiedliwe sekwencje, nie patrząc na to ile razy dany klocek był losowany i jak dawno danego klocka nie wylosował. Zdarza się, że jedne klocki losuje wielokrotnie razy częściej, a to uniemożliwia normalną grę — a to niesprawiedliwe, dlatego nowa nazwa bardziej pasuje. ;)

I to w sumie wszystko. Dziś będę implementował kolejne generatory, bo zostały jeszcze dwa — CLASSIC, czyli odpowiednik oryginalnego (w końcu rozgryzłem jak on działa) oraz FAIR, czyli moja propozycja, generująca sprawiedliwą sekwencję klocków, ale z drugiej strony będącą wyzwaniem dla gracza.



Na razie wykorzystywane jest renderowanie software'owe, dlatego możecie się spodziewać lagów, choć nie są to lagi ”silnika” gry. Klatki nie są gubione — sprawdziłem to programowo i podczas gry każda klatak wykonuje się w zadanym czasie. Problemem tutaj jest Windows, bo system nie nadąża z odmalowywaniem zawartości okna i najwyraźniej czasami pomija bieżące odmalowywanie aby skupić się na kolejnym (co wygląda jak lag). Jest to zauważalne na wysokich poziomach — od 16 wzwyż, może od 19 wzwyż (trzeba mieć wprawne oko).

Ale tym się nie przejmujcie — po użyciu SDL ten problem zniknie. Jeśli jest to dla was zauważalne i wam to przeszkadza to sugeruję wyłączyć dźwięki i zmniejszyć rozmiar okna. Obsługę SDL-a dorzucę na sam koniec, kiedy już będę pewny, że cała mechanika gry działa zgodnie z oczekiwaniami. A na razie jest jak jest. :D

1
furious programming napisał(a):
  • Naprawiłem obliczanie liczby punktów soft-dropu (czyli opuszczenia klocka strzałką w dół) — oryginał ma zepsute kalkulacje tych punktów i dostaje się bardzo dziwne wartości, natomiast moja wersja poprawnie liczy te punkty (dostaje się tyle, ile wierszy opadł klocek). Tak wymyśliło to Nintendo i tak zrobili (choć zabugowali te obliczenia), a więc i ja tak zrobiłem.

Ale jesteś pewien, że to bugi? "Dziwne wartości" mogą jednak mieć uzasadnienie, choćby na poziomie na przykład generowania losowych liczb.

2
Silv napisał(a):

Ale jesteś pewien, że to bugi?

Tak, to na pewno błąd — a bugów w oryginale jest masakrycznie dużo.

W książeczce dołączanej do kartridża (a także w wielu artykułach na temat Tetrisa dla konsoli NES) jest wyraźnie napisane, że liczba punktów za soft-drop jest równa liczbie opuszczonych wierszy. Jeśli jednak włączy się grę i od razu po pojawieniu się klocka wciśnie i przytrzyma strzałkę w dół, klocek opadnie łącznie 18 wierszy (lub 19, jeśli to longbar), a punktów dostanie się maksymalnie 14. Ewidentnie ktoś miał problem z liczeniem. ;)

Oryginalna wersja ma mnóstwo błędów i aż dziw bierze, że tak prostą grę z tak prymitywną mechaniką można było aż tak zepsuć. A jeszcze większy dziw bierze, że tak zepsutą i irytującą swoją niesprawiedliwością grę używa się od 11 lat w scenie kompetetywnej, w tym na turniejach takich jak Mistrzostwa Europy (CTEC) i Mistrzostwa Świata (CTWC).

0

Tak z ciekawości - który system obrotu zaimplementowałeś? https://tetris.fandom.com/wiki/Category:Rotation_Systems
Planujesz może możliwość ich zmiany w ustawieniach? Trochę mnie zdziwiło jak napisałeś że z obrotami nie było problemu, natomiast miałeś problem z opadaniem - odwzorowanie poprawnie takiego SRS czy ARS zajmuje trochę czasu, a inne systemy obrotów nie pozwalają na żadne sztuczki i nie są chyba już używane w żadnych mistrzostwach?

furious programming napisał(a):

W książeczce dołączanej do kartridża (a także w wielu artykułach na temat Tetrisa dla konsoli NES) jest wyraźnie napisane, że liczba punktów za soft-drop jest równa liczbie opuszczonych wierszy. Jeśli jednak włączy się grę i od razu po pojawieniu się klocka wciśnie i przytrzyma strzałkę w dół, klocek opadnie łącznie 18 wierszy (lub 19, jeśli to longbar), a punktów dostanie się maksymalnie 14. Ewidentnie ktoś miał problem z liczeniem. ;)

tu https://www.reddit.com/r/Tetris/comments/b5u8li/nes_1989_tetris_how_many_points_do_you_get_for/ jest opisane dokładnie jak liczy oryginał - wychodzi że max to 15 punktów za klocek, jeśli się trzymasz oryginału to może to też warto odwzorować

0
obscurity napisał(a):

Tak z ciekawości - który system obrotu zaimplementowałeś?

Nintendo Rotation System — w końcu robię klona wersji z NES-a.

Planujesz może możliwość ich zmiany w ustawieniach?

Nie, dlatego że wersja na konsolę NES jest jedyną klasyczną odsłoną, w którą gra się na scenie kompetetywnej i którą Fairtris ma imitować. Nie biorę pod uwagę żadnej innej wersji Tetrisa i żadnej mechaniki istniejącej w innych odsłonach.

Wyjątkiem jest tutaj implementacja hard-dropu oraz kumulowanie punktów soft-dropu — pierwszego mi brakuje w oryginale, a ten pozwala na lepsze (szybsze) speedruny, natomiast drugie jest dodatkiem ode mnie (nagroda w postaci dodatkowych kilkunastu/kilkudziesięciu punktów za szybkie granie).

Trochę mnie zdziwiło jak napisałeś że z obrotami nie było problemu […]

Bo system rotacji jest naprawdę łatwy do zaimplementowania. Co prawda wersja z konsoli NES nie posiada np. ”wall kicków” (wstępne odsunięcie klocka od ściany, jeśli po rotacji jego pozycja byłaby niepoprawna), ale to też jest bardzo łatwo zaimplementować — szczególnie w moim kodzie.

Natomiast wersja którą klonuję, nie wspiera tych idiotycznych, nierealnych spinów, ani ślizgania się klocków po ich postawieniu (co istnieje w wersjach nowoczesnych wersjach), dlatego implementacja nie była wymagająca.

[…] natomiast miałeś problem z opadaniem […]

Miałem, dlatego że algorytm odpowiadający za swobodny spadek oraz za soft-drop nie jest opisany w całości. Wszystko jest opisane prócz tego w którym miejscu ma być inkrementowany timer dla swobodnego spadku, a także tego, w którym miejscu ma być zerowany licznik punktów za opadanie. Testowanie przycisków też jest niejasno opisane.

Sam znalazłem odpowiednie miejsce na te instrukcje i wszystko zaczęło działać prawidłowo, dopiero po wielu testach. A później zmieniłem co nieco, tak aby odblokować kumulowanie punktów za przyspieszone opadanie. I jest to fajna funkcja.

[…] a inne systemy obrotów nie pozwalają na żadne sztuczki i nie są chyba już używane w żadnych mistrzostwach?

Na turniejach stacjonarnych używa się konsol NES, telewizorów CRT i oryginalnych kartridży, więc ma się do dyspozycji tylko to co istniało w oryginale. Na innych turniejach i ligach online, możliwe jest też używanie emulatorów, ale ROM musi być oryginalny. Dozwolone jest jedynie użycie kodów Game Genie — jednego dzięki któremu licznik punków nie zatrzymuje się na 999999 i drugiego, który blokuje animację rakiety po zakończeniu gry (bo jej nie da się przerwać, a zabiera z 15 sekund).

tu https://www.reddit.com/r/Tetris/comments/b5u8li/nes_1989_tetris_how_many_points_do_you_get_for/ jest opisane dokładnie jak liczy oryginał - wychodzi że max to 15 punktów za klocek, jeśli się trzymasz oryginału to może to też warto odwzorować

No i odwzorowałem. Oryginał błędnie liczy liczbę punktów soft-dropu, bo dodaje jałową wartość BCD do ogólnej liczby punktów, zamiast najpierw ją odkodować i dopiero wtedy zsumować — i jest to ewidentny bug. Fairtris nie wykorzystuje BCD (bo nie musi), więc poprawnie oblicza te punkty.

0

Kolejna wersja do testów — Fairtris 1.0.0.17 (beta). ;)

W tej wersji zaimplementowany został ostatni z brakujących generatorów, czyli generator FAIR. Liczba plecaków z klockami i ich zawartość została tak dobrana, aby stawiała przed graczem wyzwanie, generowane sekwencje były tak zróżnicowane i nieprzewidywalne jak w oryginale, a także aby nie odbierać w sposób niesprawiedliwy możliwości zdobywania dużej liczby punktów. Co prawda nie jest on jakoś wybitnie sprawiedliwy, ale i tak znacznie bardziej niż ten oryginalny.

Dodatkowo, algorytm ten zapewnia taką samą łączną liczbę losowanych klocków w każdym pełnym cyklu, dzięki czemu statystycznie dostaje się tyle samo z każdego rodzaju. No i co bardzo ważne, używanie soft-dropu i hard-dropu nie wpływa na rozkład klocków — a niestety oryginał bardzo mocno cierpi z tego powodu (potrafi w kółko losować klocki 2-4 typów, a pozostałych nawet kilka razy mniej). I w odróżnieniu od oryginału, w teorii istnieje możliwość przejścia gry perfekcyjnie, jednak jest to niezwykle trudne.

Generator FAIR to rozwinięcie koncepcji 7-BAG.

Klasyczny 7-BAG to jeden plecak zawierający po jednym klocku z każdego typu, wyciąganych w losowej kolejności. Natomiast FAIR to zestaw czternastu plecaków po dziesięć klocków. Każdy z plecaków zawiera po jednym klocku każdego typu oraz trzy klocki dodatkowe, duplikujące dwa rodzaje — 1×3 + 1×2 + 5×1. Plecaki są wybierane w nieznanej kolejności, tak samo jak klocki z każdego plecaka — gracz nie ma możliwości przewidzenia który klocek spadnie następny ani też który plecak będzie następnym. Jest też zabezpieczony przed wylosowaniem dwa razy tego samego plecaka klocków.

Podczas gry, wyciągane są klocki z aktualnego plecaka, a zawartość wszystkich pozostałych jest mieszana (jeden swap w każdym plecaku na klatkę). Dodatkowo, mieszana jest także macierz indeksów plecaków, tak aby w kolejnym cyklu plecaki były wybierane w losowej kolejności. Mieszanie klocków i indeksów bazuje na 16-bitowym ziarnie LFSR (ten rejestr używany jest w oryginale), które iteruje się poniższym kodem:

Seed := ((((Seed shr 9) and 1) xor ((Seed shr 1) and 1)) shl 15) or (Seed shr 1);

Aby jeszcze bardziej zwiększyć losowość i nieprzewidywalność, wszystkie plecaki indeksów i klocków są mieszane podczas przebywania w menu gry (a dokładniej, we wszystkich scenach innych niż scena rozgrywki i pauzy). W każdej klatce robi się po jednym swapie w każdym plecaku indeksów i każdym klocków.

Teraz przez pewien czas będę testować ten algorytm razem z lokalnymi graczami i zbierać feedback. Jeśli ktoś chciałby przetestować generator FAIR i dać znać co myśli o nim, to będę wdzięczny.

0

Ostatnia wersja testowa — Fairtris 1.0.018 (beta)

Pełna funkcjonalność gry jest już zaimplementowana, działają wszystkie tryby i wszystkie generatory. Co prawda obsługa kontrolerów jest nadal uboga, ale jak się to robi za pomocą joyGetPosEx, to trudno się dziwić. W każdym razie da się pobawić, szczególnie używając klawiatury. Jeśli ktoś natrafi na jakieś poważne błędy dotyczące rozgrywki to z chęcią wysłucham.

Jest to ostatnia wersja wspierająca renderowanie czysto software'owe, a także input i dźwięki obsługiwane za pomocą funkcji systemowych (takich jak PlaySoundW, GetKeyboardState czy ww. joyGetPosEx). Teraz zabieram się za ogarnięcie biblioteki SDL i jej wykorzystanie w tym projekcie. Dzięki niej, renderowanie będzie pierońsko efektywne, dźwięki będą mogły być odtwarzane jednocześnie, a wsparcie kontrolerów powinno być pełne.

Nie wiem ile zajmie mi nauka obsługi tej biblioteki. na razie stworzę sobie pusty, testowy projekt, który będę traktował jako plac zabaw i posprawdzam sobie najważniejsze rzeczy oferowane przez SDL-a. Jakby co, będę informował. ;)

0

Jeszcze jedna ”ostatnia” wersja testowa — Fairtris 1.0.0.19 (beta)

Wprowadziłem mam nadzieję ostateczne poprawki dotyczące generatorów i na razie na tym poprzestanę. To co jest obecnie działa elegancko. Choć nie wiem czy dobrze zrobiłem pisząc kod generatorów tak, jakbym programował NES-a — czyli korzystając z prymitywnego LFSR i mocno ograniczając ich logikę, tak aby jak najmniej operacji one wykonywały. Niby jest to wersja na pecety, ale w razie gdyby ktoś chciał zmodować oryginalny ROM, to będzie miał taką możliwość — uwzględniając limity NES-a, każdy z generatorów powinien się bez problemu zmieścić i działać nie powodując lagów.

3

Chwilę tu nie zaglądałem, więc mała aktualizacja — operacja wszczepiania SDL-a powiodła się. ;)

screenshot-20210825021341.png

Najpierw stworzyłem sobie testowy programik do spróbowania odtworzenia wszystkich funkcji, tak aby mieć pewność zanim ruszę z modernizacją źródeł. No ale wszystko poszło gładko — renderowanie na tylnym buforze, flip bufora na ekran, obsługa wielu dźwięków jednocześnie, obsługa klawiatury i kontrolerów, a nawet zabawa przyciskiem na pasku zadań.

Wymiana LCL na SDL we właściwym projekcie zajęła mniej więcej trzy dni, więc nieszczególnie długo. Trochę się zdziwiłem, że po zamianie instrukcji na SDL-owe i doprowadzeniu kodu do stanu umożliwiającego kompilację gra odpaliła od ręki, ale cieszy mnie to — nie muszę szukać w czym leży problem. Co prawda gra już jest grywalna, ale zostało mi jeszcze zrobić kilka rzeczy, w tym przeciąganie okna myszą, włączanie i wyłączanie trybu wideo niskiej rozdzielczości, przepisanie klasy dźwięków i jeszcze pewnie wiele innych pierdółek. Wydajność wzrosła kilkukrotnie, a w trybie wideo będzie jeszcze kilka razy wyższa.

Coż — jeszcze dzień-dwa i nowa wersja będzie dostępna do zabawy. Co prawda znalazłem trochę bugów w SDL, które trochę psują mi grę (szczególnie jeśli chodzi o obsługę ekskluzywnego trybu wideo), ale zobaczymy co da się z tym zrobić — zgłoszone są, będziemy próbować coś z nimi zrobić.

1

Tryb wideo zaimplementowany. Działa bezbłędnie, choć w mojej aplikacji testowej nie działał za dobrze — nie przywracał poprzedniego rozmiaru i położenia okna po wyjściu z ekskluzywnego trybu wideo. No a w projekcie głównym nie ma z tym żadnego problemu, pomimo użycia tego samego kodu. Dziwne, ale to nie pierwszy raz się zdziwiłem podczas używania SDL-a. :D

Czy kogokolwiek razi to, że gra domyślnie będzie się uruchamiała w ekskluzywnym trybie wideo?

Pytam was jako graczy, czy wam też przeszkadza to, że jak pobierzecie jakąś grę (jakąkolwiek) i ją uruchomicie, to że nie otwiera się w oknie, a na pełny ekran. Bo mi testerzy donieśli, że mają jebutne monitory i nie chce im się szukać jak ten tryb wyłączyć i wrócić do okienka. A nie będzie to trudne — F11 i po problemie.

1

Wypuściłem wersję beta projektu do testów — Fairtris 2.0.0.2 beta.

Z nowości to oczywiście użycie biblioteki SDL, a więc pierońsko wydajne renderowanie, wsparcie ekskluzywnego trybu wideo (o stałej rozdzielczości 800×600), wsparcie wielu dźwięków odgrywanych jednocześnie, obsługa pełnej puli kontrolerów oraz brak dużego input-laga, który wcześniej był spowodowany niewydajnym renderowaniem. W mojej ocenie czucie gry jest podobne jak na Mesenie, czyli jednym z najlepiej imitujących NES-a emulatorów.

Dużą nowością jest też implementacja dwóch kolejnych generatorów. Dziś dorzuciłem do kupki algorytmy z gier Tetris: The Grand Master oraz Tetris: The Grand Master 3 - Terror-Instinct — pograłem trochę i jestem wniebowzięty jakością wypluwanych sekwencji. Tak więc od teraz gra wspiera sześć różnych typów RNG. Instrukcji jeszcze nie ma, więc po raz kolejny niżej podaję aktualną klawiszologię.

MENU:

— nawigowanie w menu,
— przełączanie wartości aktywnej pozycji menu,

Z lub C — wejście do aktywnej opcji menu,
X — powrót do poprzedniego menu.

ROZGRYWKA:

— przesuwanie klocka,

— soft-drop,
— hard-drop,

X — rotacja odwrotnie do ruchu wskazówek zegara,
C — rotacja zgodnie z ruchem wskazówek,

Z — pauza/wznowienie,
V — ukrycie/pokazanie kolejnego klocka.

KLAWISZE SPECJALNE:

F1 — otwarcie pomocy (minimalizuje grę i otwiera główną stronę repo w przeglądarce),
F2 — przywrócenie inputu do ustawień domyślnych,

F10 — przycięcie klatki do rozmiaru NTSC (na potrzeby konfiguracji OBS i Maxout Club),
F11 — włączenie/wyłączenie ekskluzywnego trybu wideo w rozdzielczości 800×600.



Ogólnie w konstrukcji gry i jej mechanice już nic się nie zmieni, więc jedyne co by dobrze było wiedzieć to to, czy gra się u kogoś krzaczy, wyłącza lub działa nieprawidłowo. Na ten moment wiem, że kontroler retro-bit (klon NES-owego) jest niepoprawnie obsługiwany przez SDL-a i szukamy powodu tych problemów — póki co nie wiadomo czy skopane są nagłówki pascalowe, czy biblioteka SDL. W każdym razie trzy inne chińskie kontrolery działają bez zarzutu. Innych nie używam, ale SDL powinien ogarniać wszystkie, więc tutaj zdaję się na feedback.

Jedyne co pozostało to dorzucić komentarze do kodu, póki jeszcze mam w głowie cały projekt i wiem dokładnie jak działa (dokumentacji pisać nie zamierzam, bo kolejnych wersji tej gry nie przewiduję — co najwyżej portów na inne platformy), a także stworzeniem instrukcji obsługi i wrzucenie jej na główną stronę repozytorium.

2

czemu konfiguracja jest w pliku .ini a nie w treestructinfo?

1

Bo TreeStructInfo w tym przypadku to armata na muchę — podobnie jak XML. Informacji do przechowania jest za mało, aby korzystać z drzewiastej struktury i wymuszać znajomość kolejnej biblioteki do obsługi konfiguracji. Im mniej zależności tym lepiej, a w przypadku tej gry zależność jest tylko jedna — nagłówki dla SDL2.

Richtris z kolei przechowuje masę informacji, zarówno jeśli chodzi o definicję layoutu, jak i bazę rekordów personalnych i w tym przypadku TreeStructInfo został wykorzystany. Drzewa z danymi są reprezentowane przez drzewa klas, dzięki czemu ich obsługa jest wygodna i prosta — jednak wymagało to napisania sporej ilości kodu, bo generatora klas na podstawie zawartości konfiga na razie nie stworzyłem.

Jeśli jesteś ciekaw ile obecnie danych trzyma Richtris to do załączników wrzucam cztery jego pliki konfiguracyjne.

1

Nowa wersja do zabawy — Fairtris 2.0.0.5 beta 2.

Repozytorium — https://github.com/furious-programming/Fairtris
Wiki projektu — https://github.com/furious-programming/Fairtris/wiki



Ta wersja charakteryzuje się taką samą rozgrywką jak wcześniej, główna mechanika gry pozostaje bez zmian, natomiast poprawiłem trochę małych błędów w różnych menu gry (niegroźnych, niemal niezauważalnych), a także co nieco usprawniłem. Dużą zmianą jest implementacja sensownego sterowania w menu gry — zamiast używać klawiszy przypisanych do właściwej rozgrywki, od teraz menu steruje się za pomocą klawiszy strzałek, wybiera opcję za pomocą Enter, a cofa przy użyciu klawisza Escape. To jest intuicyjne i pozwala wygodniej nawigować.

Drugą dużą zmianą jest rozszerzenie obsługi kontrolerów USB. Wcześniej obsługiwane były tylko osie X i Y, a teraz wspieranych jest łącznie osiem osi oraz dwa ”haty”. Jest to konieczne, dlatego że wiele współczesnych i zaawansowanych kontrolerów przypisuje osie X i Y do lewej gałki analogowej, a nie do D-pada, więc wcześniej nie dałoby się takiego kontrolera użyć. No a teraz da się — jeśli D-pad jest zmapowany jako ”hat”, to można sobie go przypisać do sterowania. Analogi do Tetrisa nie nadają się kompletnie.

I to w sumie tyle — jeśli ktoś chce przetestować nową wersję i dać znać czy trafił na jakiś błąd, to będę wdzięczny. I nie bójcie się krytykować, w końcu po to założyłem ten wątek po to, aby zasięgnąć opinii innych. Kod jest gówniany, taki jaki był, ale to na razie musi zostać, więc się nie przejmujcie, jeśli traficie na spaghetti czy moduł z tysiącem stałych. ;)

Za niedługo dam znać też społeczności Free Pascala, że popełniłem tę gierkę — może znajdą się chętni do przygotowania forków na inne platformy niż Windows. W sumie to niewiele jest do zmiany, głównie usunięcie obsługi paska zadań, wymiana ShellExecute na coś uniksowego i przerobienie ścieżek w stałych na uniksowe. Zobaczymy jak będzie.

0

Jakby ktoś chciał pogadać o projekcie, potestować, dać feedback itd., to otworzyłem serwer na Discord, gdzie można wpaść i pisać na ten temat. Sewer jest świeży, dopiero kilka osób wpadło, ale rozpuściłem wici i zobaczymy co z tego wyjdzie.

0

Nowa wersja dostępna do pobrania — Fairtris 2.0.0.6 beta 3.

Dużych zmian nie było — tylko nieznaczne poprawki dotyczące kilku ekranów menu, coby łatwiej było np. wznawiać i resetować rozgrywkę. Zmieniłem też zachowanie po wciśnięciu przycisku pomocy. Wcześniej okno się minimalizowało i otwierała się pomoc w przeglądarce, ale u niektórych użytkowników, okno nie chciało się poprawnie zminimalizować, gdy ekskluzywny tryb wideo był aktywny. Dlatego też zrezygnowałem z minimalizacji na rzecz przejścia do trybu okienkowego. Dodałem też kod otwierający konkretną stronę wiki na podstawie aktualnej sceny — dzięki temu szybciej można uzyskać pomocne informacje.

1

Finalna, stabilna wersja do pobrania — Fairtris 2.0.0.7

W sumie to już wszystko jest zrobione i działa elegancko, ale jeszcze jedną zmianę wprowadziłem — przeniosłem flip bufora na koniec. Działa to w sposób bliski oryginałowi, gdzie najpierw pobiera się input i wykonuje logikę, następnie busy-waiting do przerwania i wtedy aktualizacja ekranu. Cóż, nic innego do roboty nie zostało.

To jest ostatnia wersja Fairtrisa — więcej raczej nie będzie. Projekt ten powstał po to, aby sprawdzić w warunkach zbliżonych do konsoli NES, jak będzie się grało na różnych regionach, różnej grawitacji, prędkości DAS-u i różnych generatorach. Takie małe poledko do sprawdzenia różnych wariacji, dzięki czemu można wybrać z tej gry to co najlepsze i stworzyć konkretny, dobrze działający zamiennik, przystosowany do współczesnej technologii i wymagań związanych z ligami, turniejami i dużymi mistrzostwami. Ale to piszę w kontekście CTWC — obecna wersja może być ogrywana dowolnie, bez żadnych przeszkód. ;)

0

Dodatkowa wersja dostępna do pobrania — Fairtris 2.1.0.1

Tak, wiem, miało już nie być kolejnych wersji, ale mogłem się powstrzymać. Postanowiłem zerwać kompatybilność mechaniki sterowania z wersją oryginalną i przeprojektować ją tak, aby działała jak najlepiej. Oryginalna wersja ma po prostu zepsute sterowanie, przez co aby móc grać na poziomach o najwyższej prędkości, trzeba mechanikę DAS-u eksploitować ”wall chargem”, więc koniec z tą patologią.

DAS zmodyfikowałem, dając graczowi pełną i konkretną kontrolę nad automatycznym przesuwaniem klocków. Teraz, jeśli gracz wciśnie strzałkę w bok, po tym gdy klocek przyklei się do stosu, ale przed spawnem kolejnego (przerwa ta zwana jest ”entry delay”), to DAS zostaje naładowany od razu do pełna. Dzięki temu można się skupić w pełni na stackowaniu, zamiast na eksploitowaniu niedorobionego sterowania.

Drugą zmianą związaną ze sterowaniem jest dodanie buforowania spinów. W oryginale jest tak, że jeśli chcemy wsunąć klocek w szczelinę, możemy z wyprzedzeniem wcisnąć strzałkę w bok, a jak klocek opadnie na określoną wysokość, to zostaje automatycznie wsunięty. Takie buforowanie niestety nie działa w przypadku spinów — wciśnięcie przycisku rotacji wcześniej nic nie daje. To powoduje, że przy dużych prędkościach, trzeba wcisnąć przycisk rotacji dokładnie gdy klocek opadnie na zadaną wysokość, co na poziomach 19 i wyższych wymaga precyzji co do dwóch klatek (czyli 32ms). Dlatego też dodałem buforowanie spinów, dzięki czemu śmiało można wykorzystywać bardziej zaawansowane techniki układania, bez obawy, że nie uda się wykonać spinu, ze względu na mikroskopijne okno czasowe.

Trzecią nowinką jest dodanie nowego generatora, nazwanego balanced. Działa on bardzo podobnie do oryginalnego, z tym że do wygenerowania każdego nowego klocka, bierze pod uwagę historię ostatnich dziesięciu wygenerowanych, a także licznik suszy każdego rodzaju klocka. Jeśli któryś jest przesuszony (nie spadł w ciągu ostatnich 13 klocków), to zostaje wybrany jako następny, bez losowania. W przeciwnym razie, generuje się nowe ziarno i wyznacza nowy klocek. Jeśli jest taki sam jak poprzednio wylosowany, to losuje się jeszcze raz (maksymalnie dwa razy). Następnie sprawdza się historię i jeśli nowo wygenerowany klocek nie występuje w historii co najmniej trzy razy (longbar cztery), to jest on wypluwany jako następny, a jeśli istnieje, to w pętli losuje się klocek dotąd, aż trafi się na taki, który nie oblega historii. W ten sposób RNG jest mocno zróżnicowane, ale zabezpieczone przed suszami i powodziami. Stanowi wyzwanie dla gracza, ale nie doprowadza do sytuacji, w której uniemożliwia granie i irytuje. W mojej ocenie, po jego wielogodzinnym testowaniu, uważam go za najlepszy generator ze wszystkich dostępnych w Fairtrisie.

0

Ostateczna wersja do pobrania — Fairtris 2.2.0.1

Skoro już zerwałem kompatybilność mechaniki sterowania z pierwowzorem, to postanowiłem jeszcze jedną rzecz zaimplementować. Otóż w grze na NES-a, nie da się w pewnych przypadkach obrócić klocka — jeśli jest dosunięty do ściany stosu (obramowania) i w wyniku rotacji, fragment klocka znajdowałby się poza polem gry, to rotacja jest blokowana. Zaimplementowałem więc poprawkę, czyli tzw. wall kick, który zawsze umożliwia rotację. Jeśli klocek nie mieści się w polu gry po obrocie, to obrót zostaje wykonany, a klocek odsunięty od ściany. Natomiast obrót jest niemożliwy, jeśli go bloku zawartość stosu (czyli tak jak w oryginale).

Wall kick jest zaimplementowany w formie podstawowej, czyli odbijanie się klocka jest możliwe tylko i wyłącznie od obramowania pola gry (od zawartości pola gry nie). I o ile zakres możliwych ruchów do wykonania zwiększył się, o tyle te przekombinowane, nierealistyczne spiny i twisty (znane z ”nowoczesnych” wersji Tetrisa) nadal nie są wspierane. Wszystko działa w oparciu o mechanikę gry w wersji na konsole NES, a więc klasyczny, surowy styl nadal jest utrzymany.

Po wprowadzeniu wszystkich poprawek, granie jest przyjemne i bogate w różne możliwości. Teraz można śmiało stosować najbardziej skomplikowane techniki układania, a więc robić to, co jest głównym zadaniem w grach logicznych (czyli rozwiązywać łamigłówki, zamiast użeranić się z popsutymi mechanikami).

0

Jeszcze jedna wersja dostępna do pobrania — Fairtris 2.3.0.1

Tym razem dorzuciłem kilka poprawek związanych z obsługą ekskluzywnego trybu wideo, bo trochę posysał. Po pierwsze, usunąłem wymuszanie rozdzielczości 800×600 dla trybu wideo — od teraz zawsze używana jest aktualna rozdzielczość ekranu. Po drugie, dodałem utrzymywanie proporcji obrazu dla trybu wideo, coby zawsze było 4:3 (wcześniej proporcje były wymuszane rozdzielczością SVGA, ale na różnych komputerach były różne efekty). Po trzecie, tryb wideo dostępny jest tylko dla głównego ekranu — na wielu komputerach i tak nie dało się odpalić tego trybu na dodatkowym monitorze, tylko problemy stwarzało. Tryb okienkowy nadal działa tak jak działał — jest dostępny na dowolnym monitorze, również przy rozciąganiu na pełen ekran.

I to w sumie tyle — nie ma za bardzo co już poprawiać, bo wszystko działa.

Natomiast to co uważałem za problem, czyli powódź zdarzeń generowanych po wciśnięciu strzałki na niektórych kontrolerach (np. szarym retro-bit), już problemem nie jest — to nie była i nie jest wina SDL-a, a gównianej jakości kontrolerów. Te źle działające kontrolery działają źle wszędzie, nie tylko w przypadku Fairtrisa. Sprwadziliśmy je narzędziem Gamepad Tester i okazało się, że one posiadają cztery osie analogowe zamiast dwóch cyfrowych, pomimo tego, że fizycznie mają jedynie D-Pad i cztery zwykłe przyciski. Pogratulować twórcom. :D

1

Wersja poprawiona ostatniego wydania — Fairtris 2.3.1.2

W tej wersji jedyną zmianą jest poprawiona inicjalizacja subsystemu SDL, dzięki czemu Fairtris wykorzystuje inicjalizacją jedynie wymaganych modułów SDL — flaga SDL_INIT_EVERYTHING nie jest już wykorzystywana. Zapobiega to problemowi z inicjalozacją modułu "sensor manager", występującego na niektórych komputerach.

4

Szykuję całkiem nową, trzecią już wersję gry — wszystko dlatego, że w najbliższych tygodniach chcemy zorganizować turniej online w Fairtrisa, pomiędzy sezonami ligowymi. No i aby móc grać mecze w sprawiedliwych warunkach, trzeba zapewnić obu graczom taki sam zestaw klocków, a żeby go zapewnić, trzeba dodać do gry opcję wpisywania ziarna dla RNG.

Dlatego też postanowiłem dodać nowe menu i dać możliwość wyboru trybu gry. Tryb jednoosobowy zostaje bez zmian, natomiast dodatkowo będzie tryb kwalifikacji i meczu dla turnieju na punkty, a także tryb kwalifikacji i meczu dla turnieju w speedrun. Menu wybory trybu mam już oprogramowane — tak wygląda dla obu skórek:

screenshot-20211228160702.png

Menu konfiguracji typu single player nie zmieniło się, a cztery pozostałe będą wyglądać tak:

screenshot-20211228161058.png

Dla kwalifikacji będzie można ustawić timer odliczający ile jeszcze czasu mają trwać (zwykle dwie godziny), natomiast dla meczu turniejowego będzie można wklepać seed generatora, który zwykle losowany jest za pomocą tetris-bota na czacie Twitcha. Interfejs gry dla sceny rozgrywki będzie odpowiednio przygotowany dla tych trybów, tak aby wyświetlać aktualny licznik czasu speedrunu itp. (po lewej mecz na punkty, po prawej mecz w speedrun):

screenshot-20211228161603.png

Rdzeń rozgrywki pozostaje jeden i będzie wykorzystywany bez względu na wybrany tryb — jedyne co trzeba zrobić to dorzucić do niego dodatkowy kod, który uwzględni obliczanie czasu, doda "kill-screen" na poziomie 19 dla speedrunu itd. Do tego lekko rozwinie się renderery, tak aby malowały dodatkowe dane.

Nie będę się bawił w projektowanie wspaniałego i elastycznego kodu na potrzeby wszystkich menu itd., bo raczej nie ma sensu poświęcać na to czasu, skoro i tak docelowa grupka odbiorców jest niewielka. Zrobi się porządne copy-paste, jak na poważnego janusza przystało i będzie dobrze. :D

1

No i jest nareszcie świeżutka wersja — Fairtris 3.0.0.2 beta

Główną nowością w tej wersji jest rozszerzenie trybów gry z jednego aż do sześciu. Teraz gra dzieli się na dwie główne kategorie — maraton, którego celem jest zebranie jak największej liczby punktów oraz speedrun, w którym należy jak najszybciej dojść z poziomu 0 do 19 (czyli skasować 190 linii) w czasie nie dłuższym niż 10 minut.

Dodatkowo, zaimplementowałem też tryb kwalifikacji maratonu oraz speedrunu, który pozwala ustawić sobie timer odliczający czas (licznik jest widoczny podczas grania oraz w kilku menu). Oprócz kwalifikacji, jest także tryb meczu, w którym dodatkowo ustala się seed generatora, po to aby mieć ten sam zestaw klocków u obu graczy, coby pojedynek był sprawiedliwy. Seed można wpisać ręcznie z klawiatury albo wygenerować losowy (można też skopiować go do schowka i z niego wkleić, standardowymi skrótami klawiszowymi).

Wszystkie wyniki są gromadzone w dwóch głównych listach (wyniki punktowe dla maratonów oraz czasy dla speedrunów), bez względu na wybrany tryb gry (swobodne gry, kwalifikacje czy mecz). Dodatkowo, gra posiada tymczasowe listy na potrzeby kwalifikacji i meczów, aby łatwiej było pokazać jak przebiegły kwalifikacje oraz jak wyglądała efektywność gier meczowych.

Nowością jest możliwość wybrania mechaniki sterowania — do dyspozycji jest nowoczesna mechanika, cechująca się wysoką responsywnością oraz większymi możliwościami, a także klasyczna, zgodna z oryginalną mechaniką z Tetrisa na konsolę NES. Usprawniłem też co nieco, np. działanie generatorów, poprawiłem renderowanie niektórych menu, dodałem kilka nowych dźwięków.

Pełna funkcjonalność nowej wersji Fairtrisa opisana jest w wiki projektu.

0

@furious programming:

Gierka to powstała — oprócz chęci nauki SDL —

  1. Wiem, ze piszesz w Pascalu, ale czemu nie chciales pisac w C i/lub C++?
  2. Jezeli znasz dobrze C++ w wersji 98, 11, 14 - to moglbys sprobowac w C++ 17 / 20 o ile nie znasz C++ 17 / 20.
2
teofrast napisał(a):
  1. Wiem, ze piszesz w Pascalu, ale czemu nie chciales pisac w C i/lub C++

Bo to w sumie dokładnie ten sam poziom abstrakcji. Między współczesnym Free Pascalem a współczesnym C++ nie ma wielkiej różnicy, jeśli chodzi o możliwości, efektywność itd. Jednak znaczącą różnicą jest to, że Free Pascal ma dużo przyjemniejszą składnię (rozwklekłą w stosunku do C++, ale czytelną) i łatwiej się z nim pracuje, ze względu na brak udziwnień i mnogości UB.

  1. Jezeli znasz dobrze C++ w wersji 98, 11, 14 - to moglbys sprobowac w C++ 17 / 20 o ile nie znasz C++ 17 / 20.

No właśnie — wybrałem Free Pascala, dlatego że różnych proceduralnych i obiektowych Pascali używam od 15 lat (Free Pascala z Lazarusem mniej więcej od siedmiu lat), a C/C++ łyknąłem co najwyżej podstawy, bardzo dawno temu. Tak więc tutaj wybór był oczywisty, a nawet można stwierdzić, że nie było go wcale. ;)

Swój przyszły projekt dużej gry również zrealizuję za pomocą Free Pascala, SDL i Lazarusa — świetnie mi się z tymi technologiami pracuje i znam jest dość dobrze. Tym bardziej, że dzięki nim mogę zrobić samą grę, ale też narzędzia-edytory, instalatory, aktualizatory itd. — nie ograniczają mnie.

4

Gdyby ktoś chciał zobaczyć Fairtrisa i profesjonalnych graczy w akcji, to kilka dni temu odbył się towarzyski mecz, gdzie zmierzyli się Xenophilius z Mecexem. Mecex testował już Fairtrisa wcześniej i przyzwyczaił się do timingu i z tego powodu poszło mu znacznie lepiej — przynajmniej, jeśli chodzi o sterowanie. ;)

Rozgrzewka i luźna rozmowa — https://www.twitch.tv/videos/1257311433?t=1h49m3s
Właściwy mecz — https://www.twitch.tv/videos/1257311433?t=2h1m7s

Edit: w tym tygodniu (pewnie w weekend) odbędzie się luźny stream — będę grał z jednym z topowych polskich graczy w Fairtrisa i pewnie dyskutował na około-tetrisowe tematy. Będzie można zobaczyć jak wygląda granie w klocki, po polsku. :D

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.