まず、このページから、既にPhotonのセットアップは終了していることを前提にしています。
OpenSiv3D上でPhotonを扱うには、mak1aさんが作成したSceneMaster
クラスを使用します。ここから引っ張ってきてSceneMaster.hpp
を作成しておきましょう。
SceneMasterの説明をする前に、一つだけ重要なことがあります。それは、OpenSiv3D側の関数には全て「s3d::
」をつけるということです。そうしないと、PhotonとOpenSiv3Dの関数やクラスが衝突してしまい、大量のエラーが発生してしまいます。
では、説明に入ります。
宣言・定義は普通にSceneManagerとほとんど同じですが、引数を二つ取ります。一つ目にはPhotonのAppID
を、二つ目にはバージョンを渡しましょう。
ちなみに、SceneMasterクラスはUtility
名前空間で定義されています。 もちろん、自作の構造体を使用したgetData()
も使用可能です。
新しいシーンクラスを定義する時は、Utility::SceneMaster<class State>::Scene
を継承して、SceneManagerのようにupdate()
、draw() const
、そしてコンストラクタ(IScene
の初期化も忘れずに!)を再定義(override
)してください。
ここまでで、SceneMasterを使った実装をすると、こんな感じになります。
# include "SceneMaster.hpp"
using MyScene = Utility::SceneMaster<s3d::String>;
class Title : public MyScene::Scene {
private:
// 変数の定義など
public:
// コンストラクタ
Title(const InitData& init_) : IScene(init_)
{
}
// 更新関数
void update() override
{
}
// 描画関数(const 修飾)
void draw() const override
{
}
};
void Main()
{
MyApp manager(U"/*PhotonのAppID*/",U"1.0");
manager.add<Title>(U"Title");
while (s3d::System::Update())
{
if (!manager.update()) break;
}
}
ここでようやくPhotonとの連携に入ります。
Photonへの接続はConnect()
、切断はDisconnect()
で可能です。
これだけでも動作はすると思いますが、動いていることは実感できないと思います。これは、エンジンであらかじめ用意されている関数を再定義してデバッグ出力をさせることをすれば解決できます。
void ConnectReturn(int errorCode, const ExitGames::Common::JString& errorString, const ExitGames::Common::JString& region, const ExitGames::Common::JString& cluster);
errorCode : 終了コード。0で正常
errorString : エラーの内容(?)
region :
cluster :
概要
Photonサーバーに接続した後に呼ばれる関数です。if (errorCode)
で接続が正常に行われたかが確認できます。
概要
Photonサーバーから切断した問に呼ばれる関数です。
void JoinRandomRoomReturn(int localPlayerNr, const ExitGames::Common::Hashtable& roomProperties, const ExitGames::Common::Hashtable& playerProperties, int errorCode, const ExitGames::Common::JString& errorString);
localPlayerNr :
roomProperties : 部屋の情報(後述)
playerProperties :
errorCode : 終了コード。0で正常
errorString : エラーの内容(?)
概要
サーバーに接続後、部屋に接続した後に呼ばれる関数です。if (errorCode)
で接続が正常に行われたかが確認できます。
void CreateRoomReturn(int localPlayerNr, const ExitGames::Common::Hashtable& roomProperties, const ExitGames::Common::Hashtable& playerProperties, int errorCode, const ExitGames::Common::JString& errorString);
localPlayerNr :
roomProperties : 部屋の情報(後述)
playerProperties :
errorCode : 終了コード。0で正常
errorString : エラーの内容(?)
概要
部屋を新しく作成した後に呼ばれる関数です。if (errorCode)
で作成が正常に行われたかが確認できます。
void JoinRoomEventAction(int playerNr, const ExitGames::Common::JVector& playernrs, const ExitGames::LoadBalancing::Player& player);
playerNr :
playernrs :
player : プレイヤーの情報
概要
誰かが新しく部屋に接続してきたときに呼ばれる関数です。
playerNr :
isInactive :
概要
誰かが部屋から切断したときに呼ばれる関数です。
void CustomEventAction(int playerNr, nByte eventCode, const ExitGames::Common::Object& eventContent);
playerNr :
eventCode:イベントの種類(整数)
eventContent:イベントの情報
何らかのイベントを受け取ったときに呼ばれる関数です。
ExitGames::Common::ValueObject<ExitGames::Common::Dictionary<nByte,int32>>(eventContent).getDataCopy()
のようにすると、送られてきたイベントの情報のポインタのハッシュテーブルが得られ、.getValue(const EKeyType& key)
でインデックスkey
に格納された値のポインタが取得できます。
例
// CustomEventAction関数内
// 受け取った情報を変換
auto dic = ExitGames::Common::ValueObject<ExitGames::Common::Dictionary<nByte,int32>>(eventContent).getDataCopy();
// データの取り出し(キー:1)
auto Data = *dic.getValue(1);
id : 新しいホストのID
oldID : これまでのホストのID
概要
部屋のホストが交代したとき、つまりホストが退出したときに呼ばれる関数です。
これらにデバッグ出力などを実装してあげると、いい感じに動いてくれるはずです。
roomProperties
はExitGames::Common::Hashtable
の、部屋の情報を格納したハッシュテーブルです。これを使用することで、同じサーバー内でも複数種類の部屋の識別ができるようになります。
以下に、Photonを使用するときに必要になってくる関数をあげておきます。これらの関数に再定義は不要です。
Photonのサーバーに接続します。接続の処理が終わるとConnectReturn
関数が呼ばれます。
void CreateRoom(const ExitGames::Common::JString& roomName_, const ExitGames::Common::Hashtable& properties_, const nByte maxPlayers_);
概要
新しく部屋を作成します。
roomName_ : 作成する部屋の名前
properties_ : 部屋の情報
maxPlayers_ : プレイヤーの最大数
サーバーから切断します
概要
Photonサーバーに接続していればtrue
、接続していなければfalse
を返します。
クライアントの情報はgetClient()
で取得できます。以下に挙げているのは、そのメンバ関数です
bool opJoinRandomRoom(const Common::Hashtable& customRoomProperties=Common::Hashtable(), nByte maxPlayers=0, nByte matchmakingMode=MatchmakingMode::FILL_ROOM, const Common::JString& lobbyName=Common::JString(), nByte lobbyType=LobbyType::DEFAULT, const Common::JString& sqlLobbyFilter=Common::JString(), const Common::JVector<Common::JString>& expectedUsers=Common::JVector<Common::JString>());
概要
ランダムに部屋に接続します。見ての通り、一応何も引数を取らなくても動作はします。
customRoomProperties : 部屋の情報
maxPlayers : プレイヤーの最大数
matchmakingMode :
lobbyName :
lobbyType :
sqlLobbyFilter :
expectedUsers :
概要
クライアントのプレイヤー情報を取得します。
サーバーのタイムスタンプを取得しそうですが、SceneMasterのデフォルトだと何もしません。
bool Client::opRaiseEvent(bool reliable, const Ftype& parameters, nByte eventCode, const RaiseEventOptions& options);
概要
イベントを送ります(後述)
reliable :
parameters : 送る情報
eventCode : イベントコード
options : オプション(省略可)
イベントを送る時は、Photonで用意されている、ExitGames::Common::Dictionary<EKeyType, EValueType>
を使います。これは、EKeyType
をキー(の型)、EValueType
を要素(の型)としたハッシュテーブルとして扱います。これにデータを追加する時はput(const EKeyType& key, const EValueType& val)
を使います。引数の名前を見てもわかる通り、この関数は第一引数にキー、第二引数に要素を取ります。
そして最後、データの作成が終わり、データを送る時は、GetClient().opRaiseEvent(bool reliable, const Ftype& parameters, nByte eventCode, const RaiseEventOptions& options=RaiseEventOptions());
を使用します。第二引数に送る情報、第三引数にイベントコード(イベントの種類)を渡します。第4引数は省略可能です。(第一引数「reliable(=信頼性)」、どういう意味なのか...とりあえずtrue
を渡してください。)
少しまとめると、イベントの送信は以下のようになります。
// イベントを送信したいところ
// 送信用ハッシュテーブルの作成
ExitGames::Common::Dictionary<nByte, int32> dic;
// 情報の追加
dic.put(1, 100);
// 送信
GetClient().opRaiseEvent(true, dic, 1);
最後に、実際にPhotonを使ったサンプルへのリンクを載せておきます。