Piszę grę, która ma wiele aspektów czasu. Korzystam z czasu, aby pomóc oszacować pozycje graczy, gdy sieć nie zatrzymuje się i pakiety nie przechodzą (i czas między otrzymaniem pakietu a jego brakiem). Jest to gra typu pacman, w tym sensie, że gracz wybiera kierunek i nie może przestać się poruszać, więc system ma sens (a przynajmniej tak mi się wydaje).
Mam więc dwa pytania: 1) Jak zsynchronizować zegary gier na początku, ponieważ w sieci występuje opóźnienie. 2) Czy jest w porządku NIE synchronizować ich i po prostu założyć, że są takie same (mój kod jest niezależny od strefy czasowej). To nie jest super konkurencyjna gra, w której ludzie zmieniają swoje zegary, aby oszukiwać, ale nadal.
Gra jest programowana w Javie i Pythonie (równoległe tworzenie jako projekt)
Odpowiedzi:
Myślę, że to na pewno nie OK synchornize zegara w systemie . Użytkownik nie oczekuje, że dotkniesz ustawień systemu, a wiele systemów nawet na to nie pozwala.
Wystarczy mieć korelację, aby przekonwertować znacznik czasu z zegara jednej strony na zegar drugiej strony. Z drugiej strony potrzebujesz, aby ta korelacja była dość precyzyjna, powiedzmy co najmniej do setnej sekundy, jeśli chcesz użyć jej do przewidywania pozycji graczy. Zegar systemowy nigdy nie będzie tak dobrze skorelowany między losowymi maszynami. Dlatego powinieneś sam ustalić korelację, używając pewnej odmiany motywu NTP , prawdopodobnie osadzonej w innych wiadomościach w celu zachowania przepustowości sieci.
Podstawową ideą może być to, że z każdym wysłanym pakietem wysyłany jest znacznik czasu oraz numer sekwencji i znacznik czasu, gdy otrzymałeś ostatni pakiet z drugiej strony. Na tej podstawie obliczasz objazd: Na przykład, jeśli pakiet Q mówi, że został wysłany o wartości 1000, a pakiet P został odebrany o wartości 500, niż biorąc pod uwagę, że wysłałeś pakiet P o wartości 0 i otrzymujesz Q o wartości 800, podróż w obie strony wynosi (800 - 0 ) - (1000 - 500) = 300. Nie ma sposobu na poznanie asymetrii, więc po prostu zakładasz, że pakiet zabiera połowę (150) tyknięć w dowolnym kierunku. I ten zdalny znacznik czasu wyprzedza lokalny o 1000 - (800 - 150) = 350 tyknięć. Podróż w obie strony będzie się różnić. Jeśli przyjmiesz, że zegar jest dość precyzyjny, powinieneś użyć długoterminowej średniej korelacji.
Zauważ, że nie chcesz również używać zegara systemowego dla zegara. Mogą zostać zsynchronizowane w połowie drogi, co zepchnie cię z toru. Powinieneś używać
clock(CLOCK_MONOTONIC)
na Unixie lubGetTickCount
Windowsie (nie jestem pewien, jak te interfejsy API są teraz opakowane w Javie lub Pythonie).Uwaga: Opcja
SO_TIMESTAMP
gniazda (patrz gniazdo (7) wspomniane przez ott - w komentarzu do pytania) byłaby przydatna do oddzielenia efektu opóźnienia pętli zdarzeń, która odbiera pakiety. To, czy warto wysiłek, zależy od tego, jak dobrej precyzji potrzebujesz.źródło
Skąd wiesz, który zegar gracza jest prawidłowy? Nie, więc użyj zegara referencyjnego .
NTP jest tutaj przesadą - potrzebujesz tylko ~ 1 sekundy dokładności - więc użyj rdate lub wybierz coś z jednego z wielu algorytmów synchronizacji zegara.
Po wybraniu metody spraw, aby maszyna każdego gracza wybrała czas dla tej metody (bez zmiany zegara systemowego). Niezależnie od tego, jaka jest różnica między referencyjnym czasem UTC a zegarem systemowym graczy w czasie UTC, ich efektywne przesunięcie. Za każdym razem, gdy wykonujesz obliczenia związane z czasem, np. Ekstrapolując ruchy bota lub pociski ray-trace, bierzesz pod uwagę to przesunięcie po uzyskaniu czasu systemowego. Korzystanie z UTC wyeliminuje czynniki strefy czasowej.
źródło
Po drugie stwierdzam, że nie powinieneś używać NTP ani zbliżać się do zegara systemowego. Jeśli faktycznie przeanalizujesz ten wymóg, zauważysz, że masz następujące potrzeby:
Jest to uproszczony zarys - nie próbuję zajmować się takimi kwestiami, jak opóźnienie / upuszczone pakiety itp. - ale jest to podstawowa struktura, na której powinna opierać się cała sprawa.
Nic nie musi zbliżać się do zegara systemowego ani zajmować się takimi sprawami, jak różne strefy czasowe, chociaż ostatnia pozycja może w razie potrzeby użyć strefy czasowej. Ważne jest to, że rzeczywiste czasy, które upłynęły, są mierzone za pomocą timera o wysokiej rozdzielczości opartego na zerach, więc są one całkowicie niezależne od różnic stref czasowych. Chcesz znaleźć aktualny czas na serwerze? Wystarczy dodać czas, który upłynął, do bazowego czasu odniesienia i już go masz. Podobnie dla klienta.
źródło