Sincronizzazione dei movimenti basata su tessere multigiocatore


8

Devo sincronizzare il movimento di più giocatori su Internet e sto cercando di capire il modo più sicuro per farlo.

Il gioco è basato su tessere, puoi muoverti solo in 4 direzioni e ogni mossa sposta lo sprite di 32px (nel corso del tempo ovviamente). Ora, se semplicemente inviassi questa azione di spostamento al server, che la trasmetterebbe a tutti i giocatori, mentre il tasto walk viene tenuto premuto, per continuare a camminare, devo prendere questo comando successivo, inviarlo al server, e per tutti i clienti, in tempo, o il movimento non sarà più regolare. L'ho visto in altri giochi e può diventare brutto abbastanza velocemente, anche senza ritardi. Quindi mi chiedo se questa è anche un'opzione praticabile. Questo sembra un ottimo metodo per giocatore singolo, dato che è facile, diretto (basta fare la prossima azione di movimento in tempo e aggiungerla a un elenco), e puoi facilmente aggiungere il movimento del mouse (facendo clic su un riquadro), per aggiungere un percorso a una coda, che è stato seguito.

L'altra cosa che mi è venuta in mente è stata l'invio delle informazioni che qualcuno ha iniziato a muoversi in una direzione, e ancora una volta si è fermato o ha cambiato la direzione, insieme alla posizione, in modo che lo sprite appaia nella posizione corretta, o piuttosto in modo che la posizione può essere riparata se è sbagliata. Questo (si spera) dovrebbe creare problemi solo se qualcuno è davvero in ritardo, nel qual caso è prevedibile. Per far funzionare tutto ciò, avrei bisogno di una sorta di coda, in cui i cambi di direzione in entrata e le cose vengono salvate, quindi lo sprite sa dove andare, dopo che il movimento corrente alla tessera successiva è terminato. Questo potrebbe effettivamente funzionare, ma sembra un po 'complicato. Anche se potrebbe essere l'unico modo per farlo, senza il rischio di balbettare. Se viene ricevuto un arresto o un cambio di direzione sul lato client, esso " viene salvato in una coda e il carattere continua a spostarsi sulle coordinate specificate, prima di fermarsi o cambiare direzione. Se il nuovo comando arriva troppo tardi, ci sarà anche la balbuzie ovviamente ...

Sto facendo fatica a decidere un metodo e non sono ancora riuscito a trovare esempi per questo. Il mio problema principale è mantenere fluido il movimento delle tessere, motivo per cui altri argomenti riguardanti la sincronizzazione dei movimenti basati su pixel non aiutano troppo.

Qual è il modo "standard" per farlo?

Risposte:


4

Suppongo che stai parlando di trasferirti in tempo reale. Cercare di interpolare la posizione è probabilmente una causa persa; su una connessione lenta, il tuo stato di gioco potrebbe rimanere sempre più indietro rispetto allo stato di gioco reale. A differenza dell'altro commento, consiglierei di non mettere molta logica di gioco sul lato server. Quando ho implementato questo tipo di soluzioni, il client ha costantemente un socket TCP sul server. Quando lo stato del gioco cambia, invia un messaggio al server, come "client è a x = 10, y = 20". Il server invia il messaggio agli altri client, che provano a gestirlo in base alla propria logica interna. L'uso di TCP garantisce che i tuoi messaggi arrivino in ordine.

Sfortunatamente, anche i giochi AAA non possono gestire ritardi estremi; i giocatori a volte si muovono molto rapidamente, perché i loro stati locali e di rete sono molto fuori controllo. Monitorare il ping di andata e ritorno e calciare gli utenti che sono troppo lontani / lenti aiuterà in questo.


1
+1 per "anche i giochi AAA non possono gestire ritardi estremi;" In realtà nessuno può gestire perfettamente anche piccoli ritardi. Possiamo far sembrare che possiamo però.
Valmond,

3

