Windowsストア向けのFoolアプリ



ポールセザンヌ、カードプレーヤー



昔々、Windows 95にはMicrosoft Heartsゲームがありました。 世界中の対戦相手とオンラインでトランプ。 メモリが適切に機能する場合、Windows for Workgroups 3.11(はい、これらすべてのアーティファクトが見つかりました!)いわゆるNetDDEを使用してローカルネットワークで再生するためのバージョンがありました。



長い間、カードゲームを選ぶ必要はありませんでした。 ことわざにあるように、豊かなもの...高い湾の橋と好みは、完全な無知のために消えました。 ただ一つだけが残っていた -愚か者として消える



これまで私が「バックエンド」の開発に関与したことがないという事実により、状況は複雑でした。 グーグルは正しい場所、 SignalRに私を導いた。



ここでSignalRにいくつかの熱狂的な言葉を言いたいです。 私のニーズに完全に適合する、よく文書化されたライブラリ。 ボアズは、それはWindows専用だと言うでしょう。 iOS用の集合的なファームクライアントを持っているようですが、この問題については詳しく調査しませんでした。



次の質問はホスティングです。 それから私は、Azureが私の腕の下にあるとは思わなかった。



それで私は何が欲しかった?





Azureで何を使用しますか?





それだけです



最近、私は彼らのプッシュ通知配信サービスも使用しました。 しかし、それは高価なようで(月に10ドル)、さらに、Microsoftの請求の不具合のために、これら2つのサービスに1年以上支払っていたことがわかりました! 突合せのサポートにより、彼らは間違いを認識し、1か月もの補償を提供しました。 しばらくして、このサービスを完全に中止し、プッシュ用の署名者を保存するための別のテーブルをデータベースに追加し、メインアプリケーションから自分で送信しました。



現時点では、1か月あたりのホスティングコストは約400 pです。 これは、SQLサーバーのコストのみです。 発信トラフィックが少なく、1か月あたり5 GBの空き容量に収まります。



開発



開発はVisual Studio 2015で行われ、クライアントにはMVVMフレームワークMVVMライトが使用されました。



小さなサーバー「キッチン」(審美眼と弱気な人は見ないほうがいい)



ユーザー接続、プッシュ
public override Task OnConnected() { if (((DateTime.Now - LastPush).TotalSeconds) > 360) { LastPush = DateTime.Now; Task.Run(() => SendNotifications()); } return base.OnConnected(); }
      
      







匿名ゲームを作成する
 /// <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(); } }
      
      







ゲームルームの作成
 /// <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(); } }
      
      







デッキの一番上のカードをのぞきます
 /// <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(); } } }
      
      







相手にメッセージを送る
 /// <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(); } } }
      
      









顧客について



プレーヤーを識別するために、最初にLiveId機能が使用され、次にGraph APIが使用されました。 アプリケーションの最初の起動時に、プレーヤーは自分のアカウントへのアクセスを提供するように招待されます(このアカウントからは、名前と、「ed4dd29dda5f982a」のような匿名IDのみを取得します)。 ただし、プレイヤーは匿名でプレイできますが、ゲームの統計は保持されません。



非匿名プレーヤーごとに保存されます:



1.最初のゲームの日付/最後のゲームの日付

2.プレイヤー名/ニックネーム

3.プレイしたゲームの数/勝った数

4.最後のIPアドレス

5.受け取った賞品



2人の非匿名プレイヤーがゲームでプレイする場合、ゲームを開始する前に、これらのプレイヤーのゲームの統計情報を取得します(お互いにプレイしたゲームの数と誰が勝ったか)。 このため、受信した匿名IDがSQLクエリで使用されます。



左上のスクリーンショットでは、例を見ることができます(クリック可能):







一般統計のスクリーンショット(クリック可能):







さらに、「競争」が各国で開催されています(匿名プレイヤーもここに参加します。情報はIPアドレスから取得されます)。







プレイヤーは短いメッセージを交換できます。



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





シチュエーションハンドラーの例:「カードを取りますが、対戦相手がもう少し私を追加します」:



 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));
      
      





賞品、クッキーなどについて



毎月、最も多くの勝利を収めた最初の5人のプレイヤーには、 「ベルリンを占領するために」バッジが授与されます。 上位50人の参加者には、最高の割合(5人)のバッジが授与されます。 さらに、「エクスプレス」で勝つためのバッジがあります(最後の動きで2、3または4、たとえば6またはジャックがある状況)。 その後、彼らはすべてを一挙にテーブルに置き、あなたはよくやった。 対戦相手があなたに「リスト」を与えるとき、勝利のためのクッキーがあります。 彼はまた頭蓋骨と骨で慰めを得ます。



追加機能について



アプリケーションは無料ですが、InApp Purchasesとして装飾されたさまざまな追加の「バン」があります。





おわりに



このアプリケーションを開発した結果、私は:





質問



プロモーションコードを個人の利害関係者に配布することにより、ヘリコプターからお金飛び散るという Habréの状況はどうでしょうか。 彼らがこれをキックしない場合は、連絡してください。



更新する



YouTube:いくつかのゲームを記録する



All Articles