برگزاری رقابت آنلاین

دقت کنید که این مستند مخصوص رقابت آنلاین است و برای نیازمندی‌های چت هیچ کاربردی ندارد.

در این مستند، قصد داریم نحوه انجام یک رقابت آنلاین را از طریق SDK بلادرنگ بکتوری به شما نشان دهیم. شما خواهید دید که چگونه پس از آنکه چند بازیکن با هم انطباق داده شدند و یا با چالش کاربران دیگر، در نهایت یک رقابت آنلاین (Realtime Game) را ایجاد کردند، می‌تواند رقابت را آغاز کنند، به یکدیگر پیام ارسال کنند و در نهایت رقابت را به پایان ببرند.

پیش‌نیاز

  1. در صورتی که با سرویس بلادرنگ آشنایی ندارید، به معرفی سرویس بلادرنگ مراجعه کنید.
  2. در صورتی که هنوز با تنظیمات پنل سرویس بلادرنگ آشنا نشده اید، به تنظیمات پنل سرویس بلادرنگ مراجعه کنید.
  3. اگر با سرویس Match-Making آشنایی ندارید، به آشنایی با سرویس Match-Making مراجعه کنید.
  4. اگر هنوز SDK یونیتی را راه‌اندازی نکرده‌اید، به راه‌اندازی SDK یونیتی مراجعه کنید.
  5. در صورتی که با نحوه‌ی اتصال به سرویس بلادرنگ و ایجاد یک چت ساده به کمک آن آشنایی ندارید، مستند اتصال ساده و ارسال پیام را حتما مطالعه کنید.
  6. دو روش درخواست Match-Making و چالش کاربران دیگر را بسته به نیاز اپلیکیشن خود مطالعه کنید.

روش‌های ساخت یک Match

برای ساختن یک رقابت آنلاین (Realtime Game) در بکتوری، شما باید یکی از دو روش زیر را پیاده‌سازی کرده و در نهایت یک شیء BacktoryMatch معتبر به دست آورید.

  1. از بکتوری درخواست Match-Making کنید، بکتوری درخواست‌های Match-Making کاربران مختلف را دریافت کرده و سعی می‌کند کاربرانی که سطح بازی نزدیک به هم دارند را با هم انطباق دهد و در تابع OnMatchFound، در صورتی که به تعداد کافی کاربر هم‌سطح درخواست دهند، یک رقابت آنلاین ایجاد کرده و به شما شیء BacktoryMatch را می‌دهد.
  2. از مفهوم چالش کاربران دیگر استفاده کنید؛ یعنی، کاربر موبایل شما تعدادی کاربر دیگر را مشخص کند و درخواست یک رقابت آنلاین (در اینجا چالش نامیده می‌شود) برای آنها رفته و اگر تعداد کافی از آنها درخواست را بپذیرند، در تابع OnChallengeReady شیء BacktoryMatch در اختیار آنها قرار خواهد گرفت.

در هر یک از دو روش بالا در نهایت یک شیء BacktoryMatch دارید که پیش‌نیاز شروع یک رقابت آنلاین است. در ادامه این مستند تمامی اعمالی که لازم به دانستن است، تا بتوانید یک رقابت آنلاین کامل را پیاده‌سازی کنید، خواهیم گفت.

تنظیمات آغازین Realtime Game

قدم اول در بلادرنگ قبل از شروع بازی، انجام تنظیمات رقابت آنلاین است. شما باید برای SDK بکتوری تعیین کنید که به ازای هر اتفاق در بازی چه کاری انجام دهد. برای این کار کدی مانند زیر لازم است. (فرض بر این است که شیء BacktoryMatch با نام backtoryMatch در اختیار ماست.)

// Create realtime game object with the help of BacktoryMatch object
BacktoryRealtimeGame backtoryRealtimeGame = new BacktoryRealtimeGame (backtoryMatch);

