كذبة التطبيقات لمتجر ويندوز


بول سيزان ، بطاقة اللاعبين

ذات مرة ، في نظام التشغيل Windows 95 ، كانت هناك لعبة Microsoft Hearts. لعب الورق عبر الإنترنت ، مع المعارضين في جميع أنحاء العالم. إذا كانت الذاكرة تخدمني بشكل صحيح ، فعندئذٍ في Windows for Workgroups 3.11 (نعم ، لقد وجدت كل هذه القطع الأثرية!) كان هناك إصدار للتشغيل على شبكة محلية باستخدام ما يسمى NetDDE.

لم يكن لدي لاختيار لعبة الورق لفترة طويلة. كما يقولون ، ما هو الأثرياء ... سقط الجسر والتفضيل عالي السرعة بسبب جهلهما الكامل. لم يتبق سوى شيء واحد - أن تختفي كغبي غبي.

كان الوضع معقدًا بسبب حقيقة أنني لم أشارك مطلقًا حتى الآن في تطوير "خلفية". قادني غوغلينغ إلى المكان الصحيح - SignalR .

أنا هنا أريد أن أقول بضع كلمات متحمسة لـ SignalR. مكتبة موثقة جيدًا تناسب احتياجاتي تمامًا. سيقول المملون أنه فقط من أجل Windows ، دعهم يصرخون بأسنانهم بالحسد. على الرغم من أنه يبدو أن هناك عملاء جماعيين لنظام iOS ، إلا أنني لم أدرس هذه المسألة بالتفصيل.

السؤال التالي هو استضافة. ثم لم أفكر طويلا ، كانت أزور تحت ذراعي.

إذن ماذا أردت؟


  • يجب أن تكون طريقة اتصال اللاعبين مماثلة لـ Microsoft Hearts. يقوم اللاعبون بتوصيل واحد تلو الآخر ، بمجرد الحصول على المبلغ المناسب - تبدأ اللعبة. بنفسي ، قررت أن أقصر نفسي على لعبة فردية - ولا يوجد تعادل واحد!
  • سيكون هناك عدد قليل من اللاعبين في البداية - كيف يتعرفون على بعضهم البعض؟ ثم ظهرت الفكرة لإرسال كل من يرغب في تشغيل إشعارات الدفع في الوقت الذي يقوم فيه شخص ما بتشغيل التطبيق والاتصال بخادم اللعبة. من أجل عدم اختناق المستخدمين بدفعات ، قام بتقييد "لا يزيد عن مرة واحدة كل دقيقة N".
  • أريد إحصائيات مفصلة ، جوائز ، إنجازات ، إلخ.
  • اريد بطاقات من تصميمات مختلفة
  • أريد أن ألعب مع أحد معارفي ، وليس مع أي شخص "أرسله الله".

ما الذي يمكنني استخدامه مع Azure؟


  • AppService هو ، في الواقع ، تطبيق يتصل به جميع العملاء.
  • مزود خادم + قاعدة بيانات SQL - لتخزين إحصاءات اللعبة.

هذا كل شيء.

لقد استخدمت مؤخرًا خدمة توزيع إعلام الدفع الخاصة بهم. ولكن يبدو أنه مكلف (10 دولارات في الشهر) ، بالإضافة إلى ذلك ، اتضح أنه بسبب خلل فوترة في Microsoft ، دفعت ثمن هاتين الخدمتين لأكثر من عام! أدى التأييد إلى حقيقة أنهم أدركوا الخطأ وعرضوا ما يصل إلى شهر من التعويض. بعد مرور بعض الوقت ، تخلت عن هذه الخدمة تمامًا ، وأضفت جدولًا آخر إلى قاعدة البيانات الخاصة بي لتخزين التوقيعات للدفع وإرسالها بنفسي من التطبيق الرئيسي.

في هذا الوقت ، تبلغ تكلفة الاستضافة الشهرية حوالي 400 ص. هذه ليست سوى تكلفة خادم SQL. لدي حركة مرور صادرة صغيرة وتناسبها مع 5 غيغابايت مجانًا شهريًا.

