Help us understand the problem. What is going on with this article?

文系出身1年目SEがagora.io(WebRTC SDK)を利用してじゃんけんゲームをつくってみたお話

はじめに

agora.ioとは、アメリカのagora社が提供しているライブ配信・ビデオ通話向けのSDKです。

このSDK(今回はWebRTC)を利用して、同じ部署の若手3名でじゃんけんゲームをつくってみました。
こちらで公開しています。

開発環境

Windows10 pro 64bit
Google Chrome
Visual Studio Code
GitHub
Agora Video SDK for Web 2.8.0
Agora RTM SDK for Web 0.9.1

開発工程と工数(人日)

  • 要件定義:1
  • 画面設計:0.5
  • 内部設計:1.25
  • 実装:8.25
  • テスト・修正:6.5

じゃんけんゲームの概要

ビデオ通話しながら、じゃんけんをするゲームです。

ゲーム参加者は、2~3名です。
2名の場合、参加者どちらかが「はじめる」ボタンを押してゲームを開始します。
3名の場合、3名入室した時点で自動的にゲームが開始されます。

ゲームのおおよその流れは以下の通りです。

キャプチャ.PNG

  • 入室画面

入室ボタンを押して、入室します。
ゲーム参加者がすでに3名に達している場合は、エラーメッセージ表示され、入室できません。

join.PNG

  • ゲーム画面 (ゲーム開始中)

入室するとビデオ通話が開始されます。
ゲームを開始すると、グー、チョキ、パーの役ボタンを選択できるようになります。
game1.PNG

  • ゲーム画面 (ゲーム終了後)

ゲーム参加者全員が役を選択し終えると、結果が表示されます。
game2.PNG

SDKの利用用途

  • Agora Video SDK for Web : 映像音声の送受信、映像音声のミュート・ミュート解除

  • Agora RTM (Real-time Messaging) SDK for Web : ゲーム参加者数の取得、ゲーム開始情報の送受信、役 (グー、チョキ、パー) の送受信

※RTM SDKは、それまでメッセージ送受信用に提供されていたSignaling SDKの後継サービスで、2019年8月に正式リリースされました。Signaling SDKと比べて、通信の安定性や1秒あたりに送信できるメッセージ数が向上しています。

実装

  • ゲーム開始情報・役の送信

RTM SDKのsendMessageというAPIを利用して、ゲーム開始情報や役を対戦相手に送信します。
このAPIの引数に送信するメッセージを入れています。
以下のコードでは、自分が選択した役 (localRole) を送信しています。

AgoraRTM-JankenGame.js
agoraRTMchannel.sendMessage({text:localRole}).then(() => {
    console.log(agoraRTMaccountName + " succeed in sending role: " + localRole);
    local_client_status.src = "icons/fight!.png";
    btnRoleDisable();
    checkMlist();
}).catch(error => {
    console.log(agoraRTMaccountName + " failed to sending role" + error);
    alert("もう一度選択して下さい。");
});
  • ゲーム開始情報・役の受信

一方受信側は、onというAPIの第1引数を'ChannelMessage'にして、メッセージ受信イベントを取得しています。
受信するメッセージは、ゲーム開始情報と役の情報2種類あるので、if文を使ってメッセージ内容によって、受信後の処理を変えています。

AgoraRTM-JankenGame.js
//メッセージ受信
function getChannelMessages(){
    agoraRTMchannel.on('ChannelMessage', function(message, memberId){
        console.log(agoraRTMaccountName + " got message: " + message.text + " from " + memberId);
        console.log("gameStatus is " + gameStatus);
        remoteMessage = message.text;
        if(remoteMessage == "startGame()" && gameStatus == false){
            startGame();
        }else if(remoteMessage == "1" || remoteMessage == "2" || remoteMessage == "3"){
            remoteMessage = Number(remoteMessage);
            console.log("typeof remoteMessage is " + typeof remoteMessage);
            console.log("remoteMessage is " + remoteMessage);
            getRoles(remoteMessage, memberId);
        }
    });
}
  • 勝ち負けの判定

グー:1、チョキ:2、パー:3として、それぞれの数値の引き算の値で、じゃんけんの勝ち負けの判定をおこないました。
2人でゲームをした場合のコードは、それなりにすっきり書けたのですが、3人の場合はとても冗長になってしまいました。
(もっと短いコードで書ける方法があれば、コメントいただけると嬉しいです。)