// Set realtime game listener methods
backtoryRealtimeGame.OnGameEvent = (message) =>
{
    // 1. TODO: handle game event here
};
backtoryRealtimeGame.OnDirectMessage = (message) =>
{
    // 2. TODO: handle direct chat message here
};
backtoryRealtimeGame.OnError = (message) =>
{
    // 3. TODO: handle error here
};
backtoryRealtimeGame.OnGameEnded = (message) =>
{
    // 4. TODO: handle game end here
};
backtoryRealtimeGame.OnGameStarted = () =>
{
    // 5. TODO: handle game start here
};
backtoryRealtimeGame.OnGameStartedWebhook = (message) =>
{
    // 6. TODO: handle start webhook here
};
backtoryRealtimeGame.OnPlayerJoined = (message) =>
{
    // 7. TODO: handle player join here
};
backtoryRealtimeGame.OnPlayerJoinedWebhook = (message) =>
{
    // 8. TODO: handle join webhook here
};
backtoryRealtimeGame.OnPlayerLeft = (message) =>
{
    // 9. TODO: handle player leave here
};
backtoryRealtimeGame.OnPublicMessage = (message) =>
{
    // 10. TODO: handle public message here
};
backtoryRealtimeGame.OnServerMessage = (message) =>
{
    // 11. TODO: handle server message here
};

توضیح:

  1. در قدم اول، به کمک شیء BacktoryMatch یک شیء BacktoryRealtimeGame ایجاد می‌کنیم.
  2. در گام بعد، متدهای لیسنر شیء ایجاد شده را مطابق کد بالا مقداردهی می‌کنیم.

در ادامه، به توضیح مبسوط هریک از لیسنرهای فوق می‌پردازیم.

پذیرفتن یک Match

قدم اول در یک رقابت آنلاین بعد از آنکه تنظیمات گفته شده در قسمت قبل را انجام دادید، این است که به آن Match وصل شوید. برای وصل شدن به یک Match کافیست کدی مانند زیر را، در جایی از برنامه که قصد وصل شدن دارید، اجرا کنید:

// Create realtime game object with the help of BacktoryMatch object
BacktoryRealtimeGame backtoryRealtimeGame = new BacktoryRealtimeGame (backtoryMatch);

backtoryRealtimeGame.Join (new BacktoryConnectionStatusListener()
{
    OnOpen = () => {
        Debug.Log("Joined successfully.");
    },
    OnClose = () => {
        Debug.Log("Left successfully.");
    },
    OnError = (message) => {
        Debug.Log("Error in connect and join!");
    }
});

به سادگی با استفاده از ()Join می‌توانید وارد رقابت آنلاین شوید.

دریافت اتصال کاربران دیگر

از لحظه‌ای که شما به رقابت آنلاین وصل شوید، از کاربرانی که پس از شما متصل می‌شوند، مطلع خواهید شد. برای این کار کافیست تابع OnPlayerJoined در تنظیمات رقابت را به شکل زیر پیاده‌سازی کنید:

backtoryRealtimeGame.OnPlayerJoined = (BacktoryMatchPlayerJoinedMessage message) =>
{
    Debug.Log("User with id: " + message.JoinedUserId
        + " and username: " + message.JoinedUsername + " joined the match.");

    Debug.Log(message.AllJoinedUserIds.Count + " users have already joined the match.");
};

همچنین اگر وب‌هوک Join تنظیم کرده باشید و از سمت سرور در این وب‌هوک پیامی ارسال کنید، این پیام توسط تابع زیر به دست اپلیکیشن شما خواهد رسید:

backtoryRealtimeGame.OnPlayerJoinedWebhook = (string message) =>
{
    Debug.Log("Your join webhook sent this message to you: " + message);
};

دریافت شروع بازی (اتصال همه)

پس از آنکه همه بازیکنان به بازی Join شوند، پیام GameStarted به آنها ارسال خواهد شد، دریافت این پیام بدین معنی است که از این لحظه همه در جریان رقابت هستند و می‌توان رقابت آنلاین را آغاز کرد. در صورتی که می‌خواهید اپلیکیشن شما از این اتفاق باخبر شود، تابع OnGameStarted در تنظیمات رقابت را پیاده‌سازی کنید:

