Autor Wątek: Multiplayer 2D - poruszanie się  (Przeczytany 5063 razy)

Offline SnowyMan

  • Użytkownik

# Październik 30, 2011, 15:14:59
Usuń tego Delay() i komunikację z serwerem przeprowadzaj w osobnym wątku.

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Khazad

  • Użytkownik

# Październik 30, 2011, 15:45:21
Z tego co piszesz wynika że masz socketa blokującego. Powinieneś użyć nieblokującego który w razie braku pakietów do przetworzenia kontynuuje działanie programu i sprawdza w kolejnej pętli czy jest coś co powinien odebrać.

Offline Bula

  • Użytkownik

# Październik 30, 2011, 16:14:59
Usuń tego Delay() i komunikację z serwerem przeprowadzaj w osobnym wątku.
Dzięki! O to chodziło!


Z tego co piszesz wynika że masz socketa blokującego. Powinieneś użyć nieblokującego który w razie braku pakietów do przetworzenia kontynuuje działanie programu i sprawdza w kolejnej pętli czy jest coś co powinien odebrać.
Tak, mam blokującego. Ale jak dam nieblokującego to on po prostu pominie mi jedną funkcję send lub recv i przejdzie dalej i przez to wszystko może się posypać...
« Ostatnia zmiana: Październik 30, 2011, 16:18:26 wysłana przez Bula »

Offline Avaj

  • Użytkownik

# Październik 30, 2011, 23:18:12
Imho komunikacja z serwerem w osobnym wątku to proszenie się o kłopoty.

Polecam zainteresowanie się funkcją select().

Offline Bula

  • Użytkownik

# Październik 31, 2011, 12:19:22
Tak, właśnie mam już pierwsze kłopoty z nowym wątkiem... Często 'wcina' mi wiadomości.
Bez wątku zawsze dochodziły prawidłowo.

Select stosuje się chyba na serwerze, nie?
« Ostatnia zmiana: Październik 31, 2011, 12:22:19 wysłana przez Bula »

Offline SnowyMan

  • Użytkownik

# Październik 31, 2011, 12:23:09
Zastosuj mutex'y tam gdzie aktualizujesz dane w kliencie, żeby wątek ich nie modyfikował gdy są odczytywane.

Offline Bula

  • Użytkownik

# Październik 31, 2011, 12:46:35
Wkleję może kod wątku, bo już się pogubiłem znowu :D

DWORD WINAPI InformationExchange(LPVOID p)
{
while(1)
{
Sleep( *(int*)p );

if (account_logged == true)
{
char *toSend_pos = reinterpret_cast<char*>(&pos_send);
send(sClient, toSend_pos, sizeof(pos_send), 0);

for (int i=0; i<100; i++)
{
pos_send.message[i] = '\0';
}

char players_buffer[20480];
int players_received = recv(sClient, players_buffer, 10240, 0);
players *players_info = reinterpret_cast<players*>(players_buffer);

if (players_received < 1)
{
connetion_lost = true;
draw_popup(216, 56);
Blit(symbol_icon[1], 293, 307);

BrownFont->ShowText("Połączenie z serwerem " ,1,333,310, screen);
BrownFont->ShowText("zostało zerwane!" ,1,333,320, screen);
}


for (int i=0; i<20; i++)
{
if (strcmp(players_info->message[i], "")!=0)
{
players_message[i] = players_info->message[i];
}
players_x[i] = ((map_position.x - players_info->pos_x[i] + 372));
players_y[i] = ((map_position.y - players_info->pos_y[i] + 306));
if ((players_info->p_frame[i]>0) && (players_info->p_frame[i]<=12))
{
players_frames[i] = players_info->p_frame[i];
}
players_online[i] = players_info->online[i];
}
}
}
return 0;
}

I w main po prostu te zmienne są wyświetlane. Chodzenie działa dobrze, ale czat czasem wcina wiadomości. Bez wątku wszystko dochodziło w 100%

Offline Bula

  • Użytkownik

# Październik 31, 2011, 13:20:47
Nie ma tutaj opcji edytuj post?
W każdym razie, już sobie poradziłem. Okazało się że to przez to czyszczenie bufora wiadomości po wysłaniu, to było w złym miejscu i się czyściło czasem przed wysłaniem. Teraz już chyba jest ok.

Offline Bula

  • Użytkownik

# Listopad 06, 2011, 15:44:43
Witam ponownie.

Z tym poruszaniem się męczę już kilka dni i jestem na skraju załamania nerwowego :D
Zrobiłem tak jak radziliście:
wciskam w prawo > na serwerze klient nie przesuwa się o te 2px tylko w chwili  naciśnięcia od razu zmienia współrzędne gracza na te, do których tamten dopiero idzie. I teraz klient wyświetla graczy i sam sobie animuje przechodnie między kratkami. Chodzi ładnie, ale mam pewien problem.

