Game Center - Sending and receiving data

EDIT: I did a clean, new project, but still can't get it to work. Please download it, there is a small code for viewing and probably simple for a professional or any remote user to see what I am doing wrong. Just trying to send this integer.

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

Hi

I’m trying to implement the Game Center multi-user mode in my iphone game and don’t understand what samples I have on hand in Apple Docs and from third parties regarding sending and receiving data.

Can someone please explain the code samples in the Apple White Papers 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 that was provided to me. His finished class, designed to handle all the tasks of the game center and select from it to send and receive data, will be as follows:

- (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 getting:

 - (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 is the form of white papers:

Where does PositionPacket / Packet come from? And if you want to send / receive data, you call them like this:

 [self sendPosition]; 

or

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

What should I enter as a match, data, and player ID?

eg. I have an int named 'score', but is there a special key that I need to use?

+6
source share
1 answer

In this example, PositionPacket is just a structure. The next line then places this structure in NSData, which is a byte bucket object.

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

So, if you just want to send an int score, you can have a sendScore method that looks like this:

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

As a rule, you will need a structure, so there is additional information that allows recipients to find out what data they have. In this example, this would be the goal of this line:

 msg.messageKind = PositionMessage; 

In general, you can send whatever you want to encapsulate into an NSData object, as it is just a byte bucket. You can send primitive types such as ints or structs, as in the example, or even NSObjects (provided that they implement NSCoding). You should read NSKeyedArchiver, NSCoding, and NSData for more information about sending and receiving NSObjects this way. Here is the Apple Archiving help document.

As for the reception, you do not call this method, it receives a call from you on Kit. This is what is called the "delegate method" (in Cocoa parlance) or the "callback method". You can think of it as a “phone call," which your application can receive asynchronously. Using the signature method:

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

... you say: "I can get this phone call." Therefore, when GameKit receives data on your behalf from another player, it will see that you want to receive callbacks of this type and then called by this method - then you need to update your internal state of the application based on the received one.

To continue this example, if you sent the simple “nothing but the whole” message described above, you can implement this method as follows:

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

This, of course, assumes that you have a method called updateScore: forPlayer: this will update the score table.

You can find a more general discussion / explanation of how delegates and delegation methods work in this blog post: http://mohrt.blogspot.com/2010/01/cocoa-and-delegates.html

ADDED: Using the code sent by the appellator, I made several modifications and released a version that “works” for this case using bare bones. A working version of a test application for sending one whole through GameCenter. I do not pretend to the quality of the code or its suitability for everything. I did not write 99.9% of this, please do not accept my messages here as confirmation of what appears in it.

One of the lessons (I did not know, so I hope this helps others) is that you cannot use Matchmaking with a simulator. This means that you need two iOS devices with development support to test this scenario, and probably for non-trivial programs, two development machines to debug both devices at the same time. This problem cost me the most when I figured it out.

+18
source

All Articles