de Shukant Pal

Cum să vă sincronizați aplicația de joc pe mai multe dispozitive

Dacă aveți probleme cu sincronizarea jocului online, sunteți în locul potrivit!

0*vLBlhBeBsItUgjMR
Fotografie de rawpixel pe Unsplash

La nivelul lor cel mai scăzut, jocurile tipice pot fi împărțite în pași simpli luați de fiecare jucător – se numesc ture și în fiecare tura are loc o mutare. Nu este necesar ca jucătorii să obțină o tură la rând sau să facă o singură mișcare la un moment dat. Pentru a vă sincroniza aplicația de joc pe mai multe dispozitive online, trebuie să vă puteți împărți jocul în acești pași mici.

Modelul nostru

În acest articol, luăm un simplu joc de masă generic pentru doi jucători. Înainte de a face ceva, avem nevoie de doi jucători, nu?

Pentru a configura acest lucru, trebuie să implementați o caracteristică numită matchmaking, unde aveți un nod comun în baza de date Firebase în care fiecare jucător își poate posta provocarea. Provocarea postată conține UID-ul provocatorului și o altă referință la un nod-mutări în care vor fi publicate mutările. Dacă nu ați făcut acest lucru sau aveți probleme cu implementarea acestuia, citiți acest articol potrivire.

Odată ce ambii jucători apucă nodul de mișcări, un jucător trebuie să posteze prima lor mișcare, apoi a doua, apoi prima și așa mai departe. Vom folosi Firebase’s ChildEventListener să primească mișcări postate de adversar.

Scufundați-vă mai adânc în cod

Practic, avem două lucruri de făcut: trimiterea unei mutări și primirea unei mutări. Al nostru FirebaseGameSynchronizer componenta va face exact asta, dar interpretarea mutării se va face de către Modulator tu implementezi.

mutant trimite mutarea folosind sendMoveMsg . Puteți codifica mutarea dvs. într-o varietate de moduri. De exemplu, dacă o piesă este mutată de la (a, b) la (c, d), atunci codificați mutarea ca număr abcd. Aș recomanda cu siguranță această metodă dacă dimensiunea eșantionului dvs. (sau dacă este un joc de societate, dimensiunea de bord) este mai mică de 10.

sendMoveMsg practic încarcă mutarea în nodul cu mișcări mMovesRecordList și se așteaptă ca celălalt jucător să îl asculte.

Odată ce mutarea este publicată, ambii jucători primesc mutarea. Așteaptă un minut … Nu vrei ca mutatorul să primească mutarea – pentru că este posibil să fi făcut deja mutarea la capătul lor și nu vrei să o faci de două ori.

Așadar, am adăugat și o caracteristică interesantă (dacă doriți ca ambii jucători să primească mutarea, eliminați toate referințele la mSelfMoveSoph ): semaforul se mișcă de sine. De fiecare data sendMoveMsg se numește, crește la mSelfMoveSoph. Știm câte mișcări am încărcat acum cu acest semafor.

onChildAdded este apelat ori de câte ori o mișcare este adăugată de Firebase. Ignoră mișcarea dacă semaforul are o valoare; în caz contrar, mMessageModulator este chemat să interpreteze mișcarea și să o arate utilizatorului dvs. Modulator este o interfață funcțională care este complementul codificatorului dvs. de mutare în șir. Este nevoie de acel șir încărcat în Firebase și îl convertește în mișcare.

Așteptați, asta nu va funcționa dacă utilizatorul primește un apel

Da, dacă utilizatorul primește un apel și aplicația dvs. este ucisă … cum va reveni utilizatorul la joc?

Din nou, să facem un Modulator asa:

public class GenericGameFragment implements FirebaseGameSynchronizer.Modulator {
    public void onMoveReceived(boolean isSyncingPast, String encodedMsg) {       // ... do move, show it on UI .....
    }
}

Acum se vor întâmpla două lucruri rele:

  1. Dacă utilizatorul pleacă, FirebaseGameSynchronizer va fi lăsat atașat la nod ascultându-l. Aceasta este o scurgere de utilizare a procesorului de memorie + CPU.
  2. FirebaseGameSynchronizer va avea o referință la fragmentul dvs. – vedeți-l, Modulatorul trebuie să actualizeze interfața de utilizare și are o referință la GenericGameFragment .

Sincronizarea și dezincronizarea cu nodul de mișcare

Am folosit o soluție relativ simplă la problemă. Este o combinație de două lucruri:

  1. Steagul de sincronizare: Când setați proprietatea de sincronizare, FirebaseGameSynchronizer va apela modulatorul, în caz contrar, va stoca mutarea într-un buffer. La setarea din nou a steagului de sincronizare, eliberează mai întâi mișcările în bufferul său.
  2. Atașament: Modulatorul este eliminat ori de câte ori este fragmentul onStop metoda și a pus din nou pe fragment onStart.

Înainte de a utiliza acest „nou” sincronizator, nu uitați să apelați startSync(). Pe onStop, apel stopSync si in onResume apel startSync din nou. Acum, ar trebui să sunați detachModulator și flush în onDestroy.

Verificați acest link pentru implementarea completă: FirebaseGameSynchronization Gist.

Lecturi suplimentare: