这是我第一次在我的游戏中实施配对。我正在使用cocos2d-x v3.x框架。游戏是用C ++编写的,我也在利用Apple的GameKit框架(Objective-C)。
我从一开始就关注Ray Wenderlich的教程:http://tinyurl.com/j8uoftg
我想知道是否有人遇到了我遇到的同样问题。我将在下面显示主要问题。任何帮助或建议将不胜感激......
首先,我在cocos2d-x(MultiPlayer.mm)中设置init的配对:
bool MultiPlayer::init() {
// super init first
if (!Layer::init()) {return false;}
//...
[[MultiPlayerLayer sharedManager] setUpGame];
}
MultiPlayerLayer.mm ......
-(id) init {
if( (self=[super init])) {}
return self;
}
- (void)setUpGame {
isPlayer1 = YES;
AppController *delegate = (AppController *) [UIApplication sharedApplication].delegate;
[[GCHelper sharedInstance] findMatchWithMinPlayers:2 maxPlayers:2 viewController:delegate.viewController delegate:self];
ourRandom = arc4random();
[self setGameState:kGameStateWaitingForMatch];
}
游戏中心方面的一切都很顺利。我现在被提示玩游戏,Game Center会查找玩家。找到玩家后,会通知代表该比赛可以开始(GCHelper.m):
- (void)lookupPlayers {
// a few lines later...
matchStarted = YES;
[delegate matchStarted];
}
现在我们回到MultiPlayerLayer.mm ......
- (void)matchStarted {
printf("Match started\n\n");
if (receivedRandom) {
[self setGameState:kGameStateWaitingForStart];
} else {
[self setGameState:kGameStateWaitingForRandomNumber];
}
[self sendRandomNumber];
[self tryStartGame];
}
当发送sendRandomNumber消息时,我们通过生成一个随机数(正在运行btw)来确定谁是玩家1和玩家2:
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID {
// Store away other player ID for later
if (otherPlayerID == nil) {
otherPlayerID = [playerID retain];
}
Message *message = (Message *) [data bytes];
if (message->messageType == kMessageTypeRandomNumber) {
MessageRandomNumber * messageInit = (MessageRandomNumber *) [data bytes];
printf("Received random number: %ud, ours %ud\n\n", messageInit->randomNumber, ourRandom);
bool tie = false;
if (messageInit->randomNumber == ourRandom) {
printf("TIE!\n\n");
tie = true;
ourRandom = arc4random();
[self sendRandomNumber];
} else if (ourRandom > messageInit->randomNumber) {
printf("We are player 1\n\n");
isPlayer1 = YES;
} else {
printf("We are player 2\n\n");
isPlayer1 = NO;
}
if (!tie) {
receivedRandom = YES;
if (gameState == kGameStateWaitingForRandomNumber) {
[self setGameState:kGameStateWaitingForStart];
}
[self tryStartGame];
}
}
// ...
}
然后我们尝试开始游戏。因此,如果我是玩家1并等待我们将游戏状态设置为活动状态,请设置字符串(获取其他玩家ID)并向另一方发送消息以开始游戏:
- (void)tryStartGame {
if (isPlayer1 && gameState == kGameStateWaitingForStart) {
[self setGameState:kGameStateActive];
[self sendGameBegin];
[self setupStringsWithOtherPlayerId:otherPlayerID];
}
}
当发送sendGameBegin消息时,我们在另一侧将状态设置为活动并设置播放器ID字符串:
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID {
// Store away other player ID for later
if (otherPlayerID == nil) {
otherPlayerID = [playerID retain];
}
Message *message = (Message *) [data bytes];
if (message->messageType == kMessageTypeRandomNumber) {
// ...
} else if (message->messageType == kMessageTypeGameBegin) {
[self setGameState:kGameStateActive];
[self setupStringsWithOtherPlayerId:playerID];
}
// ...
}
好了,现在我们又回到了cocos2d-x类(MultiPlayer.mm)。在我设置多人游戏之前,我在这堂课内打了this->scheduleUpdate();
。每帧调用update方法并检查游戏状态是否处于活动状态:
// game loop
void MultiPlayer::update(float fDelta) {
if ([[MultiPlayerLayer sharedManager] gameStateIsActive] && (!namesSet)) {
// set names
player1ID->setString([[[MultiPlayerLayer sharedManager] getPlayer1ID] UTF8String]);
player1ID->setPosition(Vec2((player1ID->getContentSize().width / 2) + origin.x, heartPosY - 50));
player1ID->setColor(Color3B::BLACK);
player2ID->setString([[[MultiPlayerLayer sharedManager] getPlayer2ID] UTF8String]);
player2ID->setPosition(Vec2((visibleSize.width + origin.x) - (player2ID->getContentSize().width / 2), heartPosY - 50));
player2ID->setColor(Color3B::BLACK);
namesSet = true;
}
// ...
}
我的其余代码似乎工作正常。当我在两个设备上测试我的游戏时,第一个配对游戏运行正常。选择播放器1和播放器2,并将字符串(播放器ID' s)显示在屏幕上作为我创建的标签。我可以分辨出玩家1和玩家2之间的区别,并且消息发送工作正常。当游戏结束时,我显示获胜者的玩家ID,然后等待输入。当接收到输入(点击屏幕)时,在播放器的设备上断开匹配。因此,例如,如果播放器1首先点击屏幕,则播放器1断开连接并返回主菜单。在他们选择与比赛断开连接之前,玩家2仍将在游戏中。这是我在控制台中收到的输出(对于我玩的第一个游戏):
Setting up game...
Waiting for match
Received random number: 2119557985d, ours 1863796654d
We are player 2
Match started
Waiting for start
Active
plugin com.apple.GameCenterUI.GameCenterMatchmakerExtension invalidated
Suspended
Waiting for game over
Match ended
Done
这是MultiPlayer.mm中等待结束匹配的方法:
void MultiPlayer::waitForGameOver(float dt) {
// wait for user interaction
if (userDefault->getBoolForKey("gameOverResults-MultiPlayer")) {
// unschedule
this->unschedule(schedule_selector(MultiPlayer::waitForGameOver));
// end game, return to play menu
[[MultiPlayerLayer sharedManager] matchEnded];
}
}
在MultiPlayerLayer.mm ......
- (void)matchEnded {
[self setGameState:kGameStateDone];
[[GCHelper sharedInstance].match disconnect];
[GCHelper sharedInstance].match = nil;
// this function replaces the scene in cocos2d-x
// and returns the player to the main menu
goBack();
}
更多信息:我正在使用extern" C"对于我在MultiPlayerLayer.mm中调用的C ++函数。现在当比赛断开时,玩家返回主菜单,一切都很好。我再次测试我的游戏并再次为#34; SECOND"时间。一切都出错了。这是我在控制台中收到的输出(对于" SECOND"我玩的游戏):
Setting up game...
Waiting for match
Received random number: 1726927477d, ours 1604807545d
We are player 2
Active
Match started
Waiting for start
plugin com.apple.GameCenterUI.GameCenterMatchmakerExtension invalidated
Game is not active yet. // <- I am unable to play because the game is not active
这是另一个&#34; SECOND&#34;我玩不同问题的游戏。它将游戏状态设置为活动两次。此外,在我的设备上,我正在玩玩家1,在我的第二个测试设备上,我正在玩玩家1:
Setting up game...
Waiting for match
Received random number: 588896416d, ours 3091892431d
We are player 1
Active
Match started
Waiting for start
Active
plugin com.apple.GameCenterUI.GameCenterMatchmakerExtension invalidated
我很困惑为什么会这样。它总是在第一场比赛中起作用,之后它就不起作用了。有没有人知道这是游戏中心结束时的问题,还是在第二场比赛开始之前需要释放比赛结束后存在于设备中的东西,或者仅仅是设置问题游戏状态激活前的玩家数量?感谢。
答案 0 :(得分:0)
终于解决了:
- (void)matchEnded {
[self setGameState:kGameStateDone];
[[GCHelper sharedInstance].match disconnect];
[GCHelper sharedInstance].match = nil;
// release
[otherPlayerID release];
otherPlayerID = nil;
isPlayer1 = NO;
receivedRandom = NO;
// this function replaces the scene in cocos2d-x
// and returns the player to the main menu
goBack();
}