6

EDIT: I have made a clean, new project, but still can't get it working. Please download it, there is a little code to look at and probably easy for a professional or anyone remotely experience to see whats I am doing wrong. Just trying to send that integer.

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

Hi

I am trying to implement Game Center multiplayer in my iphone game and having trouble understanding the samples I have at hand in the Apple Docs and from third parties concerning sending and receiving data.

Could someone please explain the code samples in the Official Apple docs here please: http://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/GameKit_Guide/MatchesandVoice/MatchesandVoice.html#//apple_ref/doc/uid/TP40008304-CH10-SW4

Or help me figure out this sample code I was supplied with. Its a prebuilt class, made to handle all the game center tasks and a sample from it for sending and receiving data would be this:

- (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
    }
}

And receiving:

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

My big question about this code form the official docs is:

Where does PositionPacket/Packet come from? And assuming when you want to send/receive data you call them like so:

[self sendPosition];

or

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

What do I enter as the match, data and playerID?

E.g. I have an int named 'score' but is there not a special key I need to use something?

4

1 回答 1

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 对象中的东西,因为它只是一个字节桶。您可以发送原始类型,如 int 或示例中的结构,甚至 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

补充:使用提问者发布的代码,我进行了一些修改并制作了一个适用于这个基本用例的版本。 测试应用程序的工作版本通过 GameCenter 发送一个整数我对代码的质量或它对任何东西的适用性不做任何声明。99.9% 的内容不是我写的——请不要把我在这里发帖作为对其中任何内容的认可。

学到的一个教训(我不知道,所以我放在这里希望它可以帮助其他人)是你不能在模拟器中使用匹配服务。这意味着您需要两台开发配置的 iOS 设备来测试这个场景,并且对于非平凡的程序,可能需要两台开发机器同时调试这两个设备。在解决这个问题时,这个问题花费了我最多的时间。

于 2011-01-01T17:09:53.990 回答