游戏中心 - 发送和接收数据

时间:2011-01-01 12:58:57

标签: iphone objective-c multiplayer game-center

编辑: 我做了一个干净的新项目,但仍然无法使其正常运行。请下载它,有一些代码可供查看,可能很容易让专业人士或任何人远程体验,看看我做错了什么。只是试图发送整数。

http://www.2shared.com/file/fPOCLlg5/gkTest.html

您好

我正在尝试在我的iphone游戏中实现Game Center多人游戏,并且无法理解Apple Docs和第三方有关发送和接收数据的样本。

请有人在这里解释官方Apple文档中的代码示例: http://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/GameKit_Guide/MatchesandVoice/MatchesandVoice.html#//apple_ref/doc/uid/TP40008304-CH10-SW4

或者帮我弄清楚我提供的示例代码。它是一个预先构建的类,用于处理所有游戏中心任务,以及用于发送和接收数据的样本将是:

- (void) sendPosition
{
    NSError *error;
    PositionPacket msg;
    msg.messageKind = PositionMessage;
    msg.x = currentPosition.x;
    msg.y = currentPosition.y;
    NSData *packet = [NSData dataWithBytes:&msg length:sizeof(PositionPacket)];
    [match sendDataToAllPlayers: packet withDataMode: GKMatchSendDataUnreliable error:&error];
    if (error != nil)
    {
        // handle the error
    }
}

接收:

- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID
{
    Packet *p = (Packet*)[data bytes];
    if (p.messageKind == PositionMessage)
        // handle a position message.
}

关于此代码形成官方文档的重要问题是:

PositionPacket / Packet来自哪里? 假设您想要发送/接收数据,请将其称为:

[self sendPosition];

[self match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID];

我输入什么作为匹配,数据和播放器ID?

E.g。我有一个名为'得分'的int,但是我没有需要使用的特殊键吗?

1 个答案:

答案 0 :(得分:18)

在此示例中,PositionPacket只是一个结构。然后,以下行将该结构放入NSData,这只是一个“字节桶”对象。

NSData *packet = [NSData dataWithBytes: &msg length: sizeof(PositionPacket)];

因此,如果你只想发送一个int分数,你可以使用如下所示的sendScore方法:

- (void) sendScore
{
    NSError *error;
    int myScore = self.score;
    NSData *packet = [NSData dataWithBytes:&myScore length:sizeof(myScore)];
    [match sendDataToAllPlayers: packet withDataMode: GKMatchSendDataUnreliable error: &error];
    if (error != nil)
    {
        // handle the error
    }
}

通常,您需要一个结构,以便有一些额外的信息可以让接收者知道它是什么类型的数据。在这个例子中,这就是这一行的目的:

msg.messageKind = PositionMessage;

通常,您可以发送任何您想要封装在NSData对象中的内容,因为它只是一个字节桶。您可以像示例中那样发送诸如整数或结构的原始类型,甚至是NSObject(只要它们实现NSCoding)。您应该阅读NSKeyedArchiver,NSCoding和NSData,以获取有关以这种方式发送和接收NSObject的更多信息。以下是Apple Archving上的参考文档。

至于接收,你不要调用这个方法,它会被Kit调用。这就是所谓的“委托方法”(用Cocoa说法)或“回调方法”。您可以将其视为您的应用可以异步接收的“电话”。通过实现具有签名的方法:

- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID;

...你说“我可以收到这种电话。”因此,当GameKit代表您从另一个玩家接收数据时,它会看到您希望接收这种类型的回调,然后调用该方法 - 然后由您来根据收到的内容更新您的内部应用程序状态。

继续这个例子,如果你发送了上面描述的简单的“只有整数”消息,你可以像这样实现这个方法:

- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID
{
    int* receivedScorePtr = (int*)[data bytes];
    int receivedScore = *receivedScorePtr;
    [self updateScore: received forPlayer: playerID];
}

当然,假设您有一个名为updateScore:forPlayer的方法:它会更新分数表。

您可以在此博客条目中找到有关委托和委托方法如何工作的更一般性讨论/说明:http://mohrt.blogspot.com/2010/01/cocoa-and-delegates.html

ADDED:使用提问者发布的代码,我做了一些修改并制作了一个“适用于”这个裸骨用例的版本。 Working Version of Test App To Send One Integer Through GameCenter我对代码的质量或代码的适用性没有任何说法。我没有写99.9% - 请不要把我在这里发布的内容作为对其中出现的任何内容的认可。

我吸取的一个教训(我不知道,因此我希望它能帮助其他人)是你不能在模拟器中使用Matchmaking服务。这意味着您需要两个开发配置的iOS设备才能测试这种情况,对于非平凡的程序,可能需要两台开发机器来同时调试这两个设备。在解决这个问题时,这个问题花费了我最多的时间。