Progettazione del codice del server di gioco

5

Sto progettando un server di gioco multiplayer in cui i giocatori si trovano nelle stanze. In questo momento ho lezioni per prendermi cura del cliente, networking, ecc. Sto faticando comunque a trovare un design per questa classe Room. Ad esempio, quando voglio cambiare la stanza di un cliente, dovrei chiamare client.changeRoom(newRoom) o newRoom.addClient(client) ? Che dire quando si esce da una stanza, se un cliente si distacca dalla stanza o la stanza si stacca dal cliente? Sono molto confuso qui, semplicemente non voglio finire con un disegno che rimpiangerò in futuro.

    
posta Délisson Junio 02.01.2014 - 19:11
fonte

2 risposte

7

Con i flashback ai miei LPmud giorni, la risposta è che il client (giocatore, oggetto, ...) viene spostato da una stanza all'altra e notifica la stanza precedente (e tutto il resto nella stanza) di questo fatto.

Entrando in una nuova stanza, il client notifica di nuovo tutte le cose nella stanza della sua entrata.

Non tutte le stanze (o le cose nelle stanze) si preoccupano di questo fatto e possono tranquillamente ignorare questo messaggio.

Il modo in cui la progettazione di LPmud funziona è che la stanza è "solo" un tipo speciale di oggetto con funzioni di connivenza per collegarlo ad altre stanze.

Il design della camera che esegue lo spostamento di un giocatore da una posizione all'altra significa parecchie altre ricerche.

Nota: sto usando getRoom () qui come funzione di esempio. Il metodo potrebbe essere stato getEnvironment () che restituisce il contenitore in cui si trova un oggetto ... e tutti gli oggetti hanno un contenitore (una moneta in un sacchetto in un inventario del giocatore coin-> getEnvironment() otterrebbe il sacchetto e coin-> getEnvironment()-> getEnvironment() otterrebbe il giocatore e coin-> getEnvironment()-> getEnvironment()-> getEnvironment() recupera la stanza ...)

Il giocatore dovrebbe fare un me->getRoom()->moveMeTo(newRoom); per muoversi. Questo diventa un po 'macchinoso e a volte, quando le cose vanno male, non hai spazio in cui ti trovi in modo da rendere impossibile il trasferimento in un'altra stanza.

La cosa con l''intelligenza', la cosa che fa il recitare è il giocatore, e quindi quella dovrebbe essere la cosa che fa la recitazione nella stanza.

me->getRoom()->notify_all(me,leaving);
me->moveRoom(newRoom);
me->getRoom()->notify_all(me,arriving);

Prima di precisare che ho detto me->getRoom()->moveMeTo(newRoom); era male sopra e ancora uso me->getRoom()->notify_all(...) sopra, la differenza è che nel caso in cui il client non è da nessuna parte, getRoom () restituisce un oggetto nullo che ignora tutti messaggi e quindi niente va storto lì. Tuttavia, nell'approccio moveMeTo, l'oggetto nullo ignorerebbe tutti i messaggi e non verrebbe spostato da nessuna parte.

Per inciso, potresti voler scaricare un LP mudlib per esaminarlo e considerare come sono strutturati i vari componenti. Un sacco di pensieri di design sono stati messi in esso nel corso degli anni che probabilmente rappresentano molti programmatori-decenni di raffinatezza.

Le posizioni di ganci, funzioni di connivenza e struttura, se esaminate, possono rendere più facili alcune delle tue decisioni, capire e riconsiderare.

    
risposta data 02.01.2014 - 19:35
fonte
5

Quando lo guardi al livello più alto, potrebbe andare in entrambi i modi, senza che la soluzione sia teoricamente migliore dell'altra. Lo sai già, o non faresti la domanda. Questo dilemma è abbastanza comune nella programmazione orientata agli oggetti. Il trucco è guardare più a fondo un livello di astrazione. L'implementazione è quasi sempre molto più pulita in un modo rispetto all'altro. In caso di dubbi, prova ad implementarlo in entrambi i modi e a vedere quale funziona meglio.

Ad esempio, supponi di aver scelto client.changeRoom(newRoom) . Se questa è la scelta sbagliata, il metodo finirà per consistere principalmente di chiamate sull'oggetto newRoom , come:

newRoom.populateFurniture()
newRoom.populateNPCs()
newRoom.attachChat()
newRoom.notifyPlayers()
...

Questo spesso porta a voler rendere pubblici troppi metodi Room , il che aumenta l'accoppiamento. Non avendo familiarità con la tua architettura e non avendo mai creato qualcosa di simile, non so in che modo andrà per te, sebbene add s in genere finisca per funzionare meglio sull'oggetto contenitore. Tuttavia, secondo la mia esperienza, la scelta è stata sempre incredibilmente ovvia dopo averlo provato in entrambe le direzioni.

Inoltre, non sottovalutare la possibilità che il metodo migliore possa essere una combinazione di entrambi, come:

Client::changeRoom(Room newRoom) {
    room.removeClient(this)
    newRoom.addClient(this)
    room = newRoom
}
    
risposta data 02.01.2014 - 20:10
fonte