Fondamentalmente è così che puoi farlo in modo semplice e sicuro (avviso, pseudocodice estremo):

A) Il client (playerid = 5) chiede al server di spostarsi "a destra" (o meglio, a tessera 73,18)

B) Il server controlla la sua grande mappa 2D che contiene giocatori (o ID giocatori per esempio):

 if(map[73][18] == occupied)
     Send back ('Not OK') to client (the case is blocked by another player)
else
    Set the new position as blocked: map[73][18]=5
    Release the old position: map[72][18]=0;
    Send a 'new position: 5, 73,18' message to all players who are nearby (moving client included)

C) I clienti ricevono un messaggio "nuova posizione" (o il giocatore 5 riceve il messaggio "Non OK")

D) i clienti spostano lentamente l'oggetto che ha playerid = 5 verso la sua nuova posizione (o lo crea se non ha un oggetto con playerid = 5)


Bene, grazie, ma il mio problema è quello di mantenerlo regolare sugli altri client per i continui movimenti delle tessere, non il movimento delle tessere in generale ^^
Mars

Imposta la velocità correttamente e compensa il ritardo con, ad esempio, la resa dei conti morta o solo uno spostamento 'stupido' verso l'obiettivo a velocità costante '(o la velocità proporzionale su un certo limite se invii i timestamp lungo le posizioni) e dovresti andare bene.
Valmond,

1

Penso che il metodo che hai descritto sia abbastanza buono, specialmente in un gioco semplicistico in cui sono consentite solo 4 mosse. Ecco come l'ho implementato.

Non conosco standard, ma la prima cosa che mi è venuta in mente è stata solo quella di trasmettere "cambi di input", cambiamenti nell'input di un giocatore, da un giocatore all'altro. Ad esempio, è possibile trasmettere solo messaggi lungo le righe di [tasto premuto, ID tasto, ora] o [tasto rilasciato, ID tasto, ora] e lasciare che il gioco dei giocatori agisca su questi cambiamenti di input. Includere il tempo aiuterà con la correzione del percorso (se il giocatore ha cambiato direzione al momento t, allora sarà necessario fissare "andare avanti" al momento t + 1).

Tuttavia, con questa soluzione potresti riscontrare il problema dei messaggi persi; supponiamo che il messaggio "chiave rilasciata" non sia mai stato inviato? Qualcosa che può aiutare questo è periodicamente il polling dello stato di gioco di un giocatore e la restituzione della posizione corrente del giocatore, così come qualsiasi tasto premuto, o addirittura restituire l'intero stato di gioco. A seconda del numero di giocatori e comandi, è possibile modificarlo per bilanciare il passaggio dei messaggi tra client / server per un buon equilibrio.

Un'altra cosa che puoi esaminare è la pianificazione del percorso. Ad esempio, se il giocatore si è spostato in avanti per 5 secondi, nel prossimo millisecondo le probabilità sono che il giocatore continuerà ad avanzare. In tal caso, è possibile creare una parvenza di previsione del percorso per evitare ritardi. Questo è essenzialmente ciò che sta facendo il metodo sopra, sebbene ciò possa tener conto di percorsi circolari.

Spero che questo abbia aiutato!


1
Il problema con l'invio di input è che se ne perdi uno solo o qualche volta li interpreti nell'ordine sbagliato, il tuo gamestate non andrà più bene, ad es. due client mostreranno diversi 'schermi'.
Valmond,

@Valmond ottimo punto ... in effetti, ho voglia di cancellare la mia risposta, dal momento che in quella luce sembra errato.
Jonathan Pitre,

1
Puoi inviare gli input al server (fino a quando è OK) ma il server dovrebbe (IMO) inviare dati esatti o almeno verificare i dati o forse inviare l'intero gamestate (questo è stato fatto in giochi reali come Blood Bowl ), forse puoi modificare la tua risposta invece di eliminarla :-)
Valmond,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.