Mafia on Go, Vanila JS und WebSocket'ah



Es geht um die Web-Implementierung des beliebten Kartenspiels " Mafia ". Es wurde für Spaß und Erfahrung in der Spieleentwicklung geschrieben. Die erste Version wurde in zwei Wochen Freizeit von der Arbeit geschrieben und gleichzeitig in die zweite Version umgeschrieben. Der Vorteil dieses Spiels ist das Fehlen eines Hosts.

Basierend auf den Entwicklungszielen habe ich mich für die Implementierung / Nichtimplementierung von Features entschieden.
Was genau getan werden musste:

  • Minimales Spiel, das die Regeln des klassischen Spiels wiederholt
  • Stimme der Befehle des Führers auf Clientgeräten
  • Fortsetzung des Spiels auch nach dem Neustart der Browser-Registerkarte

Was nicht geplant war oder verschoben werden konnte:

  • Spielregistrierung
  • Administrationsoberfläche
  • Permanente Speicherung von Spieldaten in einer Datenbank
  • Zeitsynchronisation zwischen Geräten

Backend


https://github.com/mrsuh/mafia-backend
Geschrieben in Go. Es speichert den Status des Spiels und ist für seine Logik verantwortlich.

Während des Spiels können Sie den Server kontaktieren, um die vollständigen Informationen zu erhalten:

curl 'http://127.0.0.1:8000/info?game=23' | python -m json.tool 

Spielinformationsanzeige
{
"event": "greet_mafia",
"event_status": 2,
"id": 23,
"is_over": false,
"iter": 1,
"players": [
{
"addr": "172.18.0.1:51438",
"createdAt": "2018-09-23T14:39:29.631475779Z",
"id": 33309,
"name": "Anton",
"role": 4
},
{
"addr": "172.18.0.1:51440",
"createdAt": "2018-09-23T14:39:32.867080927Z",
"id": 5457,
"name": "username:0",
"role": 2
},
{
"addr": "172.18.0.1:51442",
"createdAt": "2018-09-23T14:39:32.882463945Z",
"id": 14214,
"name": "username:2",
"role": 1
},
{
"addr": "172.18.0.1:51444",
"createdAt": "2018-09-23T14:39:32.895209072Z",
"id": 63759,
"name": "username:1",
"role": 3
}
],
"win": 0
}


Oder finden Sie den Status des Servers heraus:

 curl 'http://127.0.0.1:8000/health' | python -m json.tool 

Serverstatusinformationen anzeigen
{
"runtime.MemStats.Alloc": 764752,
"runtime.MemStats.NumGC": 0,
"runtime.MemStats.Sys": 4165632,
"runtime.MemStats.TotalAlloc": 764752,
"runtime.NumGoroutine": 14
}


Um festzustellen, ob der Player noch aktiv ist, sendet das Backend einen Herzschlag. Wenn ein Spieler nach einem bestimmten Intervall nicht reagiert, wird er aus dem Spiel ausgeschlossen. Wenn sich ein Spieler vor dem Ende des Intervalls erneut verbindet (das Netzwerk ist verschwunden), kann er das Spiel fortsetzen.

Für einen stabilen Betrieb wurde das Backend durch Unit-Tests mit der Standard- Go-Bibliothek abgedeckt, in denen die wichtigsten Betriebsszenarien überprüft werden.

 go test mafia-backend/src -cover ok mafia-backend/src 1.315s coverage: 70.7% of statements 

Frontend


https://github.com/mrsuh/mafia-frontend
Es ist in reinem JS geschrieben und mit Grunt erstellt .
Es enthält keine Logik.

Wenn ein Ereignis mit dem Backend auftritt, wird die gewünschte Seite gerendert, die an es gesendeten Daten angezeigt und der Sound des neuen Ereignisses abgespielt.

Das Frontend speichert die Spiel- und Spieler- IDs in LocalStorage oder in der Browser- Abfragezeichenfolge (wenn Sie mehrere Registerkarten in einem Browser für verschiedene Spieler ausführen müssen). Das völlige Fehlen von Logik sowie die Speicherung der Grundparameter des Spiels ermöglichen es, auch nach dem erneuten Laden der Seite den Status des Spiels wiederherzustellen.

