Wyróżniony projekt

Wyróżniony projekt RabBit
RabBit jest silnikiem do gier który w założeniu ma spałniać moj...

Wyróżniony wpis

Wyróżniony wpis Dziewczyna na deszczu - wytrwałość
Kończę gdy się znudzę. A nudzę się szybko. Ta świadomo&...

Wyróżniony poradnik

Wyróżniony wpis Jak rozpocząć prywatną rozmowę na czacie
Witajcie w pierwszym, bardzo krótkim i szybkim poradniku.Po...

Synchronizacja pozycji gracza w grze platformowej

Logowanie




Napisano: 27 sierpnia 2017 19:08

Mam kolejne pytanie, tym razem sam sobie nie odpowiem :P

Mianowicie chodzi mi o poruszanie postacią w wieloosobowej grze platformowej. O ile ze zwykłym chodzeniem nie było by problemu, tak tutaj dochodzi skok. No i nie wiem jak się do tego zabrać. W ogóle myślałem aby cały ten system zrobić po stronie servera, gdzie gracz tylko wysyłał by informacje o tym, że idzie i się zatrzymuje, tak samo z grawitacją liczyłby ją server. Także liczę na Waszą pomoc jak to ogarnąć :P



Napisano: 27 sierpnia 2017 19:24

W sumie to nie mam doświadczenia z tym, ale wydaje mi się że to musi być zrobione po stronie serwera. Zakładając że skokiem można dostać się w jakieś miejsce (czy też omija jakieś blokady które na pieszo nie przejdziesz) to jeżeli to byłoby sprawdzane po stronie klienta, to ktoś łatwo mógłby zrobić jakiegoś hacka na pokonywanie blokad których nie powinno się pokonać, czy coś w tym stylu. Po stronie klienta odwarzana byłaby tylko animacja skoku. Może po prostu podczas skoku sewer sprawdza gdzie postać powinna wylądowaćć i czy może tam wylądować (żeby nie wyleciała poza mapę albo na blokadę), no i aktualizuje pozycje i zwraca do klienta czy odtworzyć animację czy nie. 


Napisano: 27 sierpnia 2017 21:51

Dobrze jest zrobić poruszanie tak jak w grze singlowej, wliczając w to fizykę. Wysyłasz co jakiś czas - jeśli pozycja się zmieniła - nową pozycję do serwera. Serwer ją sprawdza czy pozycja od poprzedniej nie zmieniła się zbyt dużo - speedhack? Czy postać jest w niedozwolonym miejscu - serwer koryguje pozycje. Potem wysyła ją do wszystkich użytkowników na mapie. Wysyła ją też dla Ciebie jeśli pozycja została poprawiona. Teraz wystarczy odpowiednio interpolować w klientach z poprzednimi pozycjami.

Przykładowo wysyłanie pozycji odbywa się co 100ms. Zatem od poprzedniej pozycji do naszej nowej pozycji mamy 100ms na zastąpienie obecnej pozycji na nową.

Interpolowanie jest proste i wygląda tak:
currentPosition = lastPosition + (newPosition - lastPosition) * tween;
Gdzie:
tween = (newTime - lastTime) / 0.01; // 0.01s = 100ms

Problem takiego rozwiązania nasuwa się sam - wszystko co się dzieje obok nas jest cofnięte w czasie o 100ms (+ ping).

Możesz też trzymać czas serwera w klientach (i korygować go co jakiś czas).
Wysyłając pakiet pozycji plus kierunek ruchu do innych z serwera do klientów wysyłaj też czas obecny w serwerze.
Odbierając pakiet w kliencie uwzględniaj ten czas i przesuń postać (lub interpoluj) na dobrą pozycję.

Skok możesz potraktować w sumie jako funkcję kwadratową i uwzględniając czas przesunąć się po paraboli trochę dalej.

Napisano: 27 sierpnia 2017 23:39
A jak zrobić z grawitacją? Wysyłać ją do servera, a potem do innych graczy przesuwać o tą wartość i obliczać ją dalej?
Napisano: 27 sierpnia 2017 23:47
Licz w kliencie grawitację innych graczy na lajcie :)
Napisano: 28 sierpnia 2017 00:38
Okej, a jeszcze jedno pytanie. Ostatnim razem jak robiłem platformówkę to do grawitacji używałem czegoś takiego: If GetTickCount < Player(index).TimeGravity + 20 Then Exit Sub End If Player(index).Gravity = Player(index).Gravity + 0.7 Player(index).TimeGravity = GetTickCount Tu sprawdza i dokonuje poprawek... Aby podskoczyć zmieniałem Gravity na -11 Teraz spróbowałem zrobić to za pomocą deltaTime GravityTime = 2.97 * DeltaTime Player(index).Gravity = Player(index).Gravity + GravityTime Teraz aby podskoczyć ustawiam Gravity na -1.2 I działa poprawnie ale problem jest taki, że kiedy sprawiam aby komputer się ciął, skok jest właściwie niewidoczny. Jak to zrobić za pomocą delty, aby działało tak jak powinno?
Napisano: 28 sierpnia 2017 00:54
Zmieniaj Player.Gravity co klatkę o daną deltaTime liniowo. Potem Player.Y = Player.Y + Player.Gravity * Player.Gravity;
avatar
Liczba projektów:
Liczba wpisów na blogu: