Niedawno pojawiła się dyskusja na temat tworzenia wieloosobowej gry 2D z przewijanym bokiem, która może mieć zapętlony poziom (Pomyśl o Starbound i jak zapętlają się ich światy).
Pomyślałem, że najprostszym sposobem będzie posiadanie prostokątnej mapy ze strefami wyzwalania, która mogłaby teleportować graczy z jednej strony na drugą. Jednak oczywistym problemem związanym z tym podejściem jest posiadanie wielu graczy jednocześnie na krawędzi mapy. Nie chcesz po prostu teleportować graczy przed sobą i potrzebujesz transportu, aby inni nie zniknęli.
Aby dołączyć ten pomysł i naprawić problem, wymyśliłem: strefę wyzwalania (czerwony kwadrat na obrazku), w której gracze będą mogli zobaczyć „strefę klonowania” (zielony kwadrat). W tym zielonym kwadracie obiekty z przeciwnej strony strefy wyzwalającej zostałyby skopiowane do odpowiedniej strefy klonowania (można to zobaczyć w kształtach A i B). Kiedy gracz dotrze do początkowej krawędzi „strefy klonowania”, zostaje teleportowany na drugą stronę mapy.
W tym przykładzie Gracz 2 pomyślałby, że widzi Gracza 1, jednak tak naprawdę zobaczyłby jego klon i odwrotnie.
Wydawało się to nieco ekstremalne i złożone w odniesieniu do problemu. Moje pytanie brzmi teraz: czy to rozwiązanie jest dobrym podejściem do rozwiązania problemu, czy też istnieje prostszy sposób rozwiązania tego problemu?
źródło
Odpowiedzi:
Ten system ze wszystkimi tymi wyzwalaczami wydaje się nieco zbyt skomplikowany i podatny na błędy.
Możesz zawinąć pozycję odtwarzacza za pomocą modulo z czymś takim
playerPositionX = playerPositionX % mapWidth
W ten sposób, gdy gracz osiągnie zostaną przywrócone do 0.
playerPosition == mapWidth
playerPosition
To rozwiązanie można rozszerzyć o cały system renderowania.
źródło
pos - map_width
. At ).Kanonicznym rozwiązaniem jest użycie portali . W twoim przykładzie jest tylko jeden poziom, z wyjątkiem portalu łączącego lewy i prawy koniec.
Cokolwiek porusza się po tym portalu, jego współrzędne zostaną przetłumaczone na drugi koniec portalu, więc jeśli coś porusza się w lewo przez portal, pojawi się ponownie po prawej stronie poziomu i odwrotnie.
Twój aparat musi również obsługiwać portale; jeśli portal znajduje się w kamerze, musi renderować części poziomu po obu stronach portalu. Jeśli znasz edytory obrazów do płynnej grafiki kafelkowej, tutaj jest to ta sama oferta.
Nużącą częścią jest to, że wszystko, co dotyczy dystansu lub ścieżki, musi również wspierać portale. Obejmuje to AI, algosfery widzenia, tłumienie dźwięku i tak dalej.
Zaletą portali jest to, że jest bardzo wydajny. Silnik kompilacji wykorzystał go do symulacji poziomów wielopiętrowych, mimo że nie jest to „prawdziwy” silnik 3d. Niektóre nowoczesne silniki wykorzystują portale również do tworzenia przestrzeni innych niż euklidesowe; Portal i antichamber to godne uwagi przykłady w 3D.
źródło
Pamiętaj, że to, co wyświetlasz na ekranie i co jest w pamięci, to dwie zupełnie różne rzeczy. Wyobraź sobie, że masz okno, które musisz wypełnić danymi o świecie. Wypełniasz okno od lewej do prawej. Podczas analizowania danych w celu wypełnienia świata, jeśli dotrzesz do końca świata, po prostu zapętl się z powrotem do początku swoich danych. Korzystanie z operacji modulo jest idealny. Pamiętaj, że musisz to zrobić dla wszystkiego . Pociski, promienie, gracze, fizyka; wszyscy muszą mieć zawinięte pozycje podczas przekraczania granic świata.
Każdy gracz udostępnia dane, ale ma swoją własną perspektywę. Ich okna są zapełniane w różny sposób w zależności od tego, gdzie stoją na świecie.
Oznacza to, że nie trzeba tworzyć klonów ani teleportować nikogo. Zasadniczo masz są tworzenia klonów, po prostu renderowania postaci do siebie nawzajem ekranów.
źródło
Odłącz renderowanie od świata i możesz wykonywać zawijanie i poprawne renderowanie bez uciekania się do jakichkolwiek artefaktów klonowania lub teleportacji.
Po pierwsze, w swoim świecie masz świat o stałym rozmiarze, od
0
doWidth
. Za każdym razem, gdy obiekt spadnie poniżej 0, zawijasz go do końca, a za każdym razem, gdy obiekt się kończy,Width
zawija go do początku. Oznacza to, że wszystkie logiczne obiekty w twoim świecie są zawsze w zasięgu0...Width
.Po drugie, do renderowania zrobisz modulo na pozycji. Tak więc lewa strona ekranu to „Baza”, a prawa strona to „Baza + rozmiar”. Więc przeglądasz swój świat w poszukiwaniu czegokolwiek z tego zakresu. Będziesz faktycznie szukać zakresu modulo, który odwzorowuje go z powrotem
0...Width
.Sztuczka podczas wyszukiwania polega na zwróceniu pozycji obiektu względem
Base
lewej strony. Konwertuje to na lokalne współrzędne ekranu, dzięki czemu sam moduł renderujący nie musi martwić się o moduł, tylko wyszukiwanie.Nie trzeba niczego klonować, ponieważ każdy mechanizm renderujący obsługuje obiekt tylko w jednym miejscu.
Jeśli twój świat jest produkowany w segmentach lub przy użyciu struktur 3D, musisz go podzielić na segmenty. Dlatego nie jest to jeden spójny blok, ale można go przenieść, aby dostosować się do tego renderowania. Nie potrzebujesz wielu bloków, co najmniej 2.
źródło
Wydaje mi się, że jedynym rozsądnym podejściem byłoby wdrożenie twojego zawiniętego świata w podstawową strukturę danych całkowicie przejrzystą dla gry i użytkownika. Tak więc na niektórych poziomach niskiego poziomu masz funkcję mapCoordinate (), która zawija twoje rzeczywiste współrzędne do bazowego zasobu mapy ...
Więc jeśli twój rzeczywisty Świat ma tylko 10 jednostek szerokości, gracz i gra go nie poznają. Dla gracza świat jest nieskończony - a jeśli gra zapyta, co jest na pozycji 15 - podstawowa funkcja przetłumaczy to żądanie, modulo10 i da paczkę przedmiot na pozycji 5.
Tak więc dla całej logiki gry i wszystkiego innego jest tak, jakbyś miał nieskończony duży świat, w którym zdarzają się kopie wszystkiego.
źródło
To nie jest dokładnie to samo, ale zaimplementowałem coś podobnego w jamie gry. W grze gracze poruszali się na małym okrągłym poziomie, owiniętym wokół siebie, gdy gracz osiągnął pozycję „x” pi. Renderowanie było łatwe, ponieważ po prostu renderowaliśmy wszystko, a następnie obróciliśmy kamerę offsetową, aby śledzić, co się dzieje. Możesz zaimplementować coś podobnego, jak zasugerowano powyżej:
źródło