التنمية


تم التطوير في Visual Studio 2015 ، بالنسبة للعميل ، تم استخدام ضوء MVVM framework 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. في أول تشغيل للتطبيق ، يُدعى اللاعب إلى توفير إمكانية الوصول إلى حسابه (منه ، أغتنم فقط الاسم والمعرّف المجهول المجهول ، والذي يبدو كالتالي: "ed4dd29dda5f982a"). ومع ذلك ، يمكن للاعب اللعب بشكل مجهول ، ولكن بعد ذلك لا يتم الاحتفاظ بإحصائيات ألعابه.

لكل لاعب غير مجهول يتم تخزين:

1. تاريخ أول لعبة / تاريخ آخر لعبة
2. اسم اللاعب / اللقب
3. عدد الألعاب التي لعبت / كم منها فاز
4. عنوان IP الأخير
5. الجوائز المستلمة

إذا لعب لاعبين غير مجهولين في اللعبة ، فقبل أن أحصل على إحصاءات عن ألعاب هؤلاء اللاعبين المعينين (عدد الألعاب التي لعبوها مع بعضهم البعض والذين فازوا بها). للقيام بذلك ، يتم استخدام معرف مجهول تلقي في استعلام 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)); 

حول الجوائز وملفات تعريف الارتباط وما إلى ذلك


كل شهر ، يحصل أول خمسة لاعبين فازوا بأكبر عدد من الانتصارات على شارة "للاستيلاء على برلين" . يتم منح المشاركين في أفضل 50 شارات لأفضل نسبة من الانتصارات (أيضًا خمسة). بالإضافة إلى ذلك ، هناك شارات للفوز بـ "Express" (وضع يكون لديك في الخطوة الأخيرة 2 أو 3 أو 4 ، ستة أو مقابس). ثم وضعوا كل شيء على الطاولة في ضربة واحدة وأنت - أحسنت. هناك ملفات تعريف الارتباط لتحقيق النصر ، عندما يمنحك الخصم "قائمة". كما انه يحصل على واحد مريح ، مع جمجمة وعظام.

حول أي وظائف إضافية


التطبيق مجاني ، لكن لديه العديد من "الكعك" الإضافية المزينة باسم مشتريات InApp:

  • قم بتجميع البطاقات الخاصة بك حسب البدلة والنصائح أثناء اللعبة (عندما تحتاج إلى الضغط أو الإقلاع ، يتم دفع البطاقات المناسبة لأعلى)
  • القدرة على عدم إظهار الخصم لعدد البطاقات التي في يديك. في وضع طبيعي ، يرى ذلك
  • الفرصة دائما لبدء اللعبة أولا. خلاف ذلك ، يتم لعب الخطوة الأولى بشكل عشوائي.
  • القدرة على رؤية البطاقات تتعرض للضرب في اللعبة
  • فرصة لإلقاء نظرة خاطفة على سطح السفينة مرة واحدة لكل لعبة ومعرفة البطاقة التالية
  • القدرة على الغش. يمكنك التغلب على 3 مرات لكل لعبة أو إرم البطاقة الخاطئة ، بشكل عام أي. لكن الخصم لديه الفرصة ، بعد أن لاحظت ذلك ، لإعادة البطاقة الخطأ إليك.

الخاتمة


نتيجة لتطوير هذا التطبيق ، أنا:

  • التقى SignalR
  • تحديث SQL في الذاكرة (الاستعلامات ، الإجراءات المخزنة ، وظائف)
  • تعلمت كيفية استضافة التطبيقات على Azure
  • صعق من لعب "أحمق".

سؤال


وماذا عن الوضع مع هابري مع نثر المال من طائرة هليكوبتر من خلال توزيع أكواد الترويجي على الأشخاص المهتمين بشكل شخصي؟ إذا لم يعطوا ركلة لذلك ، فاتصل.

تحديث


يوتيوب: تسجيل اثنين من الألعاب

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


All Articles