首页 文章

iOS上的游戏中心 . 第一场比赛结束后如何避免发送消息?

提问于
浏览
0

这是我第一次在我的游戏中实施配对 . 我正在使用cocos2d-x v3.x框架 . 游戏是用C语言编写的,我也在利用Apple的GameKit框架(Objective-C) .

我从一开始就关注Ray Wenderlich的教程:http://tinyurl.com/j8uoftg

我想知道是否有人遇到过我遇到的同样问题 . 我将在下面展示主要问题 . 任何帮助或建议将不胜感激......

首先,我在cocos2d-x(MultiPlayer.mm)中在init上设置了matchmaking:

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,并将字符串(playerID)作为我创建的标签显示在屏幕上 . 我可以分辨出玩家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函数 . 现在当比赛断开时,玩家返回主菜单,一切都很好 . 我再次测试我的游戏,并在“第二”时间再次开始配对 . 一切都出错了 . 这是我在控制台中收到的输出(对于我玩的“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

这是另一个我用另一个问题玩的“第二”游戏 . 它将游戏状态设置为活动两次 . 此外,在我的设备上,我正在玩玩家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

我很困惑为什么会这样 . 它始终适用于第一个游戏,然后在此之后无效 . 有没有人知道这是游戏中心结束时的问题,还是在第二场比赛开始之前需要在比赛结束后在设备中存储了什么东西,或者仅仅是在设置玩家数量之前的问题游戏状态是否活跃?谢谢 .

1 回答

  • 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();
    }
    

相关问题