#はじめに
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名入室した時点で自動的にゲームが開始されます。
ゲームのおおよその流れは以下の通りです。
- 入室画面
入室ボタンを押して、入室します。
ゲーム参加者がすでに3名に達している場合は、エラーメッセージ表示され、入室できません。
- ゲーム画面 (ゲーム開始中)
入室するとビデオ通話が開始されます。
ゲームを開始すると、グー、チョキ、パーの役ボタンを選択できるようになります。
- ゲーム画面 (ゲーム終了後)
#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) を送信しています。
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文を使ってメッセージ内容によって、受信後の処理を変えています。
//メッセージ受信
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人の場合はとても冗長になってしまいました。
(もっと短いコードで書ける方法があれば、コメントいただけると嬉しいです。)
//判定: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