AgoraRTM-JankenGame.js
//判定:2人で遊ぶ場合
function judgeResult2(localRole, remoteRole1){
    main.src = "icons/result.png";
    console.log("localRole is " + localRole);
    console.log("remoteRole1 is " + remoteRole1);
    var diff = localRole - remoteRole1;
    console.log("localRole - remoteRole1 = " + diff);

    if(diff == 0){
        result = "あいこ";
        remote_client1_status.src = picDraw;
        local_client_status.src = picDraw;
    }else if(diff == -1 || diff == 2){
        result = "勝ち";
        remote_client1_status.src = picLoser;
        local_client_status.src = picWinner;
    }else{
        result = "負け"
        remote_client1_status.src = picWinner;
        local_client_status.src = picLoser;
    }
    console.log("Result is " + result);

    dispRemoteRole1();
    dispLocalRole();
    gameStatus = false;
    console.log("gameStatus is " + gameStatus);

    setTimeout("moveSelect()", 5000);
}

//判定:3人で遊ぶ場合
function judgeResult3(localRole, remoteRole1, remoteRole2){
    main.src = picResult;
    console.log("localRole is " + localRole);
    console.log("remoteRole1 is " + remoteRole1);
    console.log("remoteRole2 is " + remoteRole2);
    var diff1 = localRole - remoteRole1;
    var diff2 = localRole -remoteRole2; 
    var diff3 = remoteRole1 - remoteRole2;
    console.log("localRole - remoteRole1 = " + diff1);
    console.log("localRole - remoteRole2 = " + diff2);
    console.log("remoteRole1 - remoteRole2 = " + diff3);
    if(((diff1 == 0)&&(diff2 == 0)&&(diff3 == 0))||((localRole != remoteRole1)&&(localRole != remoteRole2)&&(remoteRole1 != remoteRole2))){
        result = "あいこ";
        remote_client1_status.src = picDraw;
        remote_client2_status.src = picDraw;
        local_client_status.src = picDraw;
    }else if(((diff1 == -1)||(diff1 == 2))&&((diff2 == -1)||(diff2 == 2))&&(diff3 == 0)){
        result = "勝ち";
        remote_client1_status.src = picLoser;
        remote_client2_status.src = picLoser;
        local_client_status.src = picWinner;
    }else if((diff1 == 0)&&((diff2 == -1)||(diff2 == 2))&&((diff3 == -1)||(diff3 == 2))){
        result = "勝ち";
        remote_client1_status.src = picWinner;
        remote_client2_status.src = picLoser;
        local_client_status.src = picWinner;
    }else if(((diff1 == -1)||(diff1 == 2))&&(diff2 == 0)){
        result = "勝ち";
        remote_client1_status.src = picLoser;
        remote_client2_status.src = picWinner;
        local_client_status.src = picWinner;
    }else if(diff3 == 0){
        result = "負け";
        remote_client1_status.src = picWinner;
        remote_client2_status.src = picWinner;
        local_client_status.src = picLoser;
    }else if(diff2 == 0){
        result = "負け";
        remote_client1_status.src = picWinner;
        remote_client2_status.src = picLoser;
        local_client_status.src = picLoser;
    }else{
        result = "負け";
        remote_client1_status.src = picLoser;
        remote_client2_status.src = picWinner;
        local_client_status.src = picLoser;
    }
    console.log("Result is " + result);

    dispRemoteRole1();
    dispRemoteRole2();
    dispLocalRole();
    gameStatus = false;
    console.log("gameStatus is " + gameStatus);

    setTimeout("moveSelect()", 5000);    
}

感想

  • ミュート機能等はAPIをひとつコールするだけで実装できたので、思っていたよりも簡単でした。
  • 開発をしていくうちに変数名をたくさん使うようになり、変数名のつけ方に悩みました。
  • 3人で共同開発したので、それぞれコードの書き方に違いがあったため、エラーが出たり、GitHubにコミットした際にコンフリクトが発生したりしたので、大変でした。
  • テストをする度に新しいバグが見つかり、完成まで想像以上に時間がかかってしまいました。
  • Video SDKには、BGMを流せるAPIもあったので、今後はそれを使ってもっと楽しいゲームにしたいです。

参照

Agora.io Developer Center : Agora Web SDK API Reference
Agora.io Developer Center : RTM API Reference
Bootstrap

最後に

agora.ioに関するお問い合わせはこちらから
スクリーンショット 0001-08-15 13.41.56.png

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away