iPhone Game Development - Chris Craft [109]
- (void) receiveData:(NSData *)remoteData fromPeer:(NSString *)peer
inSession: (GKSession *)session context:(void *)context {
int messageType;
[remoteData getBytes:&messageType length:sizeof(int)];
if (messageType == 0) {
StateData paddleData;
[remoteData getBytes:&paddleData length:sizeof(StateData)];
// Remote player should display on top so we need
// to invert the values
paddleData.paddleLocation.x = 320 - paddleData.paddleLocation.x;
paddleData.paddleLocation.y = 480 - paddleData.paddleLocation.y;
mainView.topPaddleData = paddleData;
// if we are a client we need to copy puck data sent from the host
if (mainView.connectionType == CLIENT_CONNECTION ) {
[mainView updatePuckData:paddleData];
}
[self sendData];
}
else {
EventData eventData;
[remoteData getBytes:&eventData length:sizeof(EventData)];
[mainView displayMessage:SCORE_MESSAGE forPlayer:TOP_PLAYER];
}
}
Calling hockeyTableDidScore and showPeerPicker sends out the data we just saw being received in the method receiveData from the preceeding code:
- (void)hockeyTableDidScore:(PlayerCode)playerCode {
EventData eventData;
eventData.packetType = 1;
NSData *dataPacket = [[NSData alloc] initWithBytes:&eventData
length:sizeof(EventData)];
[session sendDataToAllPeers:dataPacket withDataMode:GKSendDataReliable
error:nil];
}
- (void)sendData {
if (mainView.connectionType == HEADTOHEAD_CONNECTION) return;
StateData paddleData = mainView.bottomPaddleData;
NSData *data = [[NSData alloc] initWithBytes:&paddleData
length:sizeof(StateData)];
[session sendDataToAllPeers :data withDataMode:GKSendDataUnreliable
error:nil];
}
Establishing a connection between peers
The following code to connect peers is almost identical to that in P2P Chat. However, one very important step stands out. The method session: didReceiveConnectionRequestFromPeer is used to make the distinction that we are the client if it is called (Listing 7.7).
Listing 7.7
Using the Peer Picker to Establish a Connection Between Peers
- (void)showPeerPicker {
// allocate and setup the peer picker controller
picker = [[GKPeerPickerController alloc] init];
picker.delegate = self;
picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;
[picker show];
}
- (void)peerPickerController:(GKPeerPickerController *)picker
didSelectConnectionType:(GKPeerPickerConnectionType)type {
if(type == GKPeerPickerConnectionTypeOnline) {
}
}
- (GKSession *) peerPickerController:(GKPeerPickerController *)picker
sessionForConnectionType:(GKPeerPickerConnectionType)type {
session = [[GKSession alloc] initWithSessionID:
@”com.yourwebsite.yourapplicationname” displayName:nil
sessionMode:GKSessionModePeer];
session.delegate = self;
return session;
}
- (void)peerPickerController:(GKPeerPickerController *)picker
didConnectToPeer:(NSString *)peerID {
[self.picker dismiss];
}
- (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker {
[self.picker dismiss];
[self.rootViewController showMenu];
}
- (void)session:(GKSession *)session
didReceiveConnectionRequestFromPeer:(NSString *)peerID {
connectionType = CLIENT_CONNECTION;
mainView.connectionType = CLIENT_CONNECTION;
}
- (void)session:(GKSession *)session peer:(NSString *)peerID
didChangeState:(GKPeerConnectionState)state {
switch (state) {
case GKPeerStateConnected:
[self.session setDataReceiveHandler :self withContext:nil];
[self.picker dismiss];
[self sendData];
break;
case GKPeerStateDisconnected:
break;
}
}
@end
Analyzing Business Aspects
Building an application like AmuckPuck can be a rewarding venture, but it comes with a cost. Bringing together the many technologies can lead to a lot of