iPhone Game Development - Chris Craft [106]
bottomPaddleData.puckRotation +=
(bottomPaddleData.puckVelocity.x * 0.005);
}
else {
[self didScore:BOTTOM_PLAYER];
}
}
if ((bottomPaddleData.puckLocation.y - PUCK_RADIUS) < 0) {
if ((bottomPaddleData.puckLocation.x < GOAL_START)
| (bottomPaddleData.puckLocation.x > GOAL_END)) {
bottomPaddleData.puckVelocity.y = -bottomPaddleData.puckVelocity.y;
bottomPaddleData.puckLocation.y = PUCK_RADIUS;
bottomPaddleData.puckRotation +=
-(bottomPaddleData.puckVelocity.x * 0.005);
}
else {
[self didScore:TOP_PLAYER];
}
}
}
}
Separating logic for host, client, and head-to-head
You may have noticed the connectionType flag in some of the previous code listings. This is used to indicate the connection type of the application. In its current version, the application can be connected as follows:
Head-to-head
Peer-to-peer host
Peer-to-peer client
In a head-to-head connection, updates to the puck and paddles are all handled and maintained on a single device. Also, Multi-Touch has to be enabled since two touches (one for each paddle) are observed at the same time. The top player is only updated locally in head-to-head connections (Listing 7.4).
Listing 7.4
Change the Position of the Paddles Based on the Last Touch Location
- (void)updatePaddlesWithTouches:(NSSet *)touches {
NSArray *allTouches = [touches allObjects];
int count = [allTouches count];
if (count > 0) {
for (int i=0; i CGPoint touchPoint = [touch locationInView:self]; // if the touchPoint is out of bounds we need to correct it correctTouchPoint(&touchPoint); if (connectionType == HEADTOHEAD_CONNECTION & touchPoint.y < MAX_TOP_PLAYER_Y) { topPaddleData.paddleVelocity.x = touchPoint.x - topPaddleData.paddleLocation.x ; topPaddleData.paddleVelocity.y = touchPoint.y - topPaddleData.paddleLocation.y; topPaddleData.paddleLocation.x = touchPoint.x; topPaddleData.paddleLocation.y = touchPoint.y; } else if (touchPoint.y > MIN_BOTTOM_PLAYER_Y) { bottomPaddleData.paddleVelocity.x = touchPoint.x - bottomPaddleData.paddleLocation.x; bottomPaddleData.paddleVelocity.y = touchPoint.y - bottomPaddleData.paddleLocation.y; bottomPaddleData.paddleLocation.x = touchPoint.x; bottomPaddleData.paddleLocation.y = touchPoint.y; } } } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self updatePaddlesWithTouches:touches]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { [self updatePaddlesWithTouches:touches]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [self updatePaddlesWithTouches:touches]; } Another important thing to notice in the method updateView (repeated below) is that updatePuck is not called for client connections: - (void) updateView { if (connectionType != CLIENT_CONNECTION) { [self updatePuck]; } ... } In a peer-to-peer client connection, the top player is updated whenever data is received remotely from the method updatePuckData: - (void)updatePuckData:(StateData)puckData { bottomPaddleData.puckLocation.x = 320 - puckData.puckLocation.x; bottomPaddleData.puckLocation.y = 480 - puckData.puckLocation.y; bottomPaddleData.puckRotation = puckData.puckRotation; bottomPaddleData.puckVelocity.x = 320 - puckData.puckVelocity.x; bottomPaddleData.puckVelocity.y = 480 - puckData.puckVelocity.y; } The previous method ultimately receives its data from a message sent from a peer-to-peer host. This way puck physics are calculated only on one of the two devices. The sendData and receiveData methods from HockeyViewController implement this functionality (Listing 7.5). Listing 7.5 Using Game Kit Methods to Send and Receive Data Between Two Devices - (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];