backtoryRealtimeGame.OnGameStarted = () =>
{
    Debug.Log("Match finally started, let's do our best");
}

دریافت پیام وب‌هوک شروع بازی

اگر وب‌هوک شروع بازی را فعال‌سازی کرده باشید، جواب وب‌هوک مورد نظر در سرور از طریق تابع OnGameStartedWebhook در تنظیمات رقابت به دست اپلیکیشن شما خواهد رسید. برای چاپ پیام آغاز بازی کدی مانند زیر لازم است:

backtoryRealtimeGame.OnGameStartedWebhook = (string message) =>
{
    Debug.Log("Your start webhook returned this message: " + message);
}

ارسال و دریافت Event در بازی

مهم‌ترین و پرکاربردترین عمل در یک رقابت آنلاین، ارسال پیام GameEvent است. پیام GameEvent به هر اتفاقی که در بازی بیافتد و مربوط به منطق بازی باشد گفته می‌شود، مانند حرکت دادن یک مهره، زدن یک کارت، پاسخ به یک سوال، شلیک یک گلوله و یا هر چیز دیگر… .

ارسال: جهت ارسال یک پیام GameEvent باید کدی مانند زیر را در هر جایی از رقابت که آن GameEvent اتفاق می‌افتد، فراخوانی کرد:

// Send game event
Dictionary<String, String> data = new Dictionary<String, String>
{
    { "Name", "Freeze Card" },
    { "Power", "2" }
};
backtoryRealtimeGame.SendGameEvent("Special Card Used.", data);

همانطور که در بالا می‌بینید، شما به همراه هر Event می‌توانید یک دیکشنری data نیز بفرستید. در صورتی که وب‌هوک Event را تنظیم کرده باشید، این data به دست وب‌هوک می‌رسد و می‌توانید از اطلاعات آن استفاده کنید.

هم‌چنین، می‌توانید تابع SendGameEvent را با یک آرگومان اضافه‌تر نیز مشابه کد زیر فراخوانی کنید. این آرگومان اختیاری ignoreWebhook نام دارد و در صورتی که مقدار آن برابر true باشد، وب‌هوک اصلا در نظر گرفته نمی‌شود؛ انگار که اصلا شما وب‌هوکی ست نکرده باشید. در صورتی که مقدار آن برابر false باشد، مشابه حالتی عمل می‌کند که اصلا این آرگومان را پاس نداده اید. فایده‌ی چنین آرگومانی این است که ممکن است در شرایطی شما بخواهید رویدادهایی بفرستید که نیازی به وب‌هوک ندارند.

bool ignoreWebhook = true;
backtoryRealtimeGame.SendGameEvent("Special Card Used", data, ignoreWebhook);

دریافت: جهت دریافت Eventهایی که توسط بازیکنان در یک رقابت آنلاین جابه‌جا می‌شود، باید از OnGameEvent در تنظیمات رقابت استفاده کرد:

backtoryRealtimeGame.OnGameEvent = (BacktoryRealtimeGameEventMessage message) =>
{
    Debug.Log("Event sent from: " + message.UserId);
    Debug.Log("Message is: " + message.Message);
    Debug.Log("Extra data of event: " + message.Data);
}

به این ترتیب، شما می‌توانید هر Eventای که بخواهید، ارسال و دریافت کنید.

پیام مستقیم به یک بازیکن

ارسال: اگر بازی‌های آنلاین را دیده باشید، در برخی از آنها شما می‌توانید پیام مستقیم به یکی دیگر از بازیکنان بدهید. این پیام‌ها کمک به بهبود بازی می‌کند و راه ارتباطی بین آنها برای چیدن استراتژی است. برای ارسال پیام مستقیم در رقابت آنلاین بکتوری، کدی مانند زیر را باید اجرا کنید:

backtoryRealtimeGame.SendDirectMessage("<USER-ID-HERE>", "Hello, what's up?",
    (response) =>
    {
        // Check result of direct chat
        if (response.Successful)
        {
            Debug.Log("Chat sent successfully");
        }
        else
        {
            Debug.Log("Failed to send, code: "
                + response.Code
                + " and message: "
                + response.Message);
        }
    }
);

دریافت: در طرف دیگر، یعنی اپلیکیشن مقصد، برای آنکه پیام را بتوان دریافت کرد و نمایش داد، باید تابع OnDirectMessage در تنظیمات رقابت را مانند زیر پیاده‌سازی کنید:

backtoryRealtimeGame.OnDirectMessage = (BacktoryGameDirectMessage message) =>
{
    Debug.Log("A direct message from: " + message.SenderUserId);
    Debug.Log("Message is: " + message.Message);
}

ارسال و دریافت پیام به همه بازیکنان

ارسال: معمولا در بازی‌های آنلاین لازم است که بازیکنان بتوانند به یکدیگر پیام ارسال کنند. مثلا برای یک نفر مشکلی پیش می‌آید و می‌خواهد بازی را Pause کرده و مشکل را از طریق چت با بقیه بازیکنان حل کند. برای این کار در رقابت آنلاین بکتوری باید کدی مانند زیر را اجرا کرد:

// Send a message to all players in game
backtoryRealtimeGame.SendPublicMessage ("Hey everyone, please pause :)", (response) =>
{
    // Check result of game chat
    if (response.Successful)
    {
        Debug.Log("Public chat sent successfully.");
    }
    else
    {
        Debug.Log("Failed to send, code: "
            + response.Code
            + " and message: "
            + response.Message);
    }
});

دریافت: جهت دریافت پیام‌های چتی که به همه بازیکنان ارسال می‌شود نیز، کافیست تابع OnPublicMessage در تنظیمات رقابت را مانند شکل زیر پیاده‌سازی کنید:

backtoryRealtimeGame.OnPublicMessage = (BacktoryGamePublicMessage message) =>
{
    Debug.Log("A sent-to-all message in game received from: " + message.SenderUserId);
    Debug.Log("Message is: " + message.Message);
}

دریافت پیام‌های سرور

با وجود پیام‌هایی که توسط بازیکنان به یکدیگر رد و بدل می‌شود و Eventهایی که هر بازیکن ممکن است ارسال کند، گاهی لازم است یک منطق در سرور اتفاقاتی در بازی ایجاد کند. برای مثال در یک بازی سبک دفاع مثل Tower Defence، در زمان‌های خاصی هیولاهایی در بازی ظاهر می‌شود. چنین اتفاقی توسط هیچ بازیکنی تعیین نمی‌شود، بلکه منطق بازی حکم می‌کند که چنین اتفاقی در زمان خاصی بیافتد. چنین کارهایی از طریق قابلیت‌های مدیر در بلادرنگ قابل انجام است.

در صورتی که یک پیام از طریق منطق سرور به یک رقابت آنلاین ارسال شود، تابع OnServerMessage در تنظیمات رقابت فراخوانی خواهد شد. شما کافیست منطق دلخواه خود را در این تابع پیاده‌سازی کنید:

backtoryRealtimeGame.OnServerMessage = (BacktoryGameServerMessage message) =>
{
    Debug.Log("A message from master of the game: " + message.Message);
}

ارسال و دریافت نتیجه بازی

ارسال: در روش‌های تعیین نتیجه بازی گفته شد که می‌توان در تنظیمات بلادرنگ در پنل، روش تعیین نتیجه بازی را مشخص کرد. در روش رای اکثریت کاربران، امکان تعیین نتیجه بازی در اپلیکیشن وجود دارد. اپلیکیشن شما در طول رقابت آنلاین، پیام و Event جا‌به‌جا خواهد کرد و وضعیت بازی را مطابق با منطق خود به‌روزرسانی می‌کند، در پایان انجام رقابت باید به کمک کدی مانند زیر، اسامی برندگان بازی را به سرور اعلام کند:

