Fool App für den Windows Store


Paul Cezanne, Kartenspieler

Es war einmal in Windows 95 ein Microsoft Hearts-Spiel. Online Karten spielen, mit Gegnern auf der ganzen Welt. Wenn der Speicher mir recht tut, dann gab es in Windows for Workgroups 3.11 (ja, ich habe all diese Artefakte gefunden!) Eine Version zum Spielen in einem lokalen Netzwerk mit der sogenannten NetDDE.

Ich musste lange Zeit kein Kartenspiel wählen. Wie sie sagen, was ist reich ... Die hochfliegende Brücke und Vorliebe fielen aufgrund ihrer völligen Unwissenheit weg. Es gab nur noch eins - als dummer Dummkopf zu verschwinden .

Die Situation wurde durch die Tatsache kompliziert, dass ich bisher noch nie an der Entwicklung eines „Backends“ beteiligt war. Googeln führte mich direkt zum richtigen Ort - SignalR .

Hier möchte ich SignalR ein paar begeisterte Worte sagen. Eine gut dokumentierte Bibliothek, die perfekt zu meinen Bedürfnissen passt. Bores wird sagen, dass es nur für Windows ist. Lassen Sie sie vor Neid die Zähne zusammenbeißen. Obwohl es anscheinend kollektive Farm-Clients für iOS gibt, habe ich dieses Problem nicht im Detail untersucht.

Die nächste Frage ist Hosting. Dann dachte ich nicht lange nach, Azure war unter meinen Armen.

Also was wollte ich?


  • Die Art und Weise, wie Spieler eine Verbindung herstellen, sollte Microsoft Hearts ähneln. Die Spieler verbinden sich nacheinander, sobald der richtige Betrag erreicht ist - das Spiel beginnt. Für mich selbst habe ich beschlossen, mich auf ein Eins-zu-Eins-Spiel zu beschränken - und niemand zieht!
  • Am Anfang wird es nur wenige Spieler geben - wie erfahren sie voneinander? Dann kam die Idee auf, alle zu senden, die Push-Benachrichtigungen spielen möchten, sobald jemand die Anwendung startet und eine Verbindung zum Spieleserver herstellt. Um Benutzer nicht mit Stößen zu drosseln, machte er eine Einschränkung "nicht mehr als einmal alle N Minuten".
  • Ich möchte detaillierte Statistiken, Preise, Erfolge usw.
  • Ich möchte Karten mit verschiedenen Designs
  • Ich möchte mit meiner Bekanntschaft spielen und nicht mit jemandem, "den Gott gesandt hat".

Was verwende ich mit Azure?


  • AppService ist in der Tat eine Anwendung, mit der alle Clients eine Verbindung herstellen.
  • SQL Server + SQL-Datenbank - zum Speichern von Spielstatistiken.

Das ist alles.

Kürzlich habe ich auch den Push-Benachrichtigungsverteilungsdienst verwendet. Aber es schien teuer zu sein (10 Dollar pro Monat). Außerdem stellte sich heraus, dass ich aufgrund eines Microsoft-Abrechnungsfehlers mehr als ein Jahr für diese beiden Dienste bezahlt hatte! Stoßende Unterstützung führte dazu, dass sie den Fehler erkannten und bis zu einem Monat Entschädigung anboten. Nach einiger Zeit habe ich diesen Dienst vollständig aufgegeben, meiner Datenbank eine weitere Tabelle hinzugefügt, um Unterzeichner für Push zu speichern und sie selbst von der Hauptanwendung aus zu senden.

Zu diesem Zeitpunkt betragen die Kosten für das monatliche Hosting ca. 400 r. Dies sind nur die Kosten für SQL Server. Ich habe einen kleinen ausgehenden Datenverkehr und er passt in die kostenlosen 5 GB pro Monat.

Entwicklung


Die Entwicklung fand in Visual Studio 2015 statt, für den Client wurde das MVVM-Framework MVVM light verwendet.

Eine kleine Server "Küche" (Ästhetiker und schwache Nerven ist besser nicht zu sehen)


Benutzerverbindung, drücken
public override Task OnConnected() { if (((DateTime.Now - LastPush).TotalSeconds) > 360) { LastPush = DateTime.Now; Task.Run(() => SendNotifications()); } return base.OnConnected(); } 


ein anonymes Spiel erstellen
 /// <summary> ///   .        /// </summary> /// <returns>ID  </returns> async public Task<String> ConnectAnonymous(PlayerInformation pi) { MainSemaphore.WaitOne(); try { string res = String.Empty; string p_ip = Context.Request.GetHttpContext().Request.UserHostAddress; if (NextAnonymGame == null) { NextAnonymGame = new FoolGame(Context.ConnectionId, pi, p_ip, false); res = NextAnonymGame.strGameID; } else { await NextAnonymGame.Start(Context.ConnectionId, pi, p_ip); ActiveGames.Add(NextAnonymGame.strGameID, NextAnonymGame); res = NextAnonymGame.strGameID; NextAnonymGame = null; } return res; } finally { MainSemaphore.Release(); } } 


Schaffung eines Spielzimmers
 /// <summary> ///    /// </summary> /// <returns>   </returns> public String CreatePrivateGame(PlayerInformation pi) { MainSemaphore.WaitOne(); try { string p_ip = Context.Request.GetHttpContext().Request.UserHostAddress; FoolGame game = new FoolGame(Context.ConnectionId, pi, p_ip, true); WaitingPrivateGames.Add(game.strGameID, game); return game.PrivatePass; } finally { MainSemaphore.Release(); } } 


