Jak wydajnie kodować jednocześnie klienta i serwer?

15

Koduję swoją grę za pomocą modelu klient-serwer. Podczas gry w trybie dla jednego gracza gra uruchamia lokalny serwer i współpracuje z nim tak samo, jak zdalny serwer (multiplayer). Zrobiłem to, aby uniknąć kodowania oddzielnego kodu dla jednego gracza i dla wielu graczy.

Właśnie zacząłem kodować i napotkałem poważny problem. Obecnie rozwijam grę w Eclipse, mając wszystkie klasy gier zorganizowane w pakiety. Następnie w kodzie serwera po prostu używam wszystkich klas w pakietach klienckich.

Problem polega na tym, że te klasy klienta mają zmienne specyficzne dla renderowania, które oczywiście nie byłyby wykonywane na serwerze.

Czy powinienem utworzyć zmodyfikowane wersje klas klienta do użycia na serwerze? Czy powinienem po prostu zmodyfikować klasy klienta za pomocą wartości logicznej, aby wskazać, czy używa go klient / serwer. Czy są jakieś inne opcje, które mam? Zastanawiałem się, czy może nie wykorzystać klasy serwerowej jako klasy podstawowej, a potem rozszerzyć ją o renderowanie?

liamzebedee
źródło
Czy masz opcje preprocesora? Jak #ifdef KLIENT <jakiś kod> #endif. Jest to prosty sposób na udostępnianie plików klas, które mogą różnić się między serwerem i klientem, a także udostępniać części. Jest to jednak trochę niechlujne.
William Mariager,
Zgadzam się z MindWorX. Chociaż kompilacja warunkowa jest uciążliwa w Javie, istnieją rozwiązania, które należy rozważyć.
sam hocevar,
1
Kompilacja warunkowa to prymitywny sposób powiedzenia „nie poświęciłem wystarczająco dużo czasu na projektowanie w moich pakietach”, moim zdaniem =) „Trochę bałagan” zwykle przekłada się na „Co do cholery to robi?” sześć miesięcy później, kiedy ponownie przeczytasz nawet swój własny kod i przyniesie on efekt przeciwny do niczego poza wyrzucanymi prototypami.
Patrick Hughes,

Odpowiedzi:

23

Powinieneś raczej trzymać kod renderowania oddzielony od logiki gry , ponieważ są to osobne problemy .

Jeśli oddzielisz kod renderujący od kodu klienta / serwera, uzyskasz kilka korzyści:

  • Utworzenie serwera dedykowanego będzie łatwiejsze, ponieważ każdy renderowany kod będzie w jednym miejscu.
  • Możesz oddzielić updatefazę od renderfazy i uruchamiać je w różnym czasie.
  • Możesz upewnić się, że Twój kod renderowania nie mutuje stanu gry, używając const, redukując błędy.
Blair Holloway
źródło
1
+1 Nie mogę się bardziej zgodzić z tym sentymentem. Oddzielenie modelowania danych od renderowanych widoków tego modelu pozwoli ci czysto robić porządne rzeczy, takie jak wiele okien z różnymi informacjami, przenosić renderowanie na inne platformy, dodawać analizy i dostosowywać symulację do gry bez konieczności dotykania 90% bazy kodu .
Patrick Hughes,
5

Myślę, że powinieneś dokładnie oddzielić kod klienta i kodu serwera. Kod serwera i kod klienta nie powinny wiedzieć o sobie, z wyjątkiem funkcji udostępnianych przez interfejsy. Serwer nie powinien wiedzieć nic o renderowaniu, rejestrowaniu klientów, śledzeniu pozycji, czasie itp. Jeśli masz wyraźnie oddzielone obawy, łatwiej jest utrzymywać i rozwijać grę. Mam nadzieję, że to trochę pomoże.

loodakrawa
źródło
+1 Zwykle się z tym zgadzam. Jeśli serwer będzie obsługiwał klientów, powinien to zrobić jako osobne procesy.
Inżynier
5

Rozdzielenie problemów FTW, jak powiedzieli inni, ale jeśli Twoim celem końcowym jest posiadanie oddzielnych aplikacji klienckich i serwerowych, musisz pójść o krok dalej. Musisz określić, co jest specyficzne dla klienta, co jest specyficzne dla serwera i co jest udostępniane. Dla wszystkiego, co jest współużytkowane, podziel je na klasy kodu udostępnianego wyłącznie; klasy specyficzne dla klienta lub serwera mogą następnie odpowiednio podklasować lub odwoływać się do klas współdzielonych. Przenieś wspólne klasy do oddzielnego projektu, budując plik JAR „biblioteki współdzielonej” i dołącz ten plik JAR do projektów klienta i serwera.

Ma to kilka zalet: sprawia, że ​​separacja problemów jest krystalicznie czysta, aby utrzymać wszystko w osobnych projektach; zapewnia, że ​​klient i serwer zaczynają od tego samego wspólnego kodu (o ile używają tej samej wersji wspólnego pliku JAR); i uniemożliwia „przypadkowe” zmodyfikowanie współdzielonego kodu, nie zdając sobie z tego sprawy. Jeśli kod współdzielony jest w swoim własnym projekcie, będziesz wiedział, że kiedy edytujesz w nim coś, musisz wiedzieć, w jaki sposób zmiany wpłyną zarówno na klienta, jak i na serwer.

Adrian
źródło