4 minutes
[cocos2dx]photonを使ってみた – その2
お世話になります。
しゃまとんです。
photon使ってみたの続きです。
こちらではcocos2d-xでのプログラミングを行っていきます。
前回通り記事の手順にそって変更点を記載していきます。
その前までの設定はこちら
■Photonクライアントの作成
手順は全部で7つ記載されています。2,4,5が少し違います。
-
説明の通り、NetworkLogic.cpp/.hをコピーします
-
OutputListenerを削除、としていますが、メッセージを削除してしまうと、実行がうまくいかない場合にわからなくなるので、面倒ですが、CCLOGに置き換えをオススメします。
-
説明の通り、インクルード
-
NetworkLogic.cppのL4にあるappIdを自分のIDにします static const ExitGames::Common::JString appId = L"ここをIDにする";
-
FQDNの設定は不要です
-
説明の通り、インクルードします
-
説明の通り、名前空間を指定します。
これで、ビルドが通るようになります。
■アプリケーションへの組み込み
処理の概要については、変更はありません。
ソースの変更箇所については、記載されているのコード内の特殊文字がエスケープされてしまっているため、コピペしてもエラーになってしまいます。元サイトとコードが変わらない部分は、元サイトを参考にコピペしていただければ大丈夫です。
・NetworkLogic.h
array,queueをインクルード
#include <array>
#include <queue>
publicの最下位に追加
// ルームが存在するか否かを返すメソッド
bool isRoomExists(void);
// イベントを送信するメソッド
void sendEvent(nByte code, ExitGames::Common::Hashtable* eventContent);
// 自分のプレイヤー番号
int playerNr = 0;
// イベントキュー
std::queue<std::array<float, 3>> eventQueue;
・NetworkLogic.cpp
ファイルの最下部にでも追加する
bool NetworkLogic::isRoomExists(void)
{
if (mLoadBalancingClient.getRoomList().getIsEmpty()) {
return false;
}
return true;
}
void NetworkLogic::sendEvent(nByte code, ExitGames::Common::Hashtable* eventContent)
{
mLoadBalancingClient.opRaiseEvent(true, eventContent, 1, code);
}
customEventActionを下記のように上書きする
void NetworkLogic::customEventAction(int playerNr, nByte eventCode, const ExitGames::Common::Object& eventContent)
{
ExitGames::Common::Hashtable* event;
switch (eventCode) {
case 1:
event = ExitGames::Common::ValueObject<ExitGames::Common::Hashtable*>(eventContent).getDataCopy();
float x = ExitGames::Common::ValueObject<float>(event->getValue(1)).getDataCopy();
float y = ExitGames::Common::ValueObject<float>(event->getValue(2)).getDataCopy();
eventQueue.push({static_cast<float>(playerNr), x, y});
break;
}
}
createRoomReturn(), joinRoomReturn(), joinRandomRoomReturn() にlocalPlayerNrを追加
こちらは元記事のままでOKです。各functionの最下部に記入すると良いと思います。
・HelloWorldScene.h
タップ処理が漏れているので、元記事の部分と合わせて追記します。
public
virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event);
virtual void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event);
virtual void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event);
virtual void onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *unused_event);
private
virtual void update(float delta);
void addParticle(int playerNr, float x, float y);
NetworkLogic* networkLogic;
・HelloWorldScene.cpp
各タッチイベント処理を追加します。Beganには、イベント送信処理を記載します。
bool HelloWorld::onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event)
{
if (networkLogic->playerNr) {
this->addParticle(networkLogic->playerNr, touch->getLocation().x, touch->getLocation().y);
// イベント(タッチ座標)を送信
ExitGames::Common::Hashtable* eventContent = new ExitGames::Common::Hashtable();
eventContent->put<int, float>(1, touch->getLocation().x);
eventContent->put<int, float>(2, touch->getLocation().y);
networkLogic->sendEvent(1, eventContent);
}
return true;
}
void HelloWorld::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event) {
}
void HelloWorld::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event) {
}
void HelloWorld::onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *unused_event){
}
描画更新処理(update)は下記のようにします。Inputのところが少し違います。
void HelloWorld::update(float delta)
{
networkLogic->run();
switch (networkLogic->getState()) {
case STATE_CONNECTED:
case STATE_LEFT:
// ルームが存在すればジョイン、なければ作成する
if (networkLogic->isRoomExists()) {
networkLogic->setLastInput(INPUT_2);
} else {
networkLogic->setLastInput(INPUT_1);
}
break;
case STATE_DISCONNECTED:
// 接続が切れたら再度接続
networkLogic->connect();
break;
case STATE_CONNECTING:
case STATE_JOINING:
case STATE_JOINED:
case STATE_LEAVING:
case STATE_DISCONNECTING:
default:
break;
}
while (!networkLogic->eventQueue.empty()) {
std::array<float, 3> arr = networkLogic->eventQueue.front();
networkLogic->eventQueue.pop();
int playerNr = static_cast<int>(arr[0]);
float x = arr[1];
float y = arr[2];
CCLOG("%d, %f, %f", playerNr, x, y);
this->addParticle(playerNr, x, y);
}
}
パーティクル処理(addParticle)はそのまま使えるので、コピーして使いましょう。
init()にタッチ処理の設定とupdate処理の設定を追加します。
NetworkLogicの生成も少しだけ違っています。
// シングルタップリスナーを用意する
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(_swallowsTouches);
// 各イベントの割り当て
listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
listener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this);
listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
listener->onTouchCancelled = CC_CALLBACK_2(HelloWorld::onTouchCancelled, this);
// イベントディスパッチャにシングルタップ用リスナーを追加する
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
// Photonネットワーククラスのインスタンスを作成
networkLogic = new NetworkLogic();
// 毎フレームでupdateを実行させる
this->schedule(schedule_selector(HelloWorld::update));
this->scheduleUpdate();
これでビルドできれば、photon realtimeを利用した、マルチプレイヤーのサンプルが動作すると思います。
Androidでもビルドできると思いますので、やってみてください。
お疲れ様でした。
参考サイト: