Ta sama logika gry w dwóch osobnych bibliotekach graficznych

11

Jaka filozofia kodu / struktura abstrakcji / konstrukcja programu pozwoliłaby na użycie gry z grafiką 2D i 3D (osobno) BEZ konieczności ponownego kodowania logiki gry?

Mówimy o przyjęciu tego samego kodu, zmianie minimum rzeczy (na przykład zamianie nazw plików na zasoby 2D na nazwy plików na zasoby 3D), a może podłączenie kilku specjalizacji klasy podstawowej dla poszczególnych rodzajów / szablonów.

Aby umieścić go w prawdziwym kontekście, w którym ma to sens: wyobraź sobie grę dla wielu graczy w sieci LAN, w której jest jeden najwyższej klasy, wymagający wydajności klient 3D dla graczy z naprawdę dobrymi platformami dla graczy i bardziej skromny klient 2D dla starych zakurzone pudła, które ktoś znalazł na strychu. Ale to wciąż ta sama gra - rejestrowane są te same zdarzenia (ktoś podniósł monetę), używany jest ten sam protokół sieciowy, światy są proporcjonalne itp.

Aby umieścić to w kontekście MVC: Kontrolery są dokładnie takie same (naciśnięcie klawisza „W górę” ustawi przyspieszenie graczy na 3,5 jednostki / sekundę), Widoki są zupełnie inne (2D kontra 3D), a model jest taki sam z wyjątkiem czegokolwiek bezpośrednio związanego z grafiką (kontrola kolizji środowiska przeprowadzana jest co 5 sekund i wykorzystuje ten sam algorytm. Pamiętaj, że oznaczałoby to współrzędną Z dla wszystkich obiektów gry w wersji 2D, ale jest to po prostu zignorowany lub wyświetlony użytkownikowi w inny sposób, na przykład przez cień, który jest wyświetlany dalej w lewo, gdy gracz jest w powietrzu).

To, co czyni ten tak fascynującym tematem, zmusza dewelopera do bardzo jasnego wyobrażenia o strukturze jego danych i przepływie kontroli. Pamiętaj, że nie oznacza to korzystania z niczego poza biblioteką graficzną, taką jak SDL, D3DX lub OpenGL. Brak silników do gier!

Ponieważ jest to pytanie głównie teoretyczne, pominę języki programowania, ale jeśli chcesz dać przykład, możesz użyć dowolnego języka, który ci się podoba, C ++, jeśli chcesz przejść całą świnię, lub nawet Brainfuck, jeśli czujesz do wyzwania (wszelkie konkretne odpowiedzi zostaną docenione, a także wszelkie abstrakcyjne!).

Toby
źródło
Nie jestem pewien, czy to jest praktyczne. Tyle logiki gry wykorzystuje matematykę wektorową, musiałbyś zrobić wszystko w 3D przed konwersją do 2D lub cokolwiek do renderowania, lub musiałbyś całkowicie wyodrębnić bibliotekę wektorową - co z pewnością byłoby niepraktyczne?
tenpn
Wyszukaj termin „Warstwa abstrakcji” i zapoznaj się z nim, ponieważ wy dwoje będziecie razem pracować przez jakiś czas.
zaratustra

Odpowiedzi:

8

Myślę, że wszystko (?) Potrzebne byłoby warstwą abstrakcji otaczającą bibliotekę graficzną; będziesz potrzebować nowej dla każdej biblioteki, której będziesz używać, i każda będzie musiała mieć dokładnie taki sam zewnętrzny interfejs API.

Pomyśl o lokalizacji ciągów: zamiast zakodować na stałe ciąg „Inventory” w grze, zamiast tego wywołaj bibliotekę lokalizacji (być może niestandardową), która wykona niektóre procesy i zwróci odpowiedni ciąg, w zależności od kontekstu gra.

W ten sam sposób wszystkie połączenia do silnika graficznego byłyby wykonywane przez otaczające go opakowanie.

Robiąc to, ograniczasz / ograniczasz polecenia, które możesz wydać silnikowi graficznemu. Oto kilka niezbędnych:

  1. Rysuj (obiekt graficzny) w (lokalizacji)
  2. Zmodyfikuj (alfa, obrót itp.) Właściwość (obiektu graficznego)
  3. Przenieś (obiekt graficzny) do (lokalizacja)
  4. Zbuduj mapę (nazwa poziomu / struktura danych)

I kilka innych, które znajdziesz podczas pracy nad projektem.

Jeśli używasz języka obiektowego o ścisłych typach, nazwałbyś powyższe polecenia interfejsem, który wszystkie Wasze opakowania będą implementowane. Najlepiej, jeśli będą to jedyne niechronione / publiczne metody.

Teraz utwórz nowe opakowanie dla każdej biblioteki graficznej i zaimplementuj interfejs API . Kiedy otrzymasz polecenie narysowania __ w __ , musisz użyć kodu, aby utworzyć duszka lub model i wciągnąć go do swojego środowiska. Może to wymagać pewnych sztuczek, takich jak przechowywanie każdego duszka w haszu, aby był dostępny w innym czasie za pomocą danego symbolu.

Jeśli chodzi o tworzenie map, najskuteczniejszym sposobem byłoby wcześniejsze zbudowanie każdej mapy dla każdego silnika graficznego i sprawdzenie. Alternatywnie możesz zapisać mapę we własnej niestandardowej strukturze danych, a następnie użyć opakowania do zbudowania mapy z tej struktury danych.

Mam nadzieję, że to pomoże Ci zacząć =]

Justin L.
źródło
2

Budowanie architektury gry za pomocą paradygmatu wystarczająco zbliżonego do MVC, aby umożliwić całkowitą abstrakcję kodu wyświetlanego, byłoby prawdopodobnie trudne dla każdego dużego projektu. Wydaje się jednak, że największą przeszkodą w stworzeniu gry, która obsługuje zarówno klienta 2D, jak i 3D, byłoby zaprojektowanie gry, w której obaj klienci są równie zdolni.

Konieczne byłoby rozpoczęcie projektowania gry z pełnym zamiarem utworzenia i obsługi dwóch klientów, i prawdopodobnie najbezpieczniej byłoby ograniczyć wszystkie funkcje gry do tego, co ma sens dla klienta 2D.

Na przykład pułapkę, jeśli nie projektujesz do zestawu z ograniczoną funkcjonalnością, możesz stworzyć poziomy, na których ważne informacje lub obiekty byłyby widoczne tylko pod określonymi kątami. Chociaż byłoby to w porządku dla klientów 3D, którzy mają swobodę oglądania 360 stopni, chyba że twój klient 2D wyraźnie wspierałby kąt widzenia, który byłby widoczny dla każdego z tych ważnych obiektów, miałbyś negatywny wpływ na użytkowników klienta.

Najlepiej byłoby określić określoną liczbę kątów widzenia dla klienta 2D (8 lub 16 lub więcej) i opracować całą zawartość, aby pasowała do tych ograniczeń. Niestety, jeśli masz poziomy i obiekty, które mają być widoczne tylko z określonego zestawu kątów, może wyglądać dość dziwnie z poziomu klienta 3D.

Moim zdaniem próba zaprojektowania gry, w której klienci 2D i 3D mają mieć takie same możliwości, byłaby kiepskim wyborem. Myślę, że lepszym wykorzystaniem zasobów byłoby zaprojektowanie asymetrycznych opcji rozgrywki i umożliwienie każdemu klientowi wykorzystania swoich mocnych stron. Na przykład, jeśli klient 2D był przede wszystkim skoncentrowany na strategicznej perspektywie świata gry, a klient 3D był wykorzystywany do rozgrywki na poziomie taktycznym.

Charles Ellis
źródło
0

Myślę, że właściwie odpowiedziałeś na swoje pytanie:

Aby umieścić to w kontekście MVC: Kontrolery są dokładnie takie same (naciśnięcie klawisza „W górę” ustawi przyspieszenie graczy na 3,5 jednostki / sekundę), Widoki są zupełnie inne (2D kontra 3D), a model jest taki sam z wyjątkiem czegokolwiek bezpośrednio związanego z grafiką.

Dzięki zapewnieniu odpowiedniej abstrakcji między danymi wejściowymi, logiką gry itp. A grafiką rozwiążesz problem.

Jest to w zasadzie sedno modelu MVC, szczególnie jeśli dotyczy aplikacji stacjonarnych i internetowych: może istnieć wielu klientów uzyskujących dostęp do tych samych danych i manipulujących nimi (na przykład interfejs WWW, klient mobilny i klient stacjonarny do wiadomości e-mail).

Sean James
źródło
0

Zachowaj prostotę, jeśli chcesz, aby była prosta: - Napisz logikę gry, aby przenieść obiekty. Nie przechowuj na nich żadnych danych związanych z renderowaniem. - Napisz renderery, które mają szansę sprawdzić stan danych gry i je narysować.

Możesz do tego użyć mniej lub bardziej skomplikowanych technik programowania. Jedyne, czego potrzebujesz, to sposób na uzyskanie „dodatkowych” danych, które musisz renderować dla każdego obiektu gry. Najprostszym sposobem jest zero dodatkowych danych! Jeśli obiektem gry jest „Wizard”, narysuj Wizard.

Jeśli potrzebujesz bardziej skomplikowanych metod, rozważ polimorfizm, wzorzec memento, tabele skrótów, wskaźniki void * itp. Nie przerabiaj go (większość z tych metod jest przerobiona).

Vincent Scheib
źródło