Próbuję stworzyć grę wideo od zera, ale jestem naprawdę nowy i wciąż napotykam na podstawowe problemy. Co najważniejsze, w jaki sposób gry wideo przechowują informacje poza ekranem? Chodzi mi o to, skąd program wie, co następnie wyświetlić na ekranie? Lub nawet, jeśli odtwarzacz zmieni otoczenie, w jaki sposób ta zmiana pozostanie przy następnym załadowaniu na ekran?
Na przykład w New Super Mario Bros, jeśli trafisz? zablokuj, a następnie wyłącz ekran i wróć, nadal pozostaje trafiony. Jak te informacje są przechowywane, a następnie wykonywane przy następnym załadowaniu bloku przez gracza? Dlaczego się po prostu nie resetuje?
game-design
architecture
software-engineering
game-mechanics
Tylko kilka pytań
źródło
źródło
Odpowiedzi:
Zwykle należy oddzielić stan logiczny środowiska gry od reprezentacji wizualnej.
Gracz może zobaczyć tylko niewielką jego część na ekranie, ale nadal pamiętasz stan całego poziomu i zwykle obliczasz mechanikę gry dla całego poziomu. Gdy twój świat jest tak ogromny, że wymagałoby to zbyt wiele pamięci RAM i / lub procesora, możesz zawiesić dalsze obszary na dysku twardym.
Podprogram renderowania sprawdza, które części poziomu znajdują się obecnie na ekranie, a następnie je rysuje. Cokolwiek jest poza ekranem, nie jest rysowane, ale to nie znaczy, że nie jest aktualizowane.
źródło
Idziesz na to do tyłu.
Zaczynasz od logicznego stanu gry i modelujesz to. Cały logiczny stan całego świata prawie na pewno będzie zbyt duży, aby można go było zachować w pamięci jednocześnie, więc dzielisz go na mniejsze części, które można ładować i zapisywać niezależnie. Części te są często nazywane kawałkami . Te fragmenty mogą tworzyć ciągły świat, ale mogą być także osobnymi poziomami / instancjami. Terminologia różni się bardzo w zależności od gatunku i techniki, której chcesz użyć.
Następnie ładujesz te interesujące części - czyli fragmenty znajdujące się w pobliżu gracza. Fragmenty, które znajdują się zbyt daleko, są zapisywane w pamięci dyskowej / stałej i usuwane z pamięci.
Następnie, w ostatnim kroku, określasz, co jest faktycznie widoczne, tworzysz wizualną reprezentację bieżącego stanu gry i renderujesz ją na ekranie.
Oczywiście starałbyś się nie odbudowywać całej reprezentacji wizualnej za każdym razem, ale buforować ją i używać ponownie, jeśli masz już zbudowane części, ale to jest główna zasada.
Dotyczy to każdego programu, który ma wyjście. Jeśli napiszesz program z normalnym GUI, na przykład edytor tekstu, prawdopodobnie zamodelujesz dokument, a następnie GUI określi stan i widoczne części dokumentu i wyrenderuje go na ekranie. Lub odpowiednio wypełnij pola formularza, albo też.
Główny cel to: Zastanów się, gdzie i jak najpierw przechowujesz dane (prawdopodobnie wraz z tym, jak je reprezentować). Prawie każdy program musi zajmować się przechowywaniem danych. Jest tylko kilka przypadków, w których nie przechowujesz żadnych danych.
źródło
Jak powiedzieli inni, trzymasz mapę (np. W szyku) i rysujesz jej widoczną część na ekranie i nie odczytujesz z ekranu.
Ale w niektórych starszych systemach dosłownie trzymasz dane poza ekranem. Pamięć wideo miałaby na przykład 400 x 300 pikseli na ekran 320 x 200, a do tego zdefiniowałbyś rzutnię („zacznij od X = 10 Y = 30”). Aby przewijać ekran, wystarczy wyregulować rejestr. Nie musisz spędzać stu tysięcy cykli wymaganych do przenoszenia bajtów, wystarczy zmienić miejsce, w którym sprzęt wideo zaczyna je czytać.
NES ma to w połączeniu z systemem opartym na kafelkach: http://wiki.nesdev.com/w/index.php/PPU_scrolling
NES nigdy nie konstruuje pełnego obrazu w pamięci, ponieważ nie ma wystarczającej ilości pamięci RAM. Zamiast tego istnieje tablica RAM, która definiuje zestaw kafelków o szerokości dwóch ekranów. Jeden bajt na rodzaj płytki. Sprzęt wideo sprawdza kafelek i współrzędne przesunięcia X / Y, aby zdecydować, który piksel powinien pojawić się w dowolnym punkcie.
źródło
Cóż, jeśli zadajesz takie pytanie, będziesz miał długą drogę do miejsca, w którym możesz zrobić grę. Ale docierając do sedna pytania, program może zapisać stan wielu różnych rzeczy w zmiennych, które znajdują się w tylnej części twojego programu. Spójrzmy na kilka przykładów.
Mario Brothers (lub podobny) zapisuje stan poziomu, w którym się znajdujesz. Może to obejmować odległość, jaką przeszedłeś przed śmiercią, czy blok został trafiony, czy nie. W pewnym sensie bardziej obiektowym, gra mówi tylko „bądź tutaj blokiem”, a blok istnieje. potem, gdy uderzysz w blok, blok zmienia swój wewnętrzny stan, mówiąc „zostałem trafiony”. Takie dane mogą być przechowywane na różne sposoby.
Twój edytor tekstu zapisuje dane w strukturze danych. Teraz jest ich wiele i wiele sposobów ich implementacji, ale prawdopodobnie używa jakiejś formy drzewa. Na drzewie masz co najmniej jeden węzeł. Wszystko dodane przed przejściem w lewo. Cokolwiek dodane po nim, idzie w prawo. Po dodaniu trzech węzłów dwa z nich zwisają ze środkowego węzła. A drzewo może rosnąć jeszcze bardziej, dodając nowe elementy w dowolnym miejscu, a drzewo odbuduje się. Lub pomyśl o strzelankach, w których błąka się twój wróg. Każda z nich ma zmienne, które śledzą ich lokalizację, życie itp., Więc gdy ją zranisz, będzie pamiętać, że została zraniona.
Wszystkie te rzeczy wymagają znajomości struktur danych. To znacznie wykracza poza to, co widzisz na ekranie. Sugerowałbym przeczytanie o tablicach, listach, skrótach (czasami nazywanych słownikami lub mapami), a następnie powrót do problemu.
Oto kilka dobrych materiałów wyjściowych:
źródło
Do pewnego stopnia jest to funkcja renderowania 3D. Na przykład OpenGL automatycznie wyrówna geometrię poza zakresem -1,0, +1,0 w przestrzeni ekranu XY (Z jest bardziej złożone, ale podobne). Wyrównana geometria nigdy nie generuje fragmentów (w przybliżeniu pikseli), a zatem nigdy nie jest przekształcana w rzeczywiste obrazy, pomimo wysłania do systemu w celu renderowania. W każdym razie nie można pisać w przestrzeni poza oknem renderowania (jeśli wszystko działa tak, jak powinno).
W niektórych kontekstach wystarczy polegać na tym zachowaniu jako optymalizacji. Jednak nadal musisz przekazać wszystkie dane gry przez co najmniej jeden etap renderowania (shadery wierzchołków), zanim karta graficzna będzie wiedziała, co jest widoczne. W czymś takim, jak powiedzmy Skyrim, byłoby to niepraktyczne. Nie tylko musisz wysyłać każdy wierzchołek na świecie przez potok renderowania, ale musisz załadować każdy wierzchołek do pamięci systemowej / wideo. Jest to nieefektywne, jeśli w ogóle możliwe.
Dlatego wiele gier korzysta z cullingu opartego na procesorze. Zazwyczaj będą wdrażać pewnego rodzaju system LOD (poziom szczegółowości), w którym na jakość i istnienie aktywów ma wpływ to, jak ważne są w danym kontekście. Siatka piramidalna może być akceptowalnym przybliżeniem dla góry, jeśli jesteś 50 mil od niej. Jeśli w ogóle go nie widzisz (jakby był blokowany przez inne góry), nie musisz go nawet ładować. Istnieje wiele bardziej skomplikowanych metod, które są tematami, które moim zdaniem nie są bezpośrednio związane z głębokością wymaganą przez to pytanie, ale spójrz na teselację na jeden z najczęstszych przykładów.
Istotą tego jest to, że efekty wizualne są tylko produktem gry. Rzeczywiste dane nie mają nic wspólnego z tym, co widzisz lub nie widzisz przez większość czasu, a dane są filtrowane według różnych etapów w celu usunięcia obcych informacji przed dotarciem do punktu, w którym obraz jest zapisywany na ekranie. W zależności od projektu silnika wizualizacje można bardzo oddzielić od rzeczywistej logiki gry, o ile istnieje coś takiego jak posiadanie interfejsu 2D i 3D do tej samej gry. Możliwe jest nawet, że wiele silników gier będzie działać bez takiej mocy; czasami służy to do testowania AI gry.
Tam jednak sprawy mogą się komplikować. W czymś prostym, takim jak gra Mario, obliczanie ruchu wszystkich wrogów na poziomie nie jest zbyt wygórowane, nawet jeśli nie są widoczne. We współczesnych kontekstach to, co dzieje się poza ekranem, jest poważnym problemem. Jeśli jest wiele całych miast NPC, jak radzisz sobie z ich zachowaniem, gdy są całkowicie unicestwieni - na przykład, gdy gracz przebywa w innym mieście? Czy naprawdę chcesz obliczać setki decyzji NPC na całej mapie? Odpowiedź zazwyczaj brzmi „nie”, ale dokładne podejście do tego, by tego nie robić, może się różnić i może mieć wpływ na grę.
Ważne jest, aby pamiętać, że tak właśnie działa teraz . Same stare gry Mario były prawdopodobnie programowane na bardzo różne sposoby (nie potrafię mówić dokładnie), biorąc pod uwagę ekstremalne ograniczenia sprzętowe w tym czasie. Koncepcja 3D nie istniała wtedy; ale dziś prawie wszystkie gry, nawet te całkowicie 2D, używają renderowania 3D w jakiejś formie, nawet jeśli nie wiedzą, że to robią. Nowoczesny sprzęt wideo jest w pierwszej kolejności w 3D, a renderowanie 2D (przynajmniej wtedy, gdy właściwie wykorzystuje sprzęt) ignoruje jedynie trzeci wymiar.
źródło
Aby odpowiedzieć na twoje pytanie: gry wideo utrzymują stan świata gier w jakiejś abstrakcyjnej strukturze danych, która nie ma nic wspólnego z ekranem. Jest to następnie renderowane na ekranie w razie potrzeby (tj. W zależności od tego, gdzie jest gracz).
Gry, które używają RAM wideo bezpośrednio do celów stanowych, były w latach 80-tych w 8-bitowych, może nawet w 16-bitowych czasach, ale chyba, że pracujesz dla tej platformy lub dla jakiegoś µC, co zamiast tego zwiększa jej pamięć RAM w KB GB, zapomnij o tym.
To powiedziawszy, wydajesz się być bardzo nowy we wszystkim, co związane jest z programowaniem, w przeciwnym razie pytanie by się nie pojawiło. Proponuję pójść krok po kroku, najpierw programując bardzo proste rzeczy; może coś, co ma tylko tekstowe dane wejściowe / wyjściowe (proste monity i tak dalej). Szczerze mówiąc, czas, w którym to zrobiłem, upłynął około 30 lat, więc nie mam dla ciebie naprawdę dobrych zasobów, ale twoja lokalna biblioteka może być po prostu lepsza niż Internet, aby dać ci naprawdę dobry start w programowaniu.
źródło