Na razie mam tak (dla 20 graczy):

for (int i=0; i<20; i++)
{
if (players_online[i] == 1)
{
// Przechodzenie mięczy kratkami
if (players_x_old[i] < players_x[i])
{
players_x_old[i] += 2;
}
else if (players_x_old[i] > players_x[i])
{
players_x_old[i] -= 2;
}
else if (players_y_old[i] < players_y[i])
{
players_y_old[i] += 2;
}
else if (players_y_old[i] > players_y[i])
{
players_y_old[i] -= 2;
}

// Wyświetlanie graczy
if ((((position_x+(players_x[i] - 372))/32) < til_position_x+13) && (((position_x+(players_x[i] - 372))/32) > til_position_x-13))
{
if (i != client_id)
{
ShowNick(players_x_old[i], players_y_old[i], player_nicks[i]);
draw_hp(players_x_old[i], players_y_old[i], 0);
Blit(player[players_frames[i]], players_x_old[i], players_y_old[i]);
}
if (players_message[i] != "")
{
ShowMessage(i, players_message[i]);
for (int i=0; i<100; i++)
{
pos_send.message[i] = '\0';
}
}
}
}
}

Problem jest taki, że jak dam else:

// Przechodzenie mięczy kratkami
if (players_x_old[i] < players_x[i])
{
players_x_old[i] += 2;
}
else if (players_x_old[i] > players_x[i])
{
players_x_old[i] -= 2;
}
(...)

To sprawa wygląda tak, że gracz 1 idzie sobie w np prawo, a gracz drugi np na górę. I póki gracz 1 nie przestanie iść, gracz 2 stoi w miejscu i nie rusza się, dopóki tamten się nie zatrzyma.
Powiecie pewnie: "to usuń else i zostaw same if". No fajnie, i to faktycznie działa, tylko wtedy jest tak sytuacja:
gracz idzie w górę i w połowie kratki wciśnie przycisk w prawo - normalnie w kliencie jest tak, że zapamiętywane jest, że wciśnięty został przycisk w prawo, ale samo przechodzenie w prawo zostaje odłożone do momentu, gdy gracz skończy poprzednią kratkę. Wiadomo, zrobione po to żeby nie łaziło po skosie. No i to działa, ale po zmianie else na samo if inni gracze łażą po skosie bez opamiętania.

Moje pytanie:
Czemu po użyciu else, gracze o id większym (są dalej w pętli) muszą czekać, aż gracze o niższym ID zakończą procedurę poruszania się?

Offline Bula

  • Użytkownik

# Listopad 11, 2011, 17:27:29
Z tamtym już sobie poradziłem.

Mam teraz pytanie z innej beczki, a nie chce spamować nowym tematem, bo to małe pytanko.

Czy w takowej grze MMO czas powinien być pobierany z komputera gracza czy z serwera?
Jak myślicie? Z komputera to każdy może sobie zmienić i różne rzeczy mogą z tego wychodzić, chociaż teoretycznie czas jest tylko jako informacja dla gracza i nie ma wpływu na grę...
« Ostatnia zmiana: Listopad 11, 2011, 17:29:11 wysłana przez Bula »

Offline SnowyMan

  • Użytkownik

# Listopad 11, 2011, 18:56:19
Czas w sensie wirtualna data i godzina? Zdecydowanie z serwera - z tym, że taka doba powinna być przyspieszona tzn zajmować np. po 1h na dzień i noc. Dzięki temu możesz np rozdzielić questy i moby na nocne i dzienne :)

Offline Bula

  • Użytkownik

# Listopad 11, 2011, 19:59:07
Nie, chodzi mi o godzinę realną, używaną przy wyświetlaniu czasu wysłania wiadomości np.

Offline SnowyMan

  • Użytkownik

# Listopad 11, 2011, 20:30:39
W takim razie rzeczywisty czas ale podany np. jako 'Wysłano: 14:00 UTC +1".

Offline Asmodeusz

  • Użytkownik
    • Bogumił Wiatrowski: Blog

# Listopad 14, 2011, 02:52:30
Nie, chodzi mi o godzinę realną, używaną przy wyświetlaniu czasu wysłania wiadomości np.
Zdecydowanie czas serwera, nie ma jednak sensu przesyłać go ciągle. Wystarczy raz - przy łączeniu, później niech gra podaje czas na podstawie odebranego+delta. Czas in-game przydaje się do synchronizacji graczy pomiędzy sobą - mogą np. umówić się na 19:00 game-time, co rozwiązuje niezgodności, inaczej ustawione zegarki itp.