// Send winner list to server
List<String> winners = new List<String>
{
    "<WINNER-USER-ID-1>",
    "<WINNER-USER-ID-2>",
    ...
    "<WINNER-USER-ID-n>"    
};
backtoryRealtimeGame.SendWinners (winners, "extraData", (response) =>
{
    // Check result of send
    if (response.Successful)
    {
        Debug.Log("Winners sent successfully.");
    }
    else
    {
        Debug.Log("Failed to send, code: "
            + response.Code
            + " and message: "
            + response.Message);
    }
});

در کد بالا کافیست یک لیست از شناسه UserId کاربرانی که از دید اپلیکیشن شما برنده هستند بدهید.

دریافت نتیجه بازی: وقتی همه اپلیکیشن‌های درگیر در بازی نتیجه را ارسال کنند و بکتوری بتواند رای حداکثری بین آنها بگیرد، نتیجه بازی را به همه بازیکنان ارسال خواهد کرد. با این کار، در سمت اپلیکیشن، تابع OnGameEnded در تنظیمات رقابت مطابق کد زیر فراخوانی خواهد شد:

backtoryRealtimeGame.OnGameEnded = (BacktoryGameEndedMessage message) =>
{
    Debug.Log("Match ended now");
    Debug.Log("List of winners is: ");
    for (int i = 0; i < message.Winners.Count; i++)
    {
        Debug.Log(i + ": " + message.Winners[i]);
    }
    Debug.Log("ExtraData: " + message.ExtraData);
}

خروج از بازی

بعد از آن‌که همه‌ی نیازمندی‌های خود از بازی را برآورده کردید، می‌بایست از بازی خارج شوید. برای خارج شدن از بازی، کدی مانند زیر لازم است:

backtoryRealtimeGame.Leave ();

نکته‌ی مهم: به یاد داشته باشید که حتما با پایان بازی، تابع ()Leave را صدا بزنید؛ در غیر این‌صورت، اتصال شما باز مانده و علاوه بر مصرف منابع دستگاه، برای شما هزینه ایجاد می‌کند!

دریافت خروج یک بازیکن

در صورتی که یک بازیکن در میانه رقابت آنلاین از بازی خارج شود و یا عمدا شبکه خود را قطع کند، سرور از طریق OnPlayerLeft در تنظیمات رقابت به همه بازیکنان باقیمانده اطلاع‌رسانی خواهد کرد. برای مثال با دریافت این پیام می‌توانید، بر روی آیکون بازیکن حذف شده، یک علامت قطع شدن و یا ضربدر بزنید و از این طریق به بازیکن اطلاع‌رسانی کنید. نمونه کد برای دریافت این پیام به صورت زیر است:

backtoryRealtimeGame.OnPlayerLeft = (BacktoryGamePlayerLeftMessage message) =>
{
    Debug.Log("User with id: " + message.UserId + " is disconnected from game");
}

دریافت خطای وب‌هوک

اگر در تنظیمات وب‌هوک در پنل، تیک انتقال خطا را فعال کنید، خطاهایی که در وب‌هوک اتفاق می‌افتد، از طریق تابع OnWebhookError در تنظیمات رقابت به دست اپلیکیشن شما خواهد رسید. کد زیر این خطا را دریافت و لاگ می‌زند:

backtoryRealtimeGame.OnWebHookError = (string message) => {
    Debug.Log("Error in server webhook: " + message);
}

به این ترتیب، شما تمامی توانمندی‌هایی که در جریان یک رقابت آنلاین وجود دارد را دیدید و حال می‌توانید یک بازی با قابلیت رقابت آنلاین بسازید. در صورتی که بازخورد، پیشنهاد و یا انتقادی نسبت به مستندات دارید، از طریق ایمیل به پشتیبانی بکتوری ما را در جریان بگذارید.