#3 Zbuduj więzienie myszą, i pomieszczenia, które same się znajdują
· Nick
Drugi kamień milowy jest ukończony i po raz pierwszy jest na co patrzeć. Klient w Godot siedzi teraz na rdzeniu symulacji i myszą można zbudować jednopiętrowe więzienie: układać podłogi, rysować ściany, stawiać drzwi, oznaczać pomieszczenia, burzyć. Wszystko to zwykłe sześciany i płaskie kolory, a ludzi w środku nadal nie ma. Ale to miejsce i można po nim oprowadzać kamerę.
Co można robić teraz
Zaczynasz nową grę, wybierasz rozmiar mapy (64, 128 lub 256 kafelków w boku) i opcjonalne ziarno, i dostajesz pustą siatkę. Kamera jest ortograficzna ze stałym nachyleniem. Obraca się wyłącznie co 90°, przybliża w stronę kursora, przesuwa się klawiszami lub środkowym przyciskiem i ma tryb widoku z góry do budowania. Ściany zasłaniałyby pomieszczenia kamerze obracanej swobodnie, więc nie obraca się swobodnie.
Podłogi i rozbiórka przyjmują prostokąt. Ściany biegną po obrysie (albo po prostej, jeśli przytrzymasz Shift). Drzwi stawia się kliknięciem, a kierunek wybierają z sąsiednich ścian, z klawiszem do obracania. Podczas przeciągania obszar pod kursorem jest pokazywany jako duch: zielone kafelki zostaną zbudowane, czerwone pominięte, a podpis mówi ile i dlaczego. Nic nie jest wysyłane do świata, dopóki nie puścisz przycisku, a jeśli rdzeń mówi, że żaden kafelek się nie zmieni, nie jest wysyłane nic. Prawy przycisk lub Escape anuluje.
W modelu świata jest kilka pięter, więc jest wybór piętra, a piętra nad bieżącym są ukryte. Pomieszczenia mają własne narzędzie, opisane niżej. Nakładka debugowania pokazuje granice chunków, kafelki dostępne dla ruchu, kafelek pod kursorem i panel z czasami. Każde słowo w interfejsie jest po angielsku.
Podgląd to prawdziwy wynik
Duch, który nie zgadza się z wynikiem, jest gorszy niż brak ducha. Dlatego klient nie zgaduje, co zrobi komenda budowania. Rdzeń potrafi odpowiedzieć „co by się stało, gdybyś to uruchomił” dla tego samego obszaru, kafelek po kafelku, z powodem dla każdego kafelka, który by odrzucił. Kontrola wypełniająca podgląd to ta sama reguła, której komenda używa, gdy naprawdę się wykonuje, więc nie mogą się rozjechać. Klient tylko rysuje odpowiedź. Pyta rdzeń ponownie tylko wtedy, gdy zmieni się coś, co wpływa na odpowiedź: narzędzie, przeciągany obszar, piętro albo sama mapa.
Ta sama zasada kształtuje resztę klienta: czyta on stan świata i wysyła komendy, nie mając własnej logiki symulacji. Na razie rdzeń tyka w głównym wątku, a komenda z kliknięcia jest stosowana na początku następnej klatki, przed tickiem świata. Jeśli czasy ticków zaczną skakać, gdy świat zapełni się ludźmi, plan to przeniesienie rdzenia do osobnego wątku, ze zmierzonym progiem, kiedy to zrobić.
Pomieszczenia, które same się znajdują
Rozważyłem dwa sposoby tworzenia pomieszczeń. W Prison Architect rysuje się strefę, która potem jest osobnym obiektem z własnymi kafelkami. To łatwe do zrozumienia, ale w więzieniu się sypie: cały blok cel byłby jedną strefą, a po przebudowie ściany trzeba ją malować od nowa. Drugi sposób to automatyczne wykrywanie zamkniętych obszarów, ale wtedy nie da się oznaczyć dziedzińca, którego nie otaczają ściany.
Wybrałem mieszankę. Zapisywany jest tylko typ pomieszczenia na każdym kafelku: cela, stołówka, łaźnia, ambulatorium, pokój odwiedzin, plac spacerowy i tak dalej. Wszystko inne wylicza się ze ścian. Przestrzeń to grupa otwartych kafelków połączonych bokami, na jednym poziomie, i jest zamknięta, jeśli nie styka się z krawędzią mapy ani z pustym uskokiem. Pomieszczenie to wszystkie kafelki jednego typu w jednej przestrzeni. Ściany i drzwi są granicami, a typ namalowany pod ścianą jest zachowywany, ale ignorowany, więc wraca, jeśli ścianę rozbierzesz.
Daje to zachowanie, które wydaje się właściwe bez tłumaczenia. Poprowadź ścianę przez pomieszczenie, a staną się z niego dwa pomieszczenia tego samego typu. Usuń ścianę, a się połączą. Postaw drzwi tam, gdzie była ściana, a nic się nie zmieni. Niepoprawne pomieszczenie nie jest usuwane, bo byłoby to przeciwieństwo „bez bólu”; jest pokazywane na czerwono z powodami: niezamknięte, współdzielone z innym typem, za małe albo bez drzwi. Można zamalować prostokąt, jednym kliknięciem wypełnić całą zamkniętą przestrzeń albo ją wyczyścić.
Lista pomieszczeń to dane pochodne, więc nie jest zapisywana i nie wchodzi do skrótu świata; zapisywany jest tylko typ na każdym kafelku. Jest przebudowywana po komendach i po systemach, a sprawdzenie niezmienionego świata nic nie kosztuje. W tym kamieniu milowym zmieniony poziom jest przeliczany w całości, co zajmuje około pół milisekundy na mapie 256×256; przeliczanie chunk po chunku może poczekać, aż regiony ścieżek będą potrzebować tej samej maszynerii. Zasada, której się trzymam: przyrostowa przebudowa musi dać ten sam wynik co pełna.
Przebudowa tylko tego, co się zmieniło, przekrój pięter za darmo
Mapa jest rysowana jako jedna siatka na chunk na poziom, a nie jeden obiekt na ścianę. Każdy chunk ma w rdzeniu licznik wersji, a renderer pamięta, którą wersję narysował ostatnio. Gdy świat się zmienia, do kolejki trafiają tylko chunki z nowszą wersją, a kolejka jest obrabiana z budżetem czasu na klatkę, więc ogromna zmiana rozkłada się na kilka klatek zamiast zamrażać jedną. Malowanie typu pomieszczenia nie podnosi wersji mapy, więc nigdy nie budzi budowniczego siatek.
Przekrój pięter idzie za tą samą ideą robienia mniej. Piętra nad bieżącym są po prostu ukryte. Ściany bieżącego piętra są spłaszczane do jednego metra przez shader, jeden wspólny materiał i jedna wartość wysokości, więc przełączanie pięter albo pełnych ścian niczego nie przebudowuje. Przełączenie przez cztery poziomy powoduje zero przebudów siatek.
Szczelina dziesięciu centymetrów
Gdy wypróbowałem pierwsze jednopiętrowe więzienie podczas końcowej kontroli, na poziomie wyżej była podłoga i z boku między górą ściany a płytą nad nią widać było cienką jasną linię. W narożniku można było zobaczyć podłogę wiszącą w powietrzu. Podejrzewałem przekrój pięter, potem z-fighting, potem wygładzanie.
Nic z tego. Podłoga była pojedynczym płaskim czworokątem bez grubości, narysowanym na wysokości swojego poziomu plus dziesięć centymetrów. Ściany poziomu niżej sięgały dokładnie trzech metrów. Podłoga następnego poziomu zaczynała się na trzech metrach dziesięciu. Szczelina miała dziesięć centymetrów szerokości i przez nią było widać oświetloną górną ścianę muru. W poziomie wszystko pasowało idealnie, dlatego dłuższy czas zajęło mi to zauważyć.
Poprawka polega na tym, że podłoga jest teraz płytą z prawdziwą grubością, sięgającą w dół do początku swojego poziomu. Góra zostaje na tej samej wysokości, więc wybieranie kafelków myszą i wszystkie nakładki się nie zmieniły. Boczne powierzchnie są pomijane tam, gdzie podłoga lub ściana stykają się w obrębie tego samego chunka, a rysowane na granicach chunków, więc siatka chunka nigdy nie zależy od sąsiadów. Zostaje przez to ciemna dziesięciocentymetrowa krawędź na końcu płyty. Obejrzałem zrzuty ekranu sprzed i po i postanowiłem ją zostawić. Wygląda jak krawędź podłogi, którą zresztą jest.
Czy to się trzyma
Ostatnim zadaniem kamienia milowego było zbudowanie myszą jednopiętrowego więzienia i sprawdzenie, czy boli. Przeważnie nie bolało. Poza wspomnianą szczeliną przebieg wykrył drobne, irytujące rzeczy: przyciski narzędzi nie przestawały być podświetlone, gdy wybierałeś myszą inne narzędzie, a z okna Nowa gra nie było drogi powrotnej klawiszem Escape. Oba błędy naprawiono. Menu pauzy jest na liście pomysłów na później.
Co dalej
Dalej jest M2, ruch i codzienny rozkład dnia. Świat dostaje regiony i osiągalność, wyszukiwanie ścieżek działające między piętrami oraz pola przepływu dla tłumów. Rdzeń wreszcie ma prawdziwą pracę w każdym ticku, więc bramka benchmarku przestanie spać. Zobacz plan rozwoju.