Guck dir die oberste Karte im Deck an
 /// <summary> ///     - /// </summary> /// <param name="gameid"></param> /// <returns></returns> async public Task PeekCard(string gameid) { FoolGame game = null; game = ActiveGames.FirstOrDefault(games => games.Value.strGameID == gameid).Value; if (game != null) { game.GameSemaphore.Wait(); await Task.Delay(35); try { await Clients.Caller.PeekedCard(game.Deck.Peek()); } finally { game.GameSemaphore.Release(); } } } 


Sende eine Nachricht an einen Gegner
 /// <summary> ///  /// </summary> /// <param name="gameid">ID  (  )</param> /// <param name="ChatMessage"> </param> /// <returns></returns> async public Task ChatMessage(string gameid, string ChatMessage) { FoolGame game = null; game = ActiveGames.FirstOrDefault(games => games.Value.strGameID == gameid).Value; if (game != null) { game.GameSemaphore.Wait(); await Task.Delay(35); try { await Clients.OthersInGroup(gameid).ChatMessage(ChatMessage); } finally { game.GameSemaphore.Release(); } } } 



Über den Kunden


Um die Player zu identifizieren, wurde zuerst die LiveId-Funktionalität und dann die Graph-API verwendet. Beim ersten Start der Anwendung wird der Spieler aufgefordert, Zugriff auf sein Konto zu gewähren (von diesem nehme ich nur den Namen und die sogenannte anonyme ID, die ungefähr so ​​aussieht: "ed4dd29dda5f982a"). Der Spieler kann jedoch anonym spielen, aber dann werden die Statistiken seiner Spiele nicht gespeichert.

Für jeden nicht anonymen Spieler werden gespeichert:

1. Datum des ersten Spiels / Datum des letzten Spiels
2. Spielername / Spitzname
3. Anzahl der gespielten Spiele / wie viele davon gewonnen haben
4. letzte IP-Adresse
5. Preise erhalten

Wenn zwei nicht anonyme Spieler im Spiel spielen, erhalte ich vor dem Start die Statistiken der Spiele dieser bestimmten Spieler (wie viele Spiele sie miteinander gespielt haben und wer wie viel gewonnen hat). Dazu wird die empfangene anonyme ID in der SQL-Abfrage verwendet.

Im Screenshot oben links sehen Sie ein Beispiel (anklickbar):



Screenshot der allgemeinen Statistik (anklickbar):



Darüber hinaus findet länderübergreifend ein „Wettbewerb“ statt (auch anonyme Spieler nehmen hier teil, Informationen werden der IP-Adresse entnommen):



Spieler können Kurznachrichten austauschen.

 FoolHubProxy.On<string>("ChatMessage", (chatmessage) => synchrocontext.Post(delegate { PlayChatSound(); ShowMessageToast(chatmessage); }, null)); 

Ein Beispiel für einen Situationshandler „Ich nehme Karten und der Gegner fügt mir ein weiteres Nachher hinzu“:

 FoolHubProxy.On<byte, bool>("TakeOneMoreCard", (addedcard, lastcard) => synchrocontext.Post(delegate { CardModel card = new CardModel(addedcard, DeckIndex); CardsOnTable_Low.Add(card); OpponentsCards.Remove(OpponentsCards.Last()); if (lastcard) { AppMode = AppModeEnum.defeated; } }, null)); 

Über Preise, Cookies usw.


Jeden Monat erhalten die ersten fünf Spieler, die die meisten Siege errungen haben, das Abzeichen „Für die Eroberung Berlins“ . Teilnehmer in den Top 50 erhalten Abzeichen für den besten Prozentsatz an Siegen (ebenfalls fünf). Darüber hinaus gibt es Abzeichen für das Gewinnen mit „Express“ (eine Situation, in der Sie im letzten Zug 2, 3 oder 4 haben, z. B. sechs oder Buchsen). Dann legen sie alles auf einen Schlag auf den Tisch und Sie - gut gemacht. Es gibt Cookies für den Sieg, wenn der Gegner Ihnen eine "Liste" gibt. Er bekommt auch einen beruhigenden mit Schädel und Knochen.

Über zusätzliche Funktionen


Die Anwendung ist kostenlos, hat aber verschiedene zusätzliche "Brötchen", die als InApp-Käufe dekoriert sind:

  • Gruppieren Sie Ihre Karten nach Farbe und Tipps während des Spiels (wenn Sie schlagen oder werfen müssen, werden geeignete Karten nach oben gedrückt)
  • die Fähigkeit, dem Gegner nicht zu zeigen, wie viele Karten Sie in Ihren Händen haben. In einer normalen Situation sieht er es
  • die Möglichkeit, das Spiel immer zuerst zu starten. Andernfalls wird der erste Zug zufällig gespielt.
  • die Fähigkeit, die im Spiel geschlagenen Karten zu sehen
  • die Möglichkeit, einmal pro Spiel in das Deck zu schauen und die nächste Karte herauszufinden
  • die Fähigkeit zu betrügen. Sie können 3 Mal pro Spiel schlagen oder die falsche Karte werfen, im Allgemeinen jede. Aber der Gegner hat die Möglichkeit, nachdem er dies bemerkt hat, die falsche Karte an Sie zurückzugeben.

Fazit


Als Ergebnis der Entwicklung dieser Anwendung habe ich:

  • traf SignalR
  • aktualisiertes SQL im Speicher (Abfragen, gespeicherte Prozeduren, Funktionen)
  • Erfahren Sie, wie Sie Apps in Azure hosten
  • Verblüfft davon, den "Narren" zu spielen.

Frage


Und was ist mit der Situation bei Habré, in der Geld aus einem Hubschrauber gestreut wird, indem Promo-Codes an interessierte Personen persönlich verteilt werden? Wenn sie dafür keinen Kick geben, wenden Sie sich an.

Update


YouTube: Nimm ein paar Spiele auf

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


All Articles