Admin.js¶
admin ページにアクセスするには、index.html の Admin をクリックします。ユーザー名とパスワード (どちらも admin) を入力後、プレイヤーテーブルを操作して、ゲームコンテンツを操作できます。 web-admin.js のドキュメントに、アクションに使用するコードがすべて含まれています。
このファイルには 1 つの class があります。
In This Section
class AdminController¶
AdminController class には、ストリームへの接続、適切な情報表示、ゲームへのコマンド送信を行うすべてのメソッドが含まれています。
class 以外では、 AdminController のインスタンスを作成し、それに対して start() を実行してストリームへの接続を開始します。
let admin = new AdminController("video_player_hidden");
admin.start();
以下のセクションでは、AdminController class の内容について説明します。
start¶
start()
start メソッドがサービスへの接続を開始します。接続が適切に実行できると、検出した IChannelJoinResponse()
で onChannelJoin
を実行します。この処理は、 web.js
ファイルと同一のものです。
// Starts the connection to the services
start() {
fetch("/api/public/channels/join", {
method: "POST"
})
.then(data => data.json())
.then(res => this.onChannelJoin(res))
.catch(error => genvid.error(`Can't get the stream info: ${error}`));
}
onChannelJoin¶
onChannelJoin(joinRep)
onChannelJoin メソッドは、サービスとチャネルに接続後、Genvid クライアントを作成します。このプロセスで検出された情報と、class 作成プロセスで送信された videoPlayerId を使用してクライアントを作成します (これは AdminController class の引数です)。この処理は web.js
ファイルと同様のものですが、こちらはメソッドを必要としません。
その後、この class に特定のイベントを関連付ける必要があります。
- onStreamsReceived
- ストリームコンテンツを受信した時にトリガされます (ゲームデータの取得に使用)
次に、 start()
メソッドでクライアントを開始します。
// Creates the genvid Client and the function listening to it
onChannelJoin(joinRep) {
this.client = genvid.createGenvidClient(joinRep.info, joinRep.uri, joinRep.token, this.videoPlayerId);
this.client.onStreamsReceived((streams) => {
this.onStreamsReceived(streams);
});
this.client.start();
}
onStreamsReceived¶
onStreamsReceived(dataStreams)
onStreamsReceived` メソッドは、常に更新を必要とする様々なタスクを実行します。Genvid クライアント用に作成したストリームとフレームごとに、Web サイトが受信した際にコールします。この処理は、 web.js
ファイルの中で全く同じ方法で行います。
まず、プレイヤーテーブルが作成されていないことを確認します。
さまざまな処理を行う前に、ゲームデータを取得してから、そのデータが有効であることを確認する必要があります。
データの妥当性が確認できたら、データ (キューブ) からオブジェクトリストを取得し、JSON データを変換します。
オブジェクトごとにループ処理を作成し、それぞれにプレイヤーテーブルを作成します。
プレイヤーテーブルのボタンクリックを検知するためのイベントリスナーも追加します。
ループ処理後に、シーンとカメラ変更のための 2 つのボタンを作成します。
シーンとカメラ変更ボタンのクリックを検知するためのイベントリスナーを追加します。
onStreamsReceived(dataStreams) {
if (this.playerTableSetup) {
return;
} else {
this.playerTableSetup = true;
for (const stream of dataStreams.streams) {
const datas = stream.frames[0];
if (datas && stream.id === "GameData") {
const cubeData = JSON.parse(datas.data);
this.canChangeCamera = !!cubeData.camera; // will be used by changeCamera
this.canChangeScene = !!cubeData.scene; // will be used by changeScene
let cubeControlPanel = document.getElementById("admin_prototype_panel");
for (let cube of cubeData.cubes) {
let cubeControlPanelClone = cubeControlPanel.cloneNode(true);
cubeControlPanelClone.id = cube.name;
cubeControlPanelClone.querySelector(".table_name").innerText = cube.name;
document.querySelector(".admin_table_section").append(cubeControlPanelClone);
let upButton = cubeControlPanelClone.querySelector(".upDirection");
upButton.addEventListener("click", () => {
this.setDirection(cube.name, 0, 1);
}, false);
let downButton = cubeControlPanelClone.querySelector(".downDirection");
downButton.addEventListener("click", () => {
this.setDirection(cube.name, 0, -1);
}, false);
let leftButton = cubeControlPanelClone.querySelector(".leftDirection");
leftButton.addEventListener("click", () => {
this.setDirection(cube.name, -1, 0);
}, false);
let rightButton = cubeControlPanelClone.querySelector(".rightDirection");
rightButton.addEventListener("click", () => {
this.setDirection(cube.name, 1, 0);
}, false);
let resetButton = cubeControlPanelClone.querySelector(".reset");
resetButton.addEventListener("click", () => {
this.reset(cube.name);
}, false);
let slowerButton = cubeControlPanelClone.querySelector(".slower");
slowerButton.addEventListener("click", () => {
this.changeSpeed(cube.name, 0.8);
}, false);
let fasterButton = cubeControlPanelClone.querySelector(".faster");
fasterButton.addEventListener("click", () => {
this.changeSpeed(cube.name, 1.25);
}, false);
}
cubeControlPanel.remove();
let cameraButton = document.getElementsByClassName("cameraChange")[0];
if(this.canChangeCamera) {
cameraButton.addEventListener("click", () => {
this.changeCamera();
}, false);
} else {cameraButton.setAttribute("disabled", "");}
let sceneButton = document.getElementsByClassName("sceneChange")[0];
if (this.canChangeScene) {
sceneButton.addEventListener("click", () => {
this.changeScene();
}, false);
} else {sceneButton.setAttribute("disabled", "");}
this.client.close(); // This is in order to save bandwidth because we don't need the gamedata anymore.
}
}
}
}
sendCommands¶
sendCommands(bodyCommands, successMessage, errorMessage)
sendCommands` メソッドは AdminController クラスのメソッドから受け取ったコマンドをゲームに送信します。表示するすべてのメッセージを displayMessage と displayErrorMessage メソッドに転送します。
sendCommands(bodyCommands, successMessage, errorMessage) {
fetch("/api/admin/commands/game", {
method: "POST",
body: JSON.stringify(bodyCommands),
headers: {
'Content-Type': 'application/json'
}
})
.then(() => {
this.displayMessage(successMessage);
})
.catch((err) => {
this.displayErrorMessage(`Failed with error ${err} ${errorMessage}`);
});
}
setDirection¶
setDirection(cubeName, x, z)
setDirection メソッドはゲームにコマンドを送信し、プレイヤーの向きを設定します。プレイヤーの向きをクリックしたときに呼び出します。
// Changes the direction of the cube
setDirection(cubeName, x, z) {
const commands = {
id: "direction",
value: `${cubeName}:${x}:0:${z}`
};
const successMessage = `Set direction to ${cubeName}:${x}:${z}`;
const errorMessage = `to set direction to ${cubeName}:${x}:${z}`;
this.sendCommands(commands, successMessage, errorMessage);
}
changeSpeed¶
changeSpeed(cubeName, factor)
changeSpeed メソッドは、ゲームにコマンドを送信し、オブジェクトの低速化、または高速化を指示します。プレイヤーの Slower 、 Faster をクリックしたときに呼び出します。
// Changes the speed of the cube
changeSpeed(cubeName, factor) {
const commands = {
id: "speed",
value: `${cubeName}:${factor}`
};
const successMessage = `Speed changed ${cubeName}:${factor}`;
const errorMessage = `to changeSpeed ${cubeName}:${factor}`;
this.sendCommands(commands, successMessage, errorMessage);
}
reset¶
reset(cubeName)
reset メソッドは、ゲームにコマンドを送信し、オブジェクトを元の位置に戻します。プレイヤーの Reset をクリックしたときに呼び出します。
// Resets the position of the cube
reset(cubeName) {
const commands = {
id: "reset",
value: cubeName
};
const successMessage = `${cubeName} has been reset`;
const errorMessage = `to reset ${cubeName}`;
this.sendCommands(commands, successMessage, errorMessage);
}
changeCamera¶
changeCamera()
changeCamera メソッドは、ゲームにコマンドを送信し、現在のカメラを変更します。プレイヤーの Camera change ボタンをクリックしたときに呼び出します。
changeCamera() {
const commands = {
id: "camera",
value: "change"
};
const successMessage = "Camera change done";
const errorMessage = "to change the camera";
this.sendCommands(commands, successMessage, errorMessage);
}
changeScene¶
changeScene()
changeScene メソッドは、ゲームにコマンドを送信し、現在のシーンを変更します。プレイヤーの Scene change ボタンをクリックしたときに呼び出します。
changeScene() {
const commands = {
id: "scene",
value: "change"
};
const successMessage = "Scene change done";
const errorMessage = "to change the scene";
this.sendCommands(commands, successMessage, errorMessage);
}
displayMessage¶
displayMessage()
displayMessage メソッドは、実行した操作が正常に行われたことを示すメッセージを表示します。ストリームから適切にデータを取得するかどうかを確認したり、コマンド操作が成功したかどうかを確認する場合に役立ちます。
displayMessage(message) {
let messageErrorDiv = document.querySelector("#alert_error_cube");
messageErrorDiv.style.visibility = "hidden";
let messageDiv = document.querySelector("#alert_sucess_cube");
messageDiv.style.visibility = "visible";
let messageSpan = document.querySelector("#sucess_message_cube");
messageSpan.textContent = message;
}
displayErrorMessage¶
displayErrorMessage()
displayErrorMessage メソッドは、実行した操作のエラーメッセージを表示します。ストリームから適切にデータを取得できなかったことを確認したり、コマンド操作が失敗したかどうかを確認する場合に役立ちます。
displayErrorMessage(message) {
let messageDiv = document.querySelector("#alert_sucess_cube");
messageDiv.style.visibility = "hidden";
let messageErrorDiv = document.querySelector("#alert_error_cube");
messageErrorDiv.style.visibility = "visible";
let messageSpan = document.querySelector("#error_message_cube");
messageSpan.textContent = message;
}