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

Jos*_*ane 6 iphone multiplayer objective-c 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
    }
}
Run Code Online (Sandbox Code Playgroud)

接收:

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

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

哪里PositionPacket/ Packet从何而来?假设您想要发送/接收数据,您可以这样称呼它们:

[self sendPosition];
Run Code Online (Sandbox Code Playgroud)

要么

[self match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID];
Run Code Online (Sandbox Code Playgroud)

我输入什么作为匹配,数据和玩家ID?

例如,我有一个名为'score'的int,但是我没有需要使用特殊键吗?

ipm*_*mcc 18

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

NSData *packet = [NSData dataWithBytes: &msg length: sizeof(PositionPacket)];
Run Code Online (Sandbox Code Playgroud)

因此,如果您只想发送一个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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

msg.messageKind = PositionMessage;
Run Code Online (Sandbox Code Playgroud)

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

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

- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID;
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

添加:使用提问者发布的代码,我做了一些修改,并为这个裸骨用例生成了一个"有效"的版本. 测试应用程序的工作版本通过GameCenter发送一个整数我没有声明代码的质量,或者它的适用性,以及任何东西.我没有写99.9% - 请不要把我在这里发布的内容作为对其中出现的任何内容的认可.

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

  • 在我的"真正"工作之后,今晚我会试一试.:) (3认同)
  • 我编辑了我的答案,包括一个适合我的项目版本.代码的主要问题是:1)获得匹配时你还需要设置`myMatch.delegate = self;`2)你需要在`sharedMatchmaker`中添加`inviteHandler` - 参见[http:// bit .ly/fBsfOS].我在viewDidLoad中添加了它(在错误的位置,但是......)3)养成指向nil的指针的习惯,如:`NSError*error = nil;`垃圾值导致sendScore认为在那里有错误不是.在这些变化之后,它对我有用.如果您遇到麻烦,请告诉我. (2认同)