Der Browser verhindert die automatische Wiedergabe von Sounds ohne Benutzereingriff (z. B. Drücken einer Taste). Um Sounds für jedes Ereignis abzuspielen, das mit dem Backend geliefert wird, wurde nur 1 JavaScript-Audioobjekt erstellt. Jeder Spieler muss eine Taste drücken, um das Spiel zu starten. In diesem Moment wird das Audio-Objekt aktiv (zur Wiedergabe verfügbar). Anschließend kann er den src-Parameter ändern, um ohne Benutzereingriff verschiedene Sounds abzuspielen.

Um das Spiel zu testen, wurde ein „Bot“ geschrieben, der mit sich selbst spielen kann.
Öffnen Sie einfach die Registerkarte Browser, auf der die Parameter angeben, dass Sie den Test ausführen möchten

 http://127.0.0.1?master=1&test=1&sound=0&testUsersCount=5 

und ermöglichen das Öffnen neuer Registerkarten aus JavaScript für diese Domain.
Nach dem Start des Spiels werden 5 weitere Registerkarten mit Spielern geöffnet und sie beginnen untereinander zu spielen.

Interaktionsprotokoll


Das WebSocket- Protokoll wurde ausgewählt, da ein ständiger bidirektionaler Datenaustausch zwischen Backend und Frontend erforderlich ist und beide Sprachen unterstützt werden.

Spielereignisse


Das ganze Spiel ist in Ereignisse unterteilt:

Ereignisse
  • Spiel
    • erstellen
    • beitreten
    • starten
    • vorbei
    • wieder verbinden

  • Tag
    • starten

  • Nacht
    • starten

  • Bürgergruß
    • starten
    • Rolle
    • Ende

  • Mafia-Gruß
    • starten
    • Spieler
    • Ende

  • Gericht
    • starten
    • Spieler
    • Ende

  • Mafia
    • starten
    • Spieler
    • Ende

  • Arzt
    • starten
    • Spieler
    • Ende

  • Mädchen
    • starten
    • Spieler
    • Ende

  • Sherif
    • starten
    • Spieler
    • Ende



Ereignisse haben einen Anfang, ein Ende und einen Inhalt.
Zu Beginn und am Ende des Events wird eine Benachrichtigung an alle aktiven Spieler gesendet, die bestätigt werden muss. Das Spiel wird erst nach Bestätigung dieses Ereignisses durch alle aktiven Spieler fortgesetzt (z. B. erst nach dem Abspielen der Sounddatei).

Docker


Das ganze Spiel kann mit Docker ausgelöst werden :
docker-compose.yml

 version: '3' services: mafia-frontend: image: mrsuh/mafia-frontend:latest container_name: mafia_frontend ports: - 9080:80 mafia-backend: image: mrsuh/mafia-backend:latest container_name: mafia_backend ports: - 8000:8000 

Es reicht aus, Docker zu installieren (falls Sie dies noch nicht getan haben), den Text docker-compose.yml zu kopieren und den folgenden Befehl auszuführen:

 docker-compose up 

Danach können Sie die Registerkarte Spiel im Browser öffnen:

 http://127.0.0.1:9080 

Fazit


Hier können Sie sehen, wie sich das Ergebnis herausstellte (Wiedergabegeschwindigkeit um das 1,5-fache erhöht).


Nach fast einem Monat Entwicklungszeit in meiner Freizeit habe ich ein ziemlich stabiles Spiel bekommen, das Sie mit Freunden spielen können. Das Spiel hält dem erneuten Laden von Seiten oder vorübergehenden Netzwerkausfällen stand. Die Sprachausgabe von Ereignissen auf Geräten funktioniert, allerdings ohne Zeitsynchronisation. Eine Weiterentwicklung des Spiels ist nicht geplant.

PS: Danke an Lera für die Sprachausgabe des Spiels.

Source: https://habr.com/ru/post/de